Skip to content

Commit

Permalink
Merge pull request #120 from pliablepixels/match-history
Browse files Browse the repository at this point in the history
Ignore objects matched in previous alarm
  • Loading branch information
pliablepixels committed May 31, 2019
2 parents 885187d + 5921adb commit 91cbcd2
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 24 deletions.
54 changes: 39 additions & 15 deletions hook/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import re
import imutils
import ssl
import pickle
#import hashlib

import zmes_hook_helpers.log as log
Expand Down Expand Up @@ -175,11 +176,15 @@ def append_suffix(filename, token):
match = match + [cls]

# now filter these with polygon areas
#g.logger.debug ("INTERIM BOX = {} {}".format(b,l))
b, l, c = img.processIntersection(b, l, c, match)


if b:
bbox.append(b)
label.append(l)
conf.append(c)
#g.logger.debug ('ADDING {} and {}'.format(b,l))
bbox.extend(b)
label.extend(l)
conf.extend(c)
classes.append(m.get_classes())
g.logger.debug('labels found: {}'.format(l))
g.logger.debug ('match found in {}, breaking file loop...'.format(filename))
Expand All @@ -196,6 +201,8 @@ def append_suffix(filename, token):

# all models loops, all files looped

#g.logger.debug ('FINAL LIST={} AND {}'.format(bbox,label))

if not matched_file:
g.logger.debug('No patterns found using any models in all files')

Expand All @@ -208,9 +215,10 @@ def append_suffix(filename, token):
image = image2
bbox_f = filename2_bbox

for idx, b in enumerate(bbox):
out = img.draw_bbox(image, b, label[idx], classes[idx], conf[idx], None, False)
image = out
#for idx, b in enumerate(bbox):
#g.logger.debug ("DRAWING {}".format(b))
out = img.draw_bbox(image, bbox, label, classes, conf, None, False)
image = out

if g.config['write_debug_image'] == 'yes':
g.logger.debug('Writing out debug bounding box image to {}...'.format(bbox_f))
Expand All @@ -224,6 +232,21 @@ def append_suffix(filename, token):
g.logger.error('Could not write image to ZoneMinder as eventpath not present')
# Now create prediction string

if g.config['match_past_detections'] == 'yes':
# point detections to post processed data set
g.logger.debug ('Removing matches to past detections')
bbox_t, label_t, conf_t = img.processPastDetection(bbox, label, conf, args['monitorid'])
# save current objects for future comparisons
g.logger.debug ('Saving detections for monitor {} for future match'.format(args['monitorid']))
mon_file = g.config['image_path'] + '/monitor-'+args['monitorid'] +'-data.pkl'
f = open(mon_file, "wb")
pickle.dump(bbox,f)
pickle.dump(label,f)
pickle.dump(conf,f)
bbox = bbox_t
label = label_t
conf = conf_t

if g.config['frame_id'] == 'bestmatch':
if matched_file == filename1:
prefix = '[a] ' # we will first analyze alarm
Expand All @@ -233,15 +256,16 @@ def append_suffix(filename, token):
prefix = '[x] '

pred = ''
for idx, la in enumerate(label):
seen = {}
for l, c in zip(la, conf[idx]):
if l not in seen:
if g.config['show_percent'] == 'no':
pred = pred + l + ','
else:
pred = pred + l + ':{:.0%}'.format(c) + ' '
seen[l] = 1
seen = {}
#g.logger.debug ('CONFIDENCE ARRAY:{}'.format(conf))
for idx, l in enumerate(label):
if l not in seen:
if g.config['show_percent'] == 'no':
pred = pred + l + ','
else:
pred = pred + l + ':{:.0%}'.format(conf[idx]) + ' '
seen[l]=1

if pred != '':
pred = pred.rstrip(',')
pred = prefix + 'detected:' + pred
Expand Down
7 changes: 7 additions & 0 deletions hook/objectconfig.ini
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ allow_self_signed=yes
yolo_type=full
#yolo_type=tiny

# if yes, last detection will be stored for monitors
# and bounding boxes that match, along with labels
# will be discarded for new detections. This may be helpful
# in getting rid of static objects that get detected
# due to some motion.
match_past_detections = yes

# sequence of models to run for detection
models=yolo,face
# if all, then we will loop through all models
Expand Down
2 changes: 1 addition & 1 deletion hook/zmes_hook_helpers/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__version__ = "3.2.9"
__version__ = "3.3.0"
VERSION=__version__
5 changes: 5 additions & 0 deletions hook/zmes_hook_helpers/common_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@
'default': '.*',
'type': 'string'
},
'match_past_detections':{
'section': 'general',
'default': 'no',
'type': 'string'
},

'frame_id':{
'section': 'general',
Expand Down
2 changes: 1 addition & 1 deletion hook/zmes_hook_helpers/face.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,6 @@ def detect(self, image):
# convert to left top, right bottom
matched_face_names.append('face')
matched_face_rects.append((loc[3], loc[0], loc[1], loc[2]))
conf.append('1')
conf.append(1)
#rects = self._rescale_rects(matched_face_rects)
return matched_face_rects, matched_face_names, conf
2 changes: 1 addition & 1 deletion hook/zmes_hook_helpers/hog.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ def detect(self, image):
for i in r:
labels.append('person')
classes.append('person')
conf.append('1')
conf.append(1)

return r, labels, conf
68 changes: 66 additions & 2 deletions hook/zmes_hook_helpers/image_manip.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from shapely.geometry import Polygon
import cv2
import numpy as np
import pickle

# Generic image related algorithms

Expand All @@ -11,16 +12,74 @@
# it also makes sure only patterns specified in detect_pattern are drawn


def processPastDetection (bbox, label, conf,mid):
mon_file = g.config['image_path'] + '/monitor-'+mid +'-data.pkl'
g.logger.debug ('trying to load '+mon_file)
try:
fh = open(mon_file, "rb")
saved_bs = pickle.load(fh)
saved_ls = pickle.load(fh)
saved_cs = pickle.load(fh)
except FileNotFoundError:
g.logger.debug ('No history data file found for monitor {}'.format(mid))
return bbox, label, conf
# load past detection


#g.logger.debug ('loaded past: bbox={}, labels={}'.format(saved_bs, saved_ls));

new_label = []
new_bbox = []
new_conf = []

for idx, b in enumerate(bbox):
# iterate list of detections
old_b = b
it = iter(b)
b = list(zip(it,it))

b.insert(1, (b[1][0], b[0][1]))
b.insert(3, (b[0][0], b[1][1]))
#g.logger.debug ("Past detection: {}@{}".format(saved_ls[idx],b))
#g.logger.debug ('BOBK={}'.format(b))
obj = Polygon(b)
foundMatch = False
for saved_idx, saved_b in enumerate(saved_bs):
# compare current detection element with saved list from file
if saved_ls[saved_idx] != label[idx]: continue
it = iter(saved_b)
saved_b = list(zip(it,it))
saved_b.insert(1,
(saved_b[1][0], saved_b[0][1]))
saved_b.insert(3, (saved_b[0][0], saved_b[1][1]))
saved_obj = Polygon(saved_b)
if obj.equals(saved_obj):
g.logger.debug ('past detection {}@{} exactly matches {}@{} removing'.format(saved_ls[saved_idx],saved_b, label[idx],b))
foundMatch = True
break
if obj.almost_equals(saved_obj):
g.logger.debug ('past detection {}@{} approximately matches {}@{} removing'.format(saved_ls[saved_idx],saved_b, label[idx],b))
foundMatch = True
break
if not foundMatch:
new_bbox.append(old_b)
new_label.append(label[idx])
new_conf.append(conf[idx])

return new_bbox, new_label, new_conf


def processIntersection(bbox, label, conf, match):

# bbox is the set of bounding boxes
# labels are set of corresponding object names
# conf are set of confidence scores (for hog and face this is set to 1)
# match contains the list of labels that will be allowed based on detect_pattern

#g.logger.debug ("PROCESS INTERSECTION {} AND {}".format(bbox,label))
new_label = []
new_bbox = []
new_conf = []
#g.logger.debug ("INTERSECTION GOT: {}".format(bbox))

for idx, b in enumerate(bbox):
doesIntersect = False
Expand All @@ -31,8 +90,10 @@ def processIntersection(bbox, label, conf, match):
old_b = b
it = iter(b)
b = list(zip(it, it))
#g.logger.debug ("BB={}".format(b))
b.insert(1, (b[1][0], b[0][1]))
b.insert(3, (b[0][0], b[1][1]))
g.logger.debug ("polygon in process={}".format(b))
obj = Polygon(b)

for p in g.polygons:
Expand All @@ -52,13 +113,15 @@ def processIntersection(bbox, label, conf, match):
else: # of poly intersects
g.logger.debug('object:{} at {} does not fall into any polygons, removing...'
.format(label[idx], obj))
#g.logger.debug ("INTERSECTION RETURNING: {} {}".format(new_bbox, new_label))
return new_bbox, new_label, new_conf


# draws bounding boxes of identified objects and polygons

def draw_bbox(img, bbox, labels, classes, confidence, color=None, write_conf=False):

# g.logger.debug ("DRAW BBOX={} LAB={}".format(bbox,labels))
slate_colors = [
(39, 174, 96),
(142, 68, 173),
Expand All @@ -82,11 +145,12 @@ def draw_bbox(img, bbox, labels, classes, confidence, color=None, write_conf=Fal

arr_len = len(bgr_slate_colors)
for i, label in enumerate(labels):
#g.logger.debug ('drawing box for: {}'.format(label))
#=g.logger.debug ('drawing box for: {}'.format(label))
color = bgr_slate_colors[i % arr_len]
if write_conf and confidence:
label += ' ' + str(format(confidence[i] * 100, '.2f')) + '%'
# draw bounding box around object
#g.logger.debug ("DRAWING RECT={},{} {},{}".format(bbox[i][0], bbox[i][1],bbox[i][2], bbox[i][3]))
cv2.rectangle(img, (bbox[i][0], bbox[i][1]), (bbox[i][2], bbox[i][3]), color, 2)

# write text
Expand Down
4 changes: 2 additions & 2 deletions hook/zmes_hook_helpers/yolo.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,9 @@ def detect(self, image):
y = box[1]
w = box[2]
h = box[3]
bbox.append([int(round(x)), int(round(y)), int(round(x + w)), int(round(y + h))])
bbox.append( [int(round(x)), int(round(y)), int(round(x + w)), int(round(y + h))])
label.append(str(self.classes[class_ids[i]]))
conf.append(confidences[i])

#g.logger.debug ("YOLO bbox={}".format(bbox))
return bbox, label, conf

4 changes: 2 additions & 2 deletions zmeventnotification.pl
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
# ==========================================================================


my $app_version="3.7";
my $app_version="3.8";

# ==========================================================================
#
Expand Down Expand Up @@ -766,8 +766,8 @@ sub validateZmAuth
my $saved_pass = $state->{Password};
# perl bcrypt libs can't handle $2b$ or $2y$
$saved_pass =~ s/^\$2.\$/\$2a\$/;
my $new_hash = Crypt::Eksblowfish::Bcrypt::bcrypt($p, $saved_pass);
printDebug ("Comparing using bcrypt $new_hash to $saved_pass");
my $new_hash = Crypt::Eksblowfish::Bcrypt::bcrypt($p, $saved_pass);
return $new_hash eq $saved_pass;
}
}
Expand Down

0 comments on commit 91cbcd2

Please sign in to comment.