def __refresh_poly(self): self.polys_out = cv.ApproxPoly(self.contours, self.a_storage, cv.CV_POLY_APPROX_DP, self.__poly_acc / 100.0, -1) # Prints a count of the number of polygons and points in the picture thingy con = self.polys_out self.pointc = 0 self.polyc = 0 while not con == None: self.pointc += len(con) self.polyc += 1 con = con.h_next() print '\n%d polygons'%self.polyc print '%d points'%self.pointc cv.Set(self.contour_out, cv.ScalarAll(255)) cv.DrawContours(self.contour_out, self.polys_out, cv.Scalar(0, 0, 0), cv.Scalar(0, 0, 0), 99) cv.ShowImage('Contours', self.contour_out)
def getPupil(frame): pupilImg = cv.CreateImage(cv.GetSize(frame), 8, 1) cv.InRangeS(frame, (30, 30, 30), (80, 80, 80), pupilImg) contours = cv.FindContours(pupilImg, cv.CreateMemStorage(0), mode=cv.CV_RETR_EXTERNAL) del pupilImg pupilImg = cv.CloneImage(frame) while contours: moments = cv.Moments(contours) area = cv.GetCentralMoment(moments, 0, 0) if (area > 50): pupilArea = area x = cv.GetSpatialMoment(moments, 1, 0) / area y = cv.GetSpatialMoment(moments, 0, 1) / area pupil = contours global centroid centroid = (int(x), int(y)) cv.DrawContours(pupilImg, pupil, (0, 0, 0), (0, 0, 0), 2, cv.CV_FILLED) break contours = contours.h_next() return (pupilImg)
def segment(self, cv_source_image): self.get_tracker().flush() hue = self.pre_process_source(cv_source_image) size = (hue.width, hue.height) cv_out = cv.CreateImage(size, 8, 3) cv.Zero(cv_out) bounds = self.find_color_bounds(hue) for bound in bounds: (tmp1d, avg_hue) = self.extract_hue_channel(hue, bound) contours = cv.FindContours(tmp1d, cv.CreateMemStorage(), cv.CV_RETR_CCOMP) while contours: cSize = abs(cv.ContourArea(contours)) if cSize < self.min_contour_size: contours = contours.h_next() continue (_, center, radius) = cv.MinEnclosingCircle(contours) center = (int(center[0]), int(center[1])) id = self.get_tracker().add(center, radius, avg_hue, size) cv.DrawContours(cv_out, contours, cv.CV_RGB(255, 255, avg_hue), cv.CV_RGB(255, 255, avg_hue), 1, -1, 1) contours = contours.h_next() #font = cv.InitFont(cv.CV_FONT_HERSHEY_PLAIN, 0.8, 1, 0, 1, 4); #cv.Circle( cv_out, (x,y), int(radius), cv.CV_RGB(255,255,int(avg_hue)), 1 ); #cv.PutText( cv_out, "%d:%d"%(id, avg_hue), (x,y), font, cv.CV_RGB(255,255,150)); return cv_out
def getAnnotatedImage(self, showRects=True, showContours=False, showConvexHulls=False, showFlow=False): ''' @return: the annotation image with selected objects drawn upon it. showFlow will only work if the BG subtraction method was MCFD. @note: You must call detect() prior to getAnnotatedImage() to see updated results. ''' rects = self.getRects() outImg = self._annotateImg.copy( ) #deep copy, so can freely modify the copy if outImg == None: return None #draw optical flow information in white if showFlow and (self._method == pv.BG_SUBTRACT_MCFD): flow = self._bgSubtract.getOpticalFlow() flow.annotateFrame(outImg) if showContours or showConvexHulls: cvimg = outImg.asOpenCV() #draw contours in green if showContours: cv.DrawContours(cvimg, self._contours, cv.RGB(0, 255, 0), cv.RGB(255, 0, 0), 2) #draw hulls in cyan if showConvexHulls: cv.PolyLine(cvimg, self._convexHulls, True, cv.RGB(0, 255, 255)) #draw bounding box in yellow if showRects: for r in rects: outImg.annotateRect(r, "yellow") return outImg
def find_regions(self): #Create a copy image of thresholds then find contours on that image storage = cv.CreateMemStorage(0) storage1 = cv.CreateMemStorage(0) copy = cv.CreateImage(self.size, 8, 1) cv.Copy(self.threshold, copy) contours = cv.FindContours(copy, storage, cv.CV_RETR_EXTERNAL,\ cv.CV_CHAIN_APPROX_SIMPLE) #Find the largest contour if len(contours) > 0: biggest = contours biggestArea = cv.ContourArea(contours) while contours != None: nextArea = cv.ContourArea(contours) if biggestArea < nextArea: biggest = contours biggestArea = nextArea contours = contours.h_next() #print biggest # after_biggest = biggest.h_next() # after_biggest = None #Get a bounding rectangle for the largest contour br = cv.BoundingRect(biggest, update=0) #self.tree = cv.CreateContourTree(biggest, storage1, 0) #print self.contour_tree #Find the middle of it circle_x = br[0] + br[2] / 2 circle_y = br[1] + br[3] / 2 #Create a blob message and publish it. # blob = Blob( br[0], br[1], br[2], br[3], circle_x, circle_y) # self.publish(blob) #Find the coordinates for each corner of the box box_tl = (br[0], br[1]) box_tr = (br[0] + br[2], br[1]) box_bl = (br[0], br[1] + br[3]) box_br = (br[0] + br[2], br[1] + br[3]) #Draw the box cv.PolyLine(self.image,[[box_tl, box_bl, box_br, box_tr]],\ 1, cv.RGB(255, 0, 0)) #Draw the circle cv.Circle(self.image,(circle_x, circle_y), 10, cv.RGB(255, 0, 0),\ thickness=1, lineType=8, shift=0) #Draw the contours cv.DrawContours(self.image, biggest, cv.RGB(255, 255, 255), cv.RGB(0, 255, 0), 1, thickness=2, lineType=8, offset=(0, 0))
# Apply the Memory Storage for Contour Image. pContourImg = cv.CreateImage(cv.GetSize(pImg), cv.IPL_DEPTH_8U, 3) # copy source image and convert it to BGR image cv.CvtColor(pImg, pContourImg, cv.CV_GRAY2BGR) # Find contours contour = cv.FindContours(pImg, storage, cv.CV_RETR_CCOMP, cv.CV_CHAIN_APPROX_SIMPLE) # Draw the Contours cv.DrawContours(pContourImg, contour, cv.CV_RGB(255, 0, 0), cv.CV_RGB(0, 0, 255), 2, 2, 8) # Show Image cv.ShowImage("contour", pContourImg) cv.WaitKey(0) # Destory Windows cv.DestroyWindow("src") cv.DestroyWindow("contour") # Python2.7-OpenCV2.2 will Release Image MemStorage Automatically #cv.ReleaseImage( pImg ); #cv.ReleaseImage( pContourImg );
def mainLoop(): input_video_fn = get_input_video_filename() print 'input video filename:', input_video_fn # Setting up the window objects and environment proc_win_name = "Processing window" cam_win_name = "Capture from camera" proc_win = cv.NamedWindow(proc_win_name, 1) cam_win = cv.NamedWindow(cam_win_name, 1) if input_video_fn: cam = cv.CaptureFromFile(input_video_fn) else: cam = cv.CaptureFromCAM(0) cv.SetMouseCallback(proc_win_name, handle_mouse) cv.SetMouseCallback(cam_win_name, handle_mouse) msdelay = 3 initHueThreshold = 42 initIntensityThreshold = 191 skin_detector = skin.SkinDetector() skin_detector.setHueThreshold(initHueThreshold) skin_detector.setIntensityThreshold(initIntensityThreshold) cv.CreateTrackbar('hueThreshold', proc_win_name, initHueThreshold, 255, skin_detector.setHueThreshold) cv.CreateTrackbar('intensityThreshold', proc_win_name, initIntensityThreshold, 255, skin_detector.setIntensityThreshold) session = ImageProcessSession(skin_detector) ga = gesture.GestureAnalyzer() grammar = Grammar() gfn = get_grammar_filename() if not gfn: print 'usage: python GestureLock.py -g grammar_file.gmr' exit(0) answer_grammer = read_grammar(gfn) im_orig_writer = ImageWriter(output_folder=get_output_folder()) im_contour_writer = ImageWriter(output_folder='out2') prev = [] while True: k = cv.WaitKey(msdelay) k = chr(k) if k > 0 else 0 if handle_keyboard(k) < 0: break bgrimg = cv.QueryFrame(cam) if not bgrimg: break im_orig_writer.write(bgrimg) cv.Flip(bgrimg, None, 1) contours = session.process(bgrimg) img = cv.CreateImage((bgrimg.width, bgrimg.height), 8, 3) if contours: ges, area, depth = ga.recognize(contours) x, y, r, b = im.find_max_rectangle(contours) cv.Rectangle(img, (x,y), (r, b), im.color.RED) cv.DrawContours(img, contours, im.color.RED, im.color.GREEN, 1, thickness=3) print ges currentInput = grammar.instantGes(ges) print currentInput if len(prev)>=2: for i,g in enumerate(currentInput): im.puttext(prev[0], str(g), 30, 70+40*i) im_contour_writer.write(prev[0]) prev.append( img ) prev.pop(0) else: prev.append( img ) if grammar == answer_grammer: for i,g in enumerate(currentInput): im.puttext(prev[0], str(g), 30, 70+40*i) im_contour_writer.write(prev[0]) im.puttext(prev[0], 'AUTHENTICATED!', 30, 70+40*len(currentInput)) im_contour_writer.write(prev[0]) print 'AUTHENTICATED!!!!' break cv.ShowImage(proc_win_name, img)
cv.ShowImage( "skinProbDilated", skinProbImg ) #Original skin probability image after thresholding #smooth cv.Smooth(skinProbImg, skinProbImg, cv.CV_BLUR_NO_SCALE) cv.ShowImage("skinProbSmoothed", skinProbImg) #Original image #construct color image to add colored contour and rectangle skinProbColor = cv.CreateImage( (skinProbImg.width, skinProbImg.height), 8, 3) cv.CvtColor(skinProbImg, skinProbColor, cv.CV_GRAY2BGR) # find contours for blobs seq = cv.FindContours(skinProbImg, cv.CreateMemStorage(), cv.CV_RETR_EXTERNAL) while seq: cv.DrawContours(skinProbColor, seq, (255, 0, 0), (255, 255, 0), 0, 2) seqRect = cv.BoundingRect(seq) x = seqRect[0] y = seqRect[1] w = seqRect[2] h = seqRect[3] goodRectCntr = 0 goodRects = [10] if w >= 20 and h >= 20: rectCntrX = x + int(w / 2) rectCntrY = y + int(h / 2) if not ((rectCntrX > bestFaceX and rectCntrX < bestFaceX + bestFaceW) and (rectCntrY > bestFaceY and rectCntrY < bestFaceY + bestFaceH)):
def plot_contours(contours, shape): img = cv.CreateImage(shape, 8, 3) cv.NamedWindow('show', 1) cv.SetZero(img) cv.DrawContours(img, contours, color.RED, color.GREEN, 1) cv.ShowImage('show', img)
orig = cv.LoadImage('./demo1.jpg', cv.CV_LOAD_IMAGE_COLOR) im = cv.CreateImage(cv.GetSize(orig), 8, 1) cv.CvtColor(orig, im, cv.CV_BGR2GRAY) #Keep the original in colour to draw contours in the end cv.Threshold(im, im, 128, 255, cv.CV_THRESH_BINARY) cv.ShowImage("Threshold 1", im) cv.SaveImage("threshold1.jpg",im) element = cv.CreateStructuringElementEx(5*2+1, 5*2+1, 5, 5, cv.CV_SHAPE_RECT) cv.MorphologyEx(im, im, None, element, cv.CV_MOP_OPEN) #Open and close to make appear contours cv.MorphologyEx(im, im, None, element, cv.CV_MOP_CLOSE) cv.Threshold(im, im, 128, 255, cv.CV_THRESH_BINARY_INV) cv.ShowImage("After MorphologyEx", im) cv.SaveImage("after.jpg",im) # -------------------------------- vals = cv.CloneImage(im) #Make a clone because FindContours can modify the image contours=cv.FindContours(vals, cv.CreateMemStorage(0), cv.CV_RETR_LIST, cv.CV_CHAIN_APPROX_SIMPLE, (0,0)) _red = (0, 0, 255); #Red for external contours _green = (0, 255, 0);# Gren internal contours levels=2 #1 contours drawn, 2 internal contours as well, 3 ... co=cv.DrawContours (orig, contours, _red, _green, levels, 2, cv.CV_FILLED) #Draw contours on the colour image cv.SaveImage("save.jpg",orig) # cv.SaveImage("co.jpg",co) cv.ShowImage("Image", orig) cv.WaitKey(0)
def listen(self): bgimg = cv.CreateImage((self.background.width, self.background.height), 8, 3) img = cv.CreateImage((self.background.width, self.background.height), 8, 3) cv.Copy(self.background, bgimg) smallimg = cv.CreateImage((self.background.width / self.zoom, self.background.height / self.zoom), 8, 3) cv.GetRectSubPix( bgimg, smallimg, (self.background.width / (2 * self.zoom) + self.offset[0], self.background.height / (2 * self.zoom) + self.offset[1])) cv.Resize(smallimg, img) cv.Smooth(img, img, cv.CV_GAUSSIAN) if (self.cp != False): cv.Circle(img, self.zoomPt(int(self.cp.x), int(self.cp.y)), 3, cv.RGB(0, 255, 0), -1) mask = thresholding.threshold(img, thresholding.CUSTOM, False, crop_rect=None, cam_info=None, listener=None, hue_interval=(self.hue_low, self.hue_up)) cv.Not(mask, mask) new_img = cv.CloneImage(img) cv.SetZero(new_img) cv.Copy(img, new_img, mask) new_img = thresholding.sat_threshold(new_img, 50) cv.Line(img, (self.ch_x - 25, self.ch_y), (self.ch_x + 25, self.ch_y), cv.RGB(255, 255, 0)) cv.Line(img, (self.ch_x, self.ch_y - 25), (self.ch_x, self.ch_y + 25), cv.RGB(255, 255, 0)) image_gray = cv.CreateImage(cv.GetSize(new_img), 8, 1) cv.CvtColor(new_img, image_gray, cv.CV_RGB2GRAY) cv.MorphologyEx(image_gray, image_gray, None, None, cv.CV_MOP_OPEN, 1) storage = cv.CreateMemStorage(0) seq = cv.FindContours(image_gray, storage) points = [] contour = seq centers = [] ccs = [] while contour: bound_rect = cv.BoundingRect(list(contour)) area = cv.ContourArea(contour) cc = contour contour = contour.h_next() if area < 50 or area > 2500: continue ccs.append(cc) win, center, radius = cv.MinEnclosingCircle(cc) cv.DrawContours(new_img, cc, (0, 255, 0), (0, 255, 0), 0, 1) pt1 = (bound_rect[0], bound_rect[1]) pt2 = (bound_rect[0] + bound_rect[2], bound_rect[1] + bound_rect[3]) points.append(pt1) points.append(pt2) cv.Circle(new_img, center, radius, (0, 0, 255)) centers.append(center) #cv.Rectangle(new_img, pt1, pt2, cv.CV_RGB(255,0,0), 1) font = cv.InitFont(cv.CV_FONT_HERSHEY_PLAIN, 1, 1) cv.PutText(new_img, "%.2f" % area, pt1, font, (255, 255, 255)) for cont1, cont2 in itertools.combinations(ccs, 2): if is_next_to(cont1, cont2): win, c1, r1 = cv.MinEnclosingCircle(cont1) win, c2, r2 = cv.MinEnclosingCircle(cont2) cv.Line(new_img, c1, c2, (255, 255, 0)) #DRAW cv.ShowImage(self.name, new_img) #Do some funny business imgcs = {} satt = thresholding.sat_threshold(img, 50) for color in HueRanges.__dict__: if color == color.upper(): img_c = thresholding.filter_color(satt, color) cv.ShowImage(color, img_c) cv.WaitKey(25)
image_smoothed = cv.CloneImage(image) cv.Smooth(image, image_smoothed, cv.CV_GAUSSIAN, 3) # threshold the smoothed image image_threshed = thresholded_image(image_smoothed) # blobify # cv.Dilate(image_threshed, image_threshed, None, 18) # cv.Erode(image_threshed, image_threshed, None, 10) blobContour = None # extract the edges from our binary image current_contour = cv.FindContours(cv.CloneImage(image_threshed), cv.CreateMemStorage(), cv.CV_RETR_CCOMP, cv.CV_CHAIN_APPROX_SIMPLE) cv.DrawContours(image, current_contour, (0, 0, 255), (0, 100, 100), 4) # if there is a matching object in the frame if len(current_contour) != 0: # find the largest blob largest_contour = current_contour while True: current_contour = current_contour.h_next() if (not current_contour): break if (cv.ContourArea(current_contour) > cv.ContourArea(largest_contour)): largest_contour = current_contour # if we got a good enough blob
image_smoothed = cv.CloneImage(image) cv.Smooth(image, image_smoothed, cv.CV_GAUSSIAN, 9) # threshold the smoothed image image_threshed = thresholded_image(image_smoothed) # blobify cv.Dilate(image_threshed, image_threshed, None, 3) cv.Erode(image_threshed, image_threshed, None, 3) blobContour = None # extract the edges from our binary image current_contour = cv.FindContours(cv.CloneImage(image_threshed), cv.CreateMemStorage(), cv.CV_RETR_CCOMP, cv.CV_CHAIN_APPROX_SIMPLE) cv.DrawContours(image, current_contour, (0, 0, 255), (0, 100, 100), 4) if len(current_contour) != 0: # find the largest blob largest_contour = current_contour while True: current_contour = current_contour.h_next() if (not current_contour): break if (cv.ContourArea(current_contour) > cv.ContourArea(largest_contour)): largest_contour = current_contour cv.DrawContours(image_threshed, contour, external_color, hole_color, max_level)
def processFrame(): # Declare as globals since we are assigning to them now global capture global camera_index global frame_grey global prev_frame global prev_frame_grey global motionMask global mhi global orientation global prevFrameIndex diff_threshold = 50 # Capture current frame frame = cv.QueryFrame(capture) # Create frame buffer and initial all image variables needed for the motion history algorithm if not mhi: for i in range(N): buffer[i] = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_8U, 1) cv.Zero(buffer[i]) mhi = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_32F, 1) cv.Zero(mhi) orientation = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_32F, 1) # Erode the frame 3 times to remove noise #cv.Erode(frame, frame, None, 3) # Convert frame to greyscale and store it in the buffer cv.CvtColor(frame, buffer[prevFrameIndex], cv.CV_RGB2GRAY) # Iterate the indexes of the image buffer index1 = prevFrameIndex index2 = (prevFrameIndex + 1) % N # Finds the next index in the buffer prevFrameIndex = index2 motionMask = buffer[index2] # Find the motion mask by finding the difference between the current and previous frames cv.AbsDiff(buffer[index1], buffer[index2], motionMask) # Convert the motion mask to a binary image cv.Threshold(motionMask, motionMask, diff_threshold, 1, cv.CV_THRESH_BINARY) # Produce motion history image timeStamp = time.clock() / CLOCKS_PER_SEC cv.UpdateMotionHistory(motionMask, mhi, timeStamp, MHI_DURATION) # Copy new motion mask onto the motion history image and scale it cv.ConvertScale(mhi, motionMask, 255. / MHI_DURATION, (MHI_DURATION - timeStamp) * 255. / MHI_DURATION) # Calculate the motion gradient and find the direction of motion tempMask = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_8U, 1) cv.Merge(motionMask, None, None, None, tempMask) cv.CalcMotionGradient(mhi, tempMask, orientation, 0.5, 0.05, 3) angle = 360 - cv.CalcGlobalOrientation(orientation, tempMask, mhi, timeStamp, MHI_DURATION) #print angle # Contour detection method # Draw motion box and angle line cv.Dilate(tempMask, tempMask, None, 1) storage = cv.CreateMemStorage(0) contour = cv.FindContours(tempMask, storage, cv.CV_RETR_EXTERNAL, cv.CV_CHAIN_APPROX_SIMPLE) cv.DrawContours( motionMask, contour, cv.RGB(0, 0, 255), cv.RGB(0, 255, 0), 1) # Change first parameter to motionMask to get mhi and contour # Single outermost contour """ try: bound_rect1 = contour[0] bound_rect2 = contour[1] pt1 = (bound_rect1[0], bound_rect1[1]) pt2 = (bound_rect1[0] + bound_rect2[0], bound_rect1[1] + bound_rect2[1]) # draw cv.Rectangle(motionMask, pt1, pt2, cv.CV_RGB(0,0,255), 1) except: continue """ # Lots of contours """ while contour: bound_rect = cv.BoundingRect(list(contour)) contour = contour.h_next() pt1 = (bound_rect[0], bound_rect[1]) pt2 = (bound_rect[0] + bound_rect[2], bound_rect[1] + bound_rect[3]) # draw cv.Rectangle(motionMask, pt1, pt2, cv.CV_RGB(0,0,255), 1) """ # Combine motion mask and contours output = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_8U, 1) #cv.Merge(motionMask, None, None, None, tempMask) # Display image cv.ShowImage("CS201 - Homework 3 - Tyler Boraski", motionMask) # If wrong camera index is initialized, press "n" to cycle through camera indexes. c = cv.WaitKey(10) if c == "n": camera_index += 1 # Try the next camera index capture = cv.CaptureFromCAM(camera_index) if not capture: # If the next camera index didn't work, reset to 0. camera_index = 0 capture = cv.CaptureFromCAM(camera_index) # If "esc" is pressed the program will end esc = cv.WaitKey(7) % 0x100 if esc == 27: quit()
def repeat(begin, unmute, last, hold, beginhold): """Actual finger detection function, passes mute and click status""" #captures input frame frame = cv.QueryFrame(capture) #creates horizontally flipped copy of input frame to work with cv.Copy(frame, sframe) cv.Flip(sframe, sframe, 1) #makes mask of skintones dog = skin(sframe, ccolor) #inverts skintone mask to all non-skin areas cv.ConvertScale(dog, dog, -1, 255) #makes greyscale copy of frame cv.CvtColor(sframe, grey, cv.CV_BGR2GRAY) #replaces nonskin areas with white cv.Add(grey, white, grey, dog) #implements laplacian edge detection on greyscale image dst_16s2 = cv.CreateImage(cv.GetSize(bg), cv.IPL_DEPTH_16S, 1) cv.Laplace(grey, dst_16s2, 5) cv.Convert(dst_16s2, grey) #creates a threshold to binarize the image cv.Threshold(grey, grey, 75, 255, cv.CV_THRESH_BINARY) #creates contours on greyscale image storage = cv.CreateMemStorage(0) contours = cv.FindContours(grey, storage, cv.CV_RETR_TREE, cv.CV_CHAIN_APPROX_SIMPLE) #sets final display frame background to black cv.Set(cframe, 0) #sets minimum range for object detection mx = 20000 #initializes hand position to previous best = last #creates some cvSeq maxcont by copying contours maxcont = contours #goes through all contours and finds bounding box while contours: bound_rect = cv.BoundingRect(list(contours)) #if bounding box area is greater than min range or current max box if bound_rect[3] * bound_rect[2] > mx: #sets max to current object, creates position at center of box, and sets display contour to current mx = bound_rect[3] * bound_rect[2] maxcont = contours #goes to next contour contours = contours.h_next() #draws largest contour on final frame cv.DrawContours(cframe, maxcont, 255, 127, 0) if maxcont: #creates convex hull of largest contour chull = cv.ConvexHull2(maxcont, storage, cv.CV_CLOCKWISE, 1) cv.PolyLine(cframe, [chull], 1, 255) chulllist = list(chull) chull = cv.ConvexHull2(maxcont, storage, cv.CV_CLOCKWISE, 0) cdefects = cv.ConvexityDefects(maxcont, chull, storage) #filters small convexity defects and draws large ones truedefects = [] for j in cdefects: if j[3] > 30: truedefects.append(j) cv.Circle(cframe, j[2], 6, 255) #if hand is in a pointer position, detects tip of convex hull if cdefects and len(truedefects) < 4: tipheight = 481 tiploc = 0 for j in chulllist: if j[1] < tipheight: tipheight = j[1] tiploc = chulllist.index(j) best = chulllist[tiploc] #keeps last position if movement too quick, or smooths slower movement xdiff = best[0] - last[0] ydiff = best[1] - last[1] dist = math.sqrt(xdiff**2 + ydiff**2) if dist > 100: best = last else: best = (last[0] + xdiff * .75, last[1] + ydiff * .75) #draws main position circle cv.Circle(cframe, (int(best[0]), int(best[1])), 20, 255) #displays image with contours cv.ShowImage("w2", cframe) cv.MoveWindow('w2', 600, 0) #delay between frame capture c = cv.WaitKey(10) if not hold: #if largest contour covers half the screen if mx > 153600 / 2: #begins timer if not yet started if begin == 0: begin = time.time() else: #sets volume to new volume, or 0 if muted #in Linux if sysname == True: os.system('amixer set Master %s' % (.64 * unmute * (100 - best[1] / 4.8))) #in Mac else: os.system( 'osascript -e \'set volume output volume %s\'' % (.64 * unmute * (100 - best[1] / 4.8))) #if 3 seconds have passed, stops timer and switches mute status if time.time() - begin > 3: unmute = 1 - unmute begin = 0 #stops timer and sets volume to new, if unmuted else: begin = 0 #in Linux if sysname == True: os.system('amixer set Master %s' % (int(.64 * unmute * (100 - best[1] / 4.8)) * .75)) #in Mac else: os.system('osascript -e \'set volume output volume %s\'' % (int(.64 * unmute * (100 - best[1] / 4.8)) * .75)) #returns timer start, mute status, and previous hand position return (begin, unmute, best, hold, beginhold)
def repeat1(begin, unmute, last, hold, beginhold): """actual function for moving and clicking mouse""" def click_down(): """Simulates a down click""" fake_input(d, ButtonPress, 1) d.sync() def click_up(): """Simulates an up click""" fake_input(d, ButtonRelease, 1) d.sync() #captures input frame frame = cv.QueryFrame(capture) #initializes mouse behavior d = Display() s = d.screen() root = s.root #creates horizontally flipped copy of input frame to work with cv.Copy(frame, sframe) cv.Flip(sframe, sframe, 1) #makes mask of skintones dog = skin(sframe, ccolor) #inverts skintone mask to all non-skin areas cv.ConvertScale(dog, dog, -1, 255) #makes greyscale copy of frame cv.CvtColor(sframe, grey, cv.CV_BGR2GRAY) #replaces nonskin areas with white cv.Add(grey, white, grey, dog) #implements laplacian edge detection on greyscale image dst_16s2 = cv.CreateImage(cv.GetSize(bg), cv.IPL_DEPTH_16S, 1) cv.Laplace(grey, dst_16s2, 5) cv.Convert(dst_16s2, grey) #creates a threshold to binarize the image cv.Threshold(grey, grey, 75, 255, cv.CV_THRESH_BINARY) #creates contours on greyscale image storage = cv.CreateMemStorage(0) contours = cv.FindContours(grey, storage, cv.CV_RETR_TREE, cv.CV_CHAIN_APPROX_SIMPLE) #sets final display frame background to black cv.Set(cframe, 0) #sets minimum range for object detection mx = 20000 #initializes hand position to previous best = last #creates some cvSeq maxcont by copying contours maxcont = contours #goes through all contours and finds bounding box while contours: bound_rect = cv.BoundingRect(list(contours)) #if bounding box area is greater than min range or current max box if bound_rect[3] * bound_rect[2] > mx: #sets max to current object, creates position at center of box, and sets display contour to current mx = bound_rect[3] * bound_rect[2] maxcont = contours #goes to next contour contours = contours.h_next() #draws largest contour on final frame cv.DrawContours(cframe, maxcont, 255, 127, 0) if maxcont: #draws and finds convex hull and convexity defects chull = cv.ConvexHull2(maxcont, storage, cv.CV_CLOCKWISE, 1) cv.PolyLine(cframe, [chull], 1, 255) chulllist = list(chull) chull = cv.ConvexHull2(maxcont, storage, cv.CV_CLOCKWISE, 0) cdefects = cv.ConvexityDefects(maxcont, chull, storage) #filters smaller convexity defects and displays larger ones truedefects = [] for j in cdefects: if j[3] > 30: truedefects.append(j) cv.Circle(cframe, j[2], 6, 255) #Finds highest point of convex hull if hand follows smooth vertical shape if cdefects and len(truedefects) < 4: tipheight = 481 tiploc = 0 for j in chulllist: if j[1] < tipheight: tipheight = j[1] tiploc = chulllist.index(j) best = chulllist[tiploc] #if hand is open, begin click if len(truedefects) >= 4: if beginhold == 0: beginhold = time.time() else: #if .05 seconds have passed, clicks down if (time.time() - beginhold > .05) and not hold: hold = True beginhold = 0 click_down() #unclicks if hand returns to smooth else: if hold: click_up() hold = False beginhold = 0 #keeps last position if movement too quick, or smooths slower movement xdiff = best[0] - last[0] ydiff = best[1] - last[1] dist = math.sqrt(xdiff**2 + ydiff**2) if dist > 100: best = last else: best = (last[0] + xdiff * .75, last[1] + ydiff * .75) #displays main position circle cv.Circle(cframe, (int(best[0]), int(best[1])), 20, 255) #displays image with contours cv.ShowImage("w2", cframe) cv.MoveWindow('w2', 500, 0) #delay between frame capture c = cv.WaitKey(10) #Mouse Move/ Bottom Pointer Dx, Dy = mousedelta(last, best) root.warp_pointer((best[0] - 320) * 1600 / 600 + 800, best[1] * 900 / 360) d.sync() return (begin, unmute, best, hold, beginhold)
storage = cv.CreateMemStorage(0) #cv.SaveImage("wshed_mask.png", marker_mask) #marker_mask = cv.LoadImage("wshed_mask.png", 0) contours = cv.FindContours(marker_mask, storage, cv.CV_RETR_CCOMP, cv.CV_CHAIN_APPROX_SIMPLE) def contour_iterator(contour): while contour: yield contour contour = contour.h_next() cv.Zero(markers) comp_count = 0 for c in contour_iterator(contours): cv.DrawContours(markers, c, cv.ScalarAll(comp_count + 1), cv.ScalarAll(comp_count + 1), -1, -1, 8) comp_count += 1 cv.Watershed(img0, markers) cv.Set(wshed, cv.ScalarAll(255)) # paint the watershed image color_tab = [(cv.RandInt(rng) % 180 + 50, cv.RandInt(rng) % 180 + 50, cv.RandInt(rng) % 180 + 50) for i in range(comp_count)] for j in range(markers.height): for i in range(markers.width): idx = markers[j, i] if idx != -1:
def find_biggest_region(D): """ finds all the contours in threshed image, finds the largest of those, and then marks in in the main image """ # Create a copy image of thresholds then find contours on that image storage = cv.CreateMemStorage(0) # Create memory storage for contours copy = cv.CreateImage(D.size, 8, 1) cv.Copy(D.threshed_image, copy) # copy threshed image # this is OpenCV's call to find all of the contours: contours = cv.FindContours(copy, storage, cv.CV_RETR_EXTERNAL, \ cv.CV_CHAIN_APPROX_SIMPLE) # Next we want to find the *largest* contour if len(contours) > 0: biggest = contours biggestArea = cv.ContourArea(contours) while contours != None: nextArea = cv.ContourArea(contours) if biggestArea < nextArea: biggest = contours biggestArea = nextArea contours = contours.h_next() # Use OpenCV to get a bounding rectangle for the largest contour br = cv.BoundingRect(biggest, update=0) #print "in find_regions, br is", br ulx, uly, width, height = br[0], br[1], br[2], br[3] D.br = (ulx, uly), (width, height) D.target_size = width * height # You will want to change these so that they draw a box # around the largest contour and a circle at its center: # Example of drawing a yellow box cv.PolyLine(D.image, [[(ulx,uly), (ulx+width,uly), (ulx+width,uly+height),\ (ulx,uly+height)]], 1, cv.RGB(255, 255, 0)) # Draw circle in the center of the target cv.Circle(D.image, (ulx+width/2,uly+height/2), 10, \ cv.RGB(255, 0, 0), thickness=1, lineType=8, shift=0) # Draw the contours in white with inner ones in green cv.DrawContours(D.image, biggest, cv.RGB(255, 255, 255), \ cv.RGB(0, 255, 0), 1, thickness=2, lineType=8, \ offset=(0,0)) # Reset coordinates to keep track of where the center of the coutour is D.last_target_coord = D.target_coord D.target_coord = (ulx + width / 2, uly - height / 2) D.p1, D.p2, D.p3, D.p4 = (D.target_coord[0],D.target_coord[1] + height/2),\ (D.target_coord[0],D.target_coord[1] + height/2), \ (D.target_coord[0],D.target_coord[1] + height/2), \ (D.target_coord[0],D.target_coord[1] + height/2) else: D.br = (0, 0), (0, 0) D.target_size = 0 D.p1, D.p2, D.p3, D.p4 = (0, 0), (0, 0), (0, 0), (0, 0)
cv.InRangeS(hsv, (165, 145, 100), (140, 255, 255), thresh) cv.ShowImage("Modifieda", thresh) cv.InRangeS(hsv, (0, 145, 100), (10, 255, 255), thresha) cv.Add(thresh, thresha, thresh) cv.Erode(thresh, thresh, iterations=5) cv.Dilate(thresh, thresh, iterations=5) ## cv.ShowImage("Saturated", sat) ## cv.ShowImage("End Resul", red) cv.ShowImage("Modified", thresh) memory = cv.CreateMemStorage(0) clone = cv.CloneImage(thresh) contours = cv.FindContours(clone, memory, cv.CV_RETR_LIST, cv.CV_CHAIN_APPROX_SIMPLE, (0, 0)) # cv.ShowImage("Only Contours", clone) cv.DrawContours(original, contours, 120, 0, 7) if not contours: rectPoints = (0, 0, 0, 0) else: rectPoints = cv.BoundingRect(contours) #print rectPoints left, top, width, height = rectPoints right, bottom = left + width, top + height cv.Rectangle(original, (left, top), (right, bottom), 255, 9, 8, 0) if top > 500: if snare == False: print i snare = True else: snare = False
def find_better_point(self, from_, direction, predicted_length, range=20): ''' Tries to find better corner arm - goes from from_ using vector direction on a line to find last visible point on this line @param from_: @param tpredicted_length: predicted length of this side @param direction: ''' img = self.bw_img timg = self.tmp_img L1 = predicted_length * 1.2 vec = direction L2 = length(vec) vec = add((0, 0), vec, L1 / L2) #vector towards direction of length of old side vec1 = rotateVec(vec, d2r(range)) vec2 = rotateVec(vec, d2r(-range)) x, y = from_ cv.ResetImageROI(img) size = cv.GetSize(img) border_points = [add(from_, vec1), add(from_, vec2), (x - 5, y - 5), (x + 5, y + 5)] (x, y, wx, wy) = cv.BoundingRect(border_points) crect = correct_rectangle((x - 3, y - 3, wx + 6, wy + 6), size) [cv.SetImageROI(i, crect) for i in [img, timg, self.gray_img]] self.bounds.extend(cvrect(crect)) cv.Threshold(self.gray_img, img, 125, 255, cv.CV_THRESH_OTSU) cv.Not(img, timg) cv.Canny(self.gray_img, img, 300, 500) cv.Or(img, timg,timg) rect = cvrect(crect) cv.Set2D(timg, 1, 1, (30, 30, 30)) conts = cv.FindContours(timg, cv.CreateMemStorage(), cv.CV_RETR_EXTERNAL) db.DrawContours(timg, conts, (255, 255, 255), (128, 128, 128), 10) cv.Zero(timg) fr = add(from_, rect[0], -1) ans = [] while conts: cont = cv.ApproxPoly(conts, cv.CreateMemStorage(), cv.CV_POLY_APPROX_DP, parameter=2, parameter2=0) cv.DrawContours(timg, cont, (255, 255, 255), (128, 128, 128), 10) cont = list(cont) L = len(cont) for i, p in enumerate(cont): if length(vector(fr, p)) < 5: prev = cont[(i - 1 + L) % L] next = cont[(i + 1) % L] ans.append(vector(fr, prev)) ans.append(vector(fr, next)) conts = conts.h_next() [cv.ResetImageROI(i) for i in [self.gray_img, timg, img]] if len(ans) == 0: # we didn't find corresponding corner, # that means it wasn't really a corner return None if len(ans) == 2 and ans[0] == ans[1]: return add(from_, direction) min = math.pi min_index = 0 for i, v in enumerate(ans): tmp = vectorAngle(vec, v) if tmp < min: min = tmp min_index = i ans = ans[min_index] if length(ans)+1< L2: # the point we just found is closer then the previous one return add(from_,direction) abs_point = add(from_, ans) if point_on_edge(abs_point, crect): if not point_on_edge(abs_point, (0, 0, size[0], size[1])): if range < 20: # this is recurence call. When we are here it means that # side is longer then expected by over 2 times - it is not # the side we are looking for- corner is not valid return None else: return self.find_better_point(from_, abs_point, predicted_length * 2, 5) return abs_point
cv.Erode(grey_scale, processed, None, 10) #cv.ShowImage("erode", processed) cv.Dilate(processed, processed, None, 10) #cv.ShowImage("dilate", processed) cv.Canny(processed, processed, 5, 70, 3) #cv.ShowImage("canny", processed) cv.Smooth(processed, processed, cv.CV_GAUSSIAN, 15, 15) cv.ShowImage("Imagem pre-procesada", processed) storage = cv.CreateMemStorage(0) # 'processed' será modificado! contours = cv.FindContours(processed, storage, cv.CV_RETR_EXTERNAL) #cv.ShowImage("depois de FindContours", processed) cv.DrawContours(orig, contours, cv.RGB(0, 255, 0), cv.RGB(255, 0, 0), 2, 3, cv.CV_AA, (0, 0)) def contour_iterator(contour): while contour: yield contour contour = contour.h_next() for c in contour_iterator(contours): # Qde de pontos deve ser ≥ 6 para cv.FitEllipse2 if len(c) >= 6: # Copiar o contorno em um array de (x,y)'s PointArray = cv.CreateMat(1, len(c), cv.CV_32FC2) for (i, (x, y)) in enumerate(c):
def draw_contours(self, image, contours): cv.DrawContours(self.result, contours, (0, 255, 0), (0, 255, 0), 1, 3, 3, (0, 0))
# Blurring image image_smoothed = cv.CloneImage(image) cv.Smooth(image, image_smoothed, cv.CV_GAUSSIAN, 1) image_threshed = thresholded_image(image_smoothed) cv.Dilate(image_threshed, image_threshed, None, 3) cv.Erode(image_threshed, image_threshed, None, 3) blobContour = None # Contour Finding !!!!!!!!!Main Algo!!!!!!!! current_contour = cv.FindContours(cv.CloneImage(image_threshed), cv.CreateMemStorage(), cv.CV_RETR_CCOMP, cv.CV_CHAIN_APPROX_SIMPLE) #just making an outline cv.DrawContours(image, current_contour,(0,0,255),(0,100,100),4) if len(current_contour) != 0: largest_contour = current_contour while True: current_contour = current_contour.h_next() if (not current_contour): break if (cv.ContourArea(current_contour) > cv.ContourArea(largest_contour)): largest_contour = current_contour # if we got a good enough blob if cv.ContourArea(largest_contour)>2.0: blobContour = largest_contour
def lineScan(self, image, source=None): """ Performs contour detection on a single channel image. Returns a set of 2d points containing the outer left line for the detected contours. """ storage = cv.CreateMemStorage() contours = cv.FindContours(image, storage, mode=cv.CV_RETR_EXTERNAL, method=cv.CV_CHAIN_APPROX_SIMPLE, offset=(0, 0)) points = [] width, height = cv.GetSize(source) mask = cv.CreateImage((width, height), cv.IPL_DEPTH_8U, 1) cv.Zero(mask) if contours: while contours: size = cv.ContourArea(contours) if size < self.contourSize: contours = contours.h_next() continue cv.DrawContours(mask, contours, (255, 255, 255), (255, 255, 255), 0, -1) contours = contours.h_next() #PolyLine(img, polys, is_closed, color, thickness=1, lineType=8, shift=0) ? None? #cv.ShowImage('mask', mask ); storage = cv.CreateMemStorage() contours = cv.FindContours(mask, storage, mode=cv.CV_RETR_EXTERNAL, method=cv.CV_CHAIN_APPROX_SIMPLE, offset=(0, 0)) while contours: seq = [(x, y) for x, y in contours if x < width / 2] points.extend(seq) contours = contours.h_next() #cv.PolyLine(source, [points], False, (0, 255, 0), 1, 8, 0) #cv.DrawContours( source, contours, (255, 0, 0), (0, 255, 0), 0, 1 ); # #if contours: # cv.DrawContours( source, contours, (255,0,0), (0,255,0), 7, -1 ) # cv.DrawContours( mask, contours, (255,0,0), (0,255,0), 7, -1 ) # # while contours: # if cv.ContourArea( contours ) < 200: # contours = contours.h_next() # continue # # y_max = max([y for _, y in contours]) # seq = [(x,y) for x,y in contours] # # #points.extend(seq); # i = 0 # # # extract only the left side of the polygon # for i in range( 0, len(seq)-1): # if seq[i][1] == y_max: # break; # # seq = seq[:i]; # # if source: # draws the detected polygon line as feedback # # points.extend(seq); # contours = contours.h_next() # # #cv.ShowImage('mask', mask ); return points
cv.Smooth(themap, themap, cv.CV_GAUSSIAN, gaussian_blur,gaussian_blur) cv.SaveImage("map.png",themap) (minval,maxval,minloc,maxloc)=cv.MinMaxLoc(themap) print "Min: "+`minval`+" max: "+`maxval` cv.ConvertScale(themap,mask,255.0/maxval,0); cv.SaveImage("mask.png",mask) cv.CmpS(themap,mask_threshold,mask,cv.CV_CMP_GT) cv.SaveImage("thresholded.png",mask) #contour = cv.FindContours(mask,cv.CreateMemStorage(),cv.CV_RETR_CCOMP,cv.CV_CHAIN_APPROX_SIMPLE) chain = cv.FindContours(mask,cv.CreateMemStorage(),cv.CV_RETR_CCOMP,cv.CV_CHAIN_CODE) contour = cv.ApproxChains(chain,cv.CreateMemStorage(),cv.CV_CHAIN_APPROX_NONE,0,100,1) img = cv.CreateMat(height,width,cv.CV_8UC3) cv.SetZero(img) cv.DrawContours(img,contour,(255,255,255),(0,255,0),6,1) cv.SaveImage("contours.png",img) img = cv.CreateMat(height,width,cv.CV_8UC3) cv.SetZero(img) # # create the voronoi graph delaunay = cv.CreateSubdivDelaunay2D((0,0,width,height),cv.CreateMemStorage()) def make_delaunay(seq): if seq == None: return i=0 for point in seq: i+=1 if i % voronoi_sampling_interval == 0:
cv.CV_RETR_LIST, cv.CV_CHAIN_APPROX_SIMPLE, (0, 0)) des = cv.CreateImage(cv.GetSize(image), 8, 3) contours2 = False hull = False blank = cv.CreateImage(cv.GetSize(image), 8, 3) while contours: contours2 = contours contours = contours.h_next() if contours2: hull = cv.ConvexHull2(contours2, cv.CreateMemStorage(), cv.CV_CLOCKWISE, 0) defects = cv.ConvexityDefects(contours2, hull, cv.CreateMemStorage()) cv.DrawContours(image, contours2, (255, 0, 0), (0, 255, 0), 0, 5) noOfDefects = 0 comx, comy = 0, 0 Z, (p, q), radius = cv.MinEnclosingCircle(contours2) if Z: cv.Circle(image, (int(p), int(q)), int(5), [0, 255, 255], -1) for defect in defects: start, end, far, d = defect xpos, ypos = far cv.Line(image, start, end, [0, 255, 0], 2) if d > 20 and not pointInFace(xpos, ypos, x, y, w, h): cv.Circle(image, far, 5, [0, 0, 255], -1) if noOfDefects:
def find_biggest_region(pub): """ finds all the contours in threshed image, finds the largest of those, and then marks in in the main image """ # get D so that we can change values in it global D # Create a copy image of thresholds then find contours on that image cv.Copy(D.threshed_image, D.copy) # copy threshed image # this is OpenCV's call to find all of the contours: contours = cv.FindContours(D.copy, D.storage, cv.CV_RETR_EXTERNAL, cv.CV_CHAIN_APPROX_SIMPLE) # Next we want to find the *largest* contour # this is the standard algorithm: # walk the list of all contours, remembering the biggest so far: if len(contours) > 0: biggest = contours biggestArea = cv.ContourArea(contours) while contours != None: nextArea = cv.ContourArea(contours) if biggestArea < nextArea: biggest = contours biggestArea = nextArea contours = contours.h_next() # Use OpenCV to get a bounding rectangle for the largest contour br = cv.BoundingRect(biggest, update=0) # Draw a red box from (42,42) to (84,126), for now (you'll change this): x = br[0] y = br[1] w = br[2] h = br[3] upper_left = (x, y) lower_left = (x, y + h) lower_right = (x + w, y + h) upper_right = (x + w, y) cv.PolyLine(D.image, [[upper_left, lower_left, lower_right, upper_right]], 1, cv.RGB(255, 0, 0)) # Draw the circle, at the image center for now (you'll change this) center = ((2 * x + w) / 2, (2 * y + h) / 2) cv.Circle(D.image, center, 10, cv.RGB(255, 255, 0), thickness=2, lineType=8, shift=0) # Draw matching contours in white with inner ones in green cv.DrawContours(D.image, biggest, cv.RGB(255, 255, 255), cv.RGB(0, 255, 0), 1, thickness=2, lineType=8, offset=(0, 0)) # publish the rectangle vertex coordinates pub.publish(','.join(map(str, [upper_left, lower_right])))
notsat = cv.CreateImage(size, 8, 1) new = cv.CreateImage(size, 8, 1) cv.Split(small, sat, None, None, None) cv.Threshold(sat, notsat, 100, 255, cv.CV_THRESH_BINARY) cv.Dilate(notsat, notsat, cv.CreateStructuringElementEx(3, 3, 1, 1, cv.CV_SHAPE_ELLIPSE), 2) storage = cv.CreateMemStorage(0) contour = cv.FindContours(notsat, storage, cv.CV_RETR_EXTERNAL, cv.CV_CHAIN_APPROX_NONE) while contour: if cv.ContourArea(contour) < 10: contour2 = contour cv.DrawContours(new, contour2, cv.RGB(255, 255, 255), cv.RGB(255, 255, 255), -1, cv.CV_FILLED, cv.CV_AA) contour = contour.h_next() cv.SaveImage("stars.png", new) cv.SaveImage("small.png", small) for i in range(0, x): for j in range(0, y): if new[j, i] == 255: p1y = j p1x = i for k in range(0, x): for l in range(0, y): if new[l, k] == 255: p2y = l p2x = k
cv.Smooth(thresholded, gaussianed, cv.CV_GAUSSIAN, 9, 9) gaussian = gaussianed #create a storage area storage = cv.CreateMemStorage(0) #find the contours of the image contours = cv.FindContours(gaussianed, storage, cv.CV_RETR_TREE, cv.CV_CHAIN_APPROX_SIMPLE, (0, 0)) #create the contoured image contouredImage = cv.CreateImage(currentFrameSize, 8, 3) cv.SetZero(contouredImage) #draw the contoured image cv.DrawContours(contouredImage, contours, _red, _green, 1, 1, cv.CV_AA, (0, 0)) #nullified whats needed rects = [] fingers = [] #untuk koordinat finger #temp #draw the magic! if len(contours) != 0: while contours != None: rect = Rect() #boxing the contours rect.line = cv.BoundingRect(contours, 1) #calculate it's wide rect.wide = math.fabs((int(rect.line[2] - rect.line[0]) * int(rect.line[3] - rect.line[1])))
def run(self): frame = cv.QueryFrame(self.capture) frame_size = cv.GetSize(frame) # Capture the first frame from webcam for image properties display_image = cv.QueryFrame(self.capture) # Greyscale image, thresholded to create the motion mask: grey_image = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_8U, 1) # The RunningAvg() function requires a 32-bit or 64-bit image... running_average_image = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_32F, 3) # ...but the AbsDiff() function requires matching image depths: running_average_in_display_color_depth = cv.CloneImage(display_image) # RAM used by FindContours(): mem_storage = cv.CreateMemStorage(0) # The difference between the running average and the current frame: difference = cv.CloneImage(display_image) target_count = 1 last_target_count = 1 last_target_change_t = 0.0 k_or_guess = 1 codebook = [] frame_count = 0 last_frame_entity_list = [] t0 = time.time() # For toggling display: image_list = ["display", "difference", "threshold", "camera", "faces"] image_index = 0 # Index into image_list # Prep for text drawing: text_font = cv.InitFont(cv.CV_FONT_HERSHEY_COMPLEX, .5, .5, 0.0, 1, cv.CV_AA) text_coord = (5, 15) text_color = cv.CV_RGB(255, 255, 255) haar_cascade = cv.Load( '/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml' ) max_targets = 3 while True: camera_image = cv.QueryFrame(self.capture) frame_count += 1 frame_t0 = time.time() # Create an image with interactive feedback: display_image = cv.CloneImage(camera_image) # Create a working "color image" to modify / blur color_image = cv.CloneImage(display_image) # Smooth to get rid of false positives cv.Smooth(color_image, color_image, cv.CV_GAUSSIAN, 19, 0) # Use the Running Average as the static background # a = 0.020 leaves artifacts lingering way too long. # a = 0.320 works well at 320x240, 15fps. (1/a is roughly num frames.) cv.RunningAvg(color_image, running_average_image, 0.420, None) # Convert the scale of the moving average. cv.ConvertScale(running_average_image, running_average_in_display_color_depth, 1.0, 0.0) # Subtract the current frame from the moving average. cv.AbsDiff(color_image, running_average_in_display_color_depth, difference) # Convert the image to greyscale. cv.CvtColor(difference, grey_image, cv.CV_RGB2GRAY) # Threshold the image to a black and white motion mask: cv.Threshold(grey_image, grey_image, 2, 255, cv.CV_THRESH_BINARY) # Smooth and threshold again to eliminate "sparkles" cv.Smooth(grey_image, grey_image, cv.CV_GAUSSIAN, 19, 0) cv.Threshold(grey_image, grey_image, 240, 255, cv.CV_THRESH_BINARY) cv.Dilate(grey_image, grey_image, None, 18) cv.Erode(grey_image, grey_image, None, 20) grey_image_as_array = numpy.asarray(cv.GetMat(grey_image)) non_black_coords_array = numpy.where(grey_image_as_array > 3) # Convert from numpy.where()'s two separate lists to one list of (x, y) tuples: non_black_coords_array = zip(non_black_coords_array[1], non_black_coords_array[0]) points = [ ] # Was using this to hold either pixel coords or polygon coords. bounding_box_list = [] # Now calculate movements using the white pixels as "motion" data contour = cv.FindContours(grey_image, mem_storage, cv.CV_RETR_CCOMP, cv.CV_CHAIN_APPROX_SIMPLE) while contour: bounding_rect = cv.BoundingRect(list(contour)) point1 = (bounding_rect[0], bounding_rect[1]) point2 = (bounding_rect[0] + bounding_rect[2], bounding_rect[1] + bounding_rect[3]) bounding_box_list.append((point1, point2)) polygon_points = cv.ApproxPoly(list(contour), mem_storage, cv.CV_POLY_APPROX_DP) # To track polygon points only (instead of every pixel): #points += list(polygon_points) # Draw the contours: levels = 0 cv.DrawContours(color_image, contour, cv.CV_RGB(255, 0, 0), cv.CV_RGB(0, 255, 0), levels, 3, 0, (0, 0)) cv.FillPoly(grey_image, [ list(polygon_points), ], cv.CV_RGB(255, 255, 255), 0, 0) cv.PolyLine(display_image, [ polygon_points, ], 0, cv.CV_RGB(255, 255, 255), 1, 0, 0) #cv.Rectangle( display_image, point1, point2, cv.CV_RGB(120,120,120), 1) contour = contour.h_next() # Find the average size of the bbox (targets), then # remove any tiny bboxes (which are prolly just noise). # "Tiny" is defined as any box with 1/10th the area of the average box. # This reduces false positives on tiny "sparkles" noise. box_areas = [] for box in bounding_box_list: box_width = box[right][0] - box[left][0] box_height = box[bottom][0] - box[top][0] box_areas.append(box_width * box_height) #cv.Rectangle( display_image, box[0], box[1], cv.CV_RGB(255,0,0), 1) average_box_area = 0.0 if len(box_areas): average_box_area = float(sum(box_areas)) / len(box_areas) trimmed_box_list = [] for box in bounding_box_list: box_width = box[right][0] - box[left][0] box_height = box[bottom][0] - box[top][0] # Only keep the box if it's not a tiny noise box: if (box_width * box_height) > average_box_area * 0.1: trimmed_box_list.append(box) # Draw the trimmed box list: #for box in trimmed_box_list: # cv.Rectangle( display_image, box[0], box[1], cv.CV_RGB(0,255,0), 2 ) bounding_box_list = merge_collided_bboxes(trimmed_box_list) # Draw the merged box list: for box in bounding_box_list: cv.Rectangle(display_image, box[0], box[1], cv.CV_RGB(0, 255, 0), 1) # Here are our estimate points to track, based on merged & trimmed boxes: estimated_target_count = len(bounding_box_list) if frame_t0 - last_target_change_t < .650: # 1 change per 0.35 secs estimated_target_count = last_target_count else: if last_target_count - estimated_target_count > 1: estimated_target_count = last_target_count - 1 if estimated_target_count - last_target_count > 1: estimated_target_count = last_target_count + 1 last_target_change_t = frame_t0 # Clip to the user-supplied maximum: estimated_target_count = min(estimated_target_count, max_targets) points = non_black_coords_array center_points = [] if len(points): k_or_guess = max(estimated_target_count, 1) # Need at least one target to look for. if len(codebook) == estimated_target_count: k_or_guess = codebook #points = vq.whiten(array( points )) # Don't do this! Ruins everything. codebook, distortion = vq.kmeans(array(points), k_or_guess) # Convert to tuples (and draw it to screen) for center_point in codebook: center_point = (int(center_point[0]), int(center_point[1])) center_points.append(center_point) trimmed_center_points = [] removed_center_points = [] for box in bounding_box_list: # Find the centers within this box: center_points_in_box = [] for center_point in center_points: if center_point[0] < box[right][0] and center_point[0] > box[left][0] and \ center_point[1] < box[bottom][1] and center_point[1] > box[top][1] : # This point is within the box. center_points_in_box.append(center_point) # Now see if there are more than one. If so, merge them. if len(center_points_in_box) > 1: # Merge them: x_list = y_list = [] for point in center_points_in_box: x_list.append(point[0]) y_list.append(point[1]) average_x = int(float(sum(x_list)) / len(x_list)) average_y = int(float(sum(y_list)) / len(y_list)) trimmed_center_points.append((average_x, average_y)) # Record that they were removed: removed_center_points += center_points_in_box if len(center_points_in_box) == 1: trimmed_center_points.append( center_points_in_box[0]) # Just use it. # If there are any center_points not within a bbox, just use them. # (It's probably a cluster comprised of a bunch of small bboxes.) for center_point in center_points: if (not center_point in trimmed_center_points) and ( not center_point in removed_center_points): trimmed_center_points.append(center_point) # Determine if there are any new (or lost) targets: actual_target_count = len(trimmed_center_points) last_target_count = actual_target_count # Now build the list of physical entities (objects) this_frame_entity_list = [] # An entity is list: [ name, color, last_time_seen, last_known_coords ] for target in trimmed_center_points: # Is this a target near a prior entity (same physical entity)? entity_found = False entity_distance_dict = {} for entity in last_frame_entity_list: entity_coords = entity[3] delta_x = entity_coords[0] - target[0] delta_y = entity_coords[1] - target[1] distance = sqrt(pow(delta_x, 2) + pow(delta_y, 2)) entity_distance_dict[distance] = entity # Did we find any non-claimed entities (nearest to furthest): distance_list = entity_distance_dict.keys() distance_list.sort() for distance in distance_list: # Yes; see if we can claim the nearest one: nearest_possible_entity = entity_distance_dict[distance] if nearest_possible_entity in this_frame_entity_list: continue # Found the nearest entity to claim: entity_found = True nearest_possible_entity[ 2] = frame_t0 # Update last_time_seen nearest_possible_entity[ 3] = target # Update the new location this_frame_entity_list.append(nearest_possible_entity) break if entity_found == False: # It's a new entity. color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) name = hashlib.md5(str(frame_t0) + str(color)).hexdigest()[:6] last_time_seen = frame_t0 new_entity = [name, color, last_time_seen, target] this_frame_entity_list.append(new_entity) # Now "delete" any not-found entities which have expired: entity_ttl = 1.0 # 1 sec. ent_count = 0 for entity in last_frame_entity_list: last_time_seen = entity[2] if frame_t0 - last_time_seen > entity_ttl: pass else: # Save it for next time... not expired yet: this_frame_entity_list.append(entity) ent_count += 1 # For next frame: last_frame_entity_list = this_frame_entity_list # Draw the found entities to screen: count = 0 if ent_count != 0: entity = this_frame_entity_list[0] center_point = entity[3] c = entity[1] # RGB color tuple # print '%s %d %d %d' % (entity[0], count, center_point[0], center_point[1]) cv.Circle(display_image, center_point, 20, cv.CV_RGB(c[0], c[1], c[2]), 1) cv.Circle(display_image, center_point, 15, cv.CV_RGB(c[0], c[1], c[2]), 1) cv.Circle(display_image, center_point, 10, cv.CV_RGB(c[0], c[1], c[2]), 2) cv.Circle(display_image, center_point, 5, cv.CV_RGB(c[0], c[1], c[2]), 3) text_font = cv.InitFont(cv.CV_FONT_HERSHEY_COMPLEX, .5, .5, 0.0, 1, cv.CV_AA) text_coord = (5, 15) text_color = cv.CV_RGB(255, 255, 255) x = 50 + (center_point[0] * 80 / 320) y = 20 + (center_point[1] * 80 / 240) if self.have_eye: self.ServoMove(0, int(x)) self.ServoMove(1, int(y)) s = '%3.0d %3.0d' % (x, y) cv.PutText(display_image, str(s), text_coord, text_font, text_color) #print "min_size is: " + str(min_size) # Listen for ESC or ENTER key c = cv.WaitKey(7) % 0x100 if c == 27 or c == 10: break # Toggle which image to show if chr(c) == 'd': image_index = (image_index + 1) % len(image_list) image_name = image_list[image_index] # Display frame to user if image_name == "display": image = display_image # cv.PutText( image, "AABBs and contours", text_coord, text_font, text_color ) elif image_name == "camera": image = camera_image cv.PutText(image, "No overlay", text_coord, text_font, text_color) elif image_name == "difference": image = difference cv.PutText(image, "Difference Image", text_coord, text_font, text_color) elif image_name == "faces": # Do face detection detect_faces(camera_image, haar_cascade, mem_storage) image = camera_image # Re-use camera image here cv.PutText(image, "Face Detection", text_coord, text_font, text_color) elif image_name == "threshold": # Convert the image to color. cv.CvtColor(grey_image, display_image, cv.CV_GRAY2RGB) image = display_image # Re-use display image here cv.PutText(image, "Motion Mask", text_coord, text_font, text_color) cv.ShowImage("Target", image) if self.writer: cv.WriteFrame(self.writer, image) frame_t1 = time.time() t1 = time.time() time_delta = t1 - t0 processed_fps = float(frame_count) / time_delta print "Got %d frames. %.1f s. %f fps." % (frame_count, time_delta, processed_fps)