class lineFilter(VideoReaderProgram): # class instance for 2 counting gates gate = None # line computation results greenRate = 0 redRate = 0 # crosses counts ingoing = 0 outgoing = 0 # when green/red rate if over threshold, first/second char passes to G/R # third flag is i or o indicating ingoing/outgoing person # __ means "nothing" # G_ = someone begins to cut in "in" direction -> G_ , i # then, we must have GR, then _R, then __ back -> +1 in # any other combination means the person went back, or there was several persons crossing in opposite directions # _R = someone begins to cut in "out" direction -> _R, o # then, we must have GR, then G_, then __ back -> +1 out lineState = "__" dirState = "_" # try to summarize various possibilities in a matrix stateMachine = { # "line,dir,newState" -> (new dirState, counter to update) (0=none, -1 = out, +1 = in) "__,_,G_": ("i", 0), # start cross in "__,_,_R": ("o", 0), # start cross out "__,_,GR": ("?", 0), # start cross quickly => can't say in which direction "G_,i,__": ("_", 0), # someone went back just before the door "G_,i,GR": ("i", 0), # continue to cross "in" "G_,i,_R": ("i", 1), # a mouse crosses in ? "GR,i,G_": ("i", 0), # someone went back while thru the door "GR,i,_R": ("i", 1), # someone ending to cross in "GR,i,__": ("_", 1), # someone ending to cross in quickly "_R,i,__": ("_", 0), # someone ended to cross in (already counted) "_R,o,__": ("_", 0), # someone went back just before the door "_R,o,GR": ("o", 0), # continue to cross "out" "_R,o,G_": ("o",-1), # a mouse crosses out ? "GR,o,_R": ("o", 0), # someone went back while thru the door "GR,o,G_": ("o",-1), # someone ending to cross out "GR,o,__": ("_",-1), # someone ending to cross out quickly "G_,o,__": ("_", 0), # someone ended to cross out (already counted) # approximation : if someone crosses the 2 lines quick then go back, we count it as crossing "GR,?,G_": ("o",-1), # started cross quickly, but we detected he's going out "GR,?,_R": ("i", 1), # started cross quickly, but we detected he's going in } # any color of any pixel varying of more than this value is considered as covering background colorThreshold = 50 # TODO : add argument # if ratio of "covering" pixels in a line is more than this threshold, we consider # than someone is crossing it lineThreshold = 10 # TODO : add argument # handle mouse to redraw red and green lines drawing = None def mouseHandler(self, event, x, y, flags, param): if event == cv2.EVENT_MBUTTONUP: self.intersectPix(x, y) elif event == cv2.EVENT_LBUTTONDOWN: self.gate.green.setStart(x, y) self.drawing = 'g' elif event == cv2.EVENT_LBUTTONUP: self.gate.green.setEnd(x, y) self.drawing = None print self.gate.green elif event == cv2.EVENT_RBUTTONDOWN: self.gate.red.setStart(x, y) self.drawing = 'r' elif event == cv2.EVENT_RBUTTONUP: self.gate.red.setEnd(x, y) self.drawing = None print self.gate.red elif event == cv2.EVENT_MOUSEMOVE and self.drawing is not None: if self.drawing == 'g': self.gate.green.setEnd(x, y) else: self.gate.red.setEnd(x, y) else: return toDraw = self.gate.background.copy() self.gate.redraw(toDraw) cv2.imshow("output", toDraw) def initialize(self): self.gate = CountingGate(self.greenLine, self.redLine) def firstFrameCallback(self, caller, frame): self.gate.setBackground(frame.copy()) self.gate.redraw(frame) caller.legendLine = 2 cv2.setMouseCallback("output", self.mouseHandler) def intersectPix(x, y): delta = max(abs(numpy.array(bg[y][x], dtype=numpy.int16) - numpy.array(frame[y][x], dtype=numpy.int16))) print x, "x", y, ":", delta def infoCallback(self, caller, stepNumber, step): return "{0:05d} : {1:3.0f} {2:3.0f} / i={3} o={4}".format( caller.frameNumber, self.greenRate, self.redRate, self.ingoing, self.outgoing) def inputFrameCallback(self, caller, stepNumber, step): """ TODO * enumerer les points des 2 lignes dans 2 listes - diff entre 1ere frame et courante comme dans diffThreshold - parcourir chaque point des lignes : en deduire des listes de segments (paires d'index) - afficher les segments obtenus (en blanc) + marquer les "taches" - les historiser + comparer l'historique des 2 lignes comment reperer les croisements : - en mode horizontal (vue dessus) ? proximite des centres ? - en mode vertical (vue de cote) ? compter combien de taches il y a entre les lignes en partant du principe qu'il y en a 0 au depart ? a creuser sur des exemples ... """ self.greenRate, self.redRate = self.gate.intersect(step['input'], self.colorThreshold) newState = ( ("G" if self.greenRate > self.lineThreshold else "_") + ("R" if self.redRate > self.lineThreshold else "_") ) if self.lineState != newState: testCase = self.lineState + "," + self.dirState + "," + newState if self.stateMachine.has_key(testCase): (self.dirState, action) = self.stateMachine[testCase] if action == 1: self.ingoing += 1 elif action == -1: self.outgoing += 1 else: print "Unknown state", testCase self.lineState = newState self.gate.redraw(step['output'])
def initialize(self): self.gate = CountingGate(self.greenLine, self.redLine)