def is_square(contour): """ Squareness checker Square contours should: -have 4 vertices after approximation, -have relatively large area (to filter out noisy contours) -be convex. -have angles between sides close to 90deg (cos(ang) ~0 ) Note: absolute value of an area is used because area may be positive or negative - in accordance with the contour orientation """ area = math.fabs( cv.ContourArea(contour) ) isconvex = cv.CheckContourConvexity(contour) s = 0 if len(contour) == 4 and area > 1000 and isconvex: for i in range(1, 4): # find minimum angle between joint edges (maximum of cosine) pt1 = contour[i] pt2 = contour[i-1] pt0 = contour[i-2] t = math.fabs(angle(pt0, pt1, pt2)) if s <= t:s = t # if cosines of all angles are small (all angles are ~90 degree) # then its a square if s < 0.3:return True return False
def somethingHasMoved(self): # Find contours storage = cv.CreateMemStorage(0) contours = cv.FindContours(self.gray_frame, storage, cv.CV_RETR_EXTERNAL, cv.CV_CHAIN_APPROX_SIMPLE) self.currentcontours = contours #Save contours while contours: #For all contours compute the area self.currentsurface += cv.ContourArea(contours) contours = contours.h_next() avg = (self.currentsurface*100)/self.surface #Calculate the average of contour area on the total size self.currentsurface = 0 #Put back the current surface to 0 if avg > self.threshold: return True else: return False
def verificaMovimento(self): """ Obtem os contornos da imagem cinza e soma a area deles para verificar se ouve diferenca. Caso a soma da area dos contornos seja maior que o "0" retorna True, caso contrario False. """ # Encontra os contornos dos objetos na imagem cinza. contornos = cv.FindContours(self.imagem_cinza, cv.CreateMemStorage(0)) while contornos: self.area_corrente += cv.ContourArea(contornos) contornos = contornos.h_next() # Faco uma media da area corrente. movimentos = (self.area_corrente * 100) / self.area self.area_corrente = 0 if movimentos > 0: return True else: return False
def find(self, img): started = time.time() gray = self.Cached('gray', img.height, img.width, cv.CV_8UC1) cv.CvtColor(img, gray, cv.CV_BGR2GRAY) sobel = self.Cached('sobel', img.height, img.width, cv.CV_16SC1) sobely = self.Cached('sobely', img.height, img.width, cv.CV_16SC1) cv.Sobel(gray, sobel, 1, 0) cv.Sobel(gray, sobely, 0, 1) cv.Add(sobel, sobely, sobel) sobel8 = self.Cached('sobel8', sobel.height, sobel.width, cv.CV_8UC1) absnorm8(sobel, sobel8) cv.Threshold(sobel8, sobel8, 128.0, 255.0, cv.CV_THRESH_BINARY) sobel_integral = self.Cached('sobel_integral', img.height + 1, img.width + 1, cv.CV_32SC1) cv.Integral(sobel8, sobel_integral) d = 16 _x1y1 = cv.GetSubRect( sobel_integral, (0, 0, sobel_integral.cols - d, sobel_integral.rows - d)) _x1y2 = cv.GetSubRect( sobel_integral, (0, d, sobel_integral.cols - d, sobel_integral.rows - d)) _x2y1 = cv.GetSubRect( sobel_integral, (d, 0, sobel_integral.cols - d, sobel_integral.rows - d)) _x2y2 = cv.GetSubRect( sobel_integral, (d, d, sobel_integral.cols - d, sobel_integral.rows - d)) summation = cv.CloneMat(_x2y2) cv.Sub(summation, _x1y2, summation) cv.Sub(summation, _x2y1, summation) cv.Add(summation, _x1y1, summation) sum8 = self.Cached('sum8', summation.height, summation.width, cv.CV_8UC1) absnorm8(summation, sum8) cv.Threshold(sum8, sum8, 32.0, 255.0, cv.CV_THRESH_BINARY) cv.ShowImage("sum8", sum8) seq = cv.FindContours(sum8, cv.CreateMemStorage(), cv.CV_RETR_EXTERNAL) subimg = cv.GetSubRect(img, (d / 2, d / 2, sum8.cols, sum8.rows)) t_cull = time.time() - started seqs = [] while seq: seqs.append(seq) seq = seq.h_next() started = time.time() found = {} print 'seqs', len(seqs) for seq in seqs: area = cv.ContourArea(seq) if area > 1000: rect = cv.BoundingRect(seq) edge = int((14 / 14.) * math.sqrt(area) / 2 + 0.5) candidate = cv.GetSubRect(subimg, rect) sym = self.dm.decode( candidate.width, candidate.height, buffer(candidate.tostring()), max_count=1, #min_edge = 6, #max_edge = int(edge) # Units of 2 pixels ) if sym: onscreen = [(d / 2 + rect[0] + x, d / 2 + rect[1] + y) for (x, y) in self.dm.stats(1)[1]] found[sym] = onscreen else: print "FAILED" t_brute = time.time() - started print "cull took", t_cull, "brute", t_brute return found
def run(self): # Capture first frame to get size frame = cv.QueryFrame(self.capture) frame_size = cv.GetSize(frame) width = frame.width height = frame.height surface = width * height # Surface area of the image cursurface = 0 # Hold the current surface that have changed grey_image = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_8U, 1) moving_average = cv.CreateImage(cv.GetSize(frame), cv.IPL_DEPTH_32F, 3) difference = None while True: color_image = cv.QueryFrame(self.capture) cv.Smooth(color_image, color_image, cv.CV_GAUSSIAN, 3, 0) # Remove false positives if not difference: # For the first time put values in difference, temp and moving_average difference = cv.CloneImage(color_image) temp = cv.CloneImage(color_image) cv.ConvertScale(color_image, moving_average, 1.0, 0.0) else: cv.RunningAvg(color_image, moving_average, 0.020, None) # Compute the average # Convert the scale of the moving average. cv.ConvertScale(moving_average, temp, 1.0, 0.0) # Minus the current frame from the moving average. cv.AbsDiff(color_image, temp, difference) # Convert the image so that it can be thresholded cv.CvtColor(difference, grey_image, cv.CV_RGB2GRAY) cv.Threshold(grey_image, grey_image, 70, 255, cv.CV_THRESH_BINARY) cv.Dilate(grey_image, grey_image, None, 18) # to get object blobs cv.Erode(grey_image, grey_image, None, 10) # Find contours storage = cv.CreateMemStorage(0) contours = cv.FindContours(grey_image, storage, cv.CV_RETR_EXTERNAL, cv.CV_CHAIN_APPROX_SIMPLE) backcontours = contours # Save contours while contours: # For all contours compute the area cursurface += cv.ContourArea(contours) contours = contours.h_next() avg = ( cursurface * 100 ) / surface # Calculate the average of contour area on the total size if avg > self.ceil: print("Something is moving !") ring = IntrusionAlarm() ring.run() # print avg,"%" cursurface = 0 # Put back the current surface to 0 # Draw the contours on the image _red = (0, 0, 255) # Red for external contours _green = (0, 255, 0) # Gren internal contours levels = 1 # 1 contours drawn, 2 internal contours as well, 3 ... cv.DrawContours(color_image, backcontours, _red, _green, levels, 2, cv.CV_FILLED) cv.ShowImage("Virtual Eye", color_image) # Listen for ESC or ENTER key c = cv.WaitKey(7) % 0x100 if c == 27 or c == 10: break elif c == 99: cv2.destroyWindow('Warning!!!')
def somethingHasMoved(self): # Find contours storage = cv.CreateMemStorage(0) contours = cv.FindContours(self.gray_frame, storage, cv.CV_RETR_EXTERNAL, cv.CV_CHAIN_APPROX_SIMPLE) #cv.ShowImage("Image", self.gray_frame) #print(self.gray_frame.width) #print(self.gray_frame.height) alto = self.gray_frame.height ancho = self.gray_frame.width q0 = self.gray_frame[ :ancho/2, :alto/2 ] q1 = self.gray_frame[ ancho/2:, :alto/2 ] q2 = self.gray_frame[ :ancho/2, alto/2: ] q3 = self.gray_frame[ ancho/2:, alto/2: ] q0nz = np.count_nonzero(q0) q1nz = np.count_nonzero(q1) q2nz = np.count_nonzero(q2) q3nz = np.count_nonzero(q3) sys.stdout.write("\033[F") #back to previous line sys.stdout.write("\033[K") #clear line sys.stdout.write("\033[F") #back to previous line sys.stdout.write("\033[K") #clear line sys.stdout.write("\033[F") #back to previous line sys.stdout.write("\033[K") #clear line if q0nz or q1nz or q2nz or q3nz: print("Algo se mueve !") #cambio de estado if q0nz != self.m0: self.m0 = q0nz self.mqtt.publish("0:%i" % (self.m0), 'camaras') if q1nz != self.m1: self.m1 = q1nz self.mqtt.publish("1:%i" % (self.m1), 'camaras') if q2nz != self.m2: self.m2 = q2nz self.mqtt.publish("3:%i" % (self.m2), 'camaras') if q3nz != self.m3: self.m3 = q3nz self.mqtt.publish("2:%i" % (self.m3), 'camaras') else: print("") print("{0} {1}\n{2} {3}".format(blockchar(q0nz),blockchar(q2nz),blockchar(q1nz),blockchar(q3nz))) self.currentcontours = contours #Save contours while contours: #For all contours compute the area self.currentsurface += cv.ContourArea(contours) contours = contours.h_next() avg = (self.currentsurface*100)/self.surface #Calculate the average of contour area on the total size self.currentsurface = 0 #Put back the current surface to 0 #print(avg) if avg > self.threshold: return True else: return False
def try_contour(self): self.total_contours += 1 self.contouri += 1 self.contour_area = cv.ContourArea(self.cur_contour) dbg('Thresh contour %d' % self.contouri, level=2) if self.filter(): dbg(' Rejected: filtered contour b/c area not %f <= %f <= %f' % (self.min_area, self.contour_area, self.max_area)) if draw_thresh_contours: # Purple cv.PolyLine(self.contours_map, [self.cur_contour], True, cv.CV_RGB(128, 0, 128)) return self.checked_contours += 1 #if contouri != 5: # continue #print ' Points:' #print_contour(contour, ' ') contour_len_ = contour_len(self.cur_contour) dbg(' len %f' % contour_len_, level=2) dbg(' area %f' % self.contour_area, level=2) if contour_len_ < self.min_len: dbg(' Rejected: did not meet minimum length w/ %f < %f' % (contour_len_, self.min_len), level=2) if draw_thresh_contours: # red cv.PolyLine(self.contours_map, [self.cur_contour], True, cv.CV_RGB(255, 0, 0)) return this_diff = contour_line_diff(self.cur_contour, self.line) dbg(' diff %f' % this_diff, level=2) if this_diff >= self.best_diff: dbg(" Rejected: worse diff %f >= %f" % (this_diff, self.best_diff), level=2) if draw_thresh_contours: # Teal cv.PolyLine(self.contours_map, [self.cur_contour], True, cv.CV_RGB(0, 128, 128)) return hist_diff = self.compare_ref(self.cur_contour) dbg(" Hist diff: %f" % hist_diff, level=2) # 0.95 was too lose if hist_diff < 0.90: dbg(" Rejected: poor histogram match", level=2) if draw_thresh_contours: # Yellow #cv.PolyLine(self.contours_map, [self.cur_contour], True, cv.CV_RGB(255, 255, 0) ) cv.PolyLine( self.contours_map, [self.cur_contour], True, cv.CV_RGB(random.randint(0, 256), random.randint(0, 256), random.randint(0, 256))) return dbg(' Accepted: new best contour', level=2) self.best_contour = self.cur_contour self.best_thresh = self.cur_thresh self.best_diff = this_diff self.best_hist_diff = hist_diff #draw_contour(self.cur_contour) if draw_thresh_contours: # green cv.PolyLine(self.contours_map, [self.cur_contour], True, cv.CV_RGB(0, 255, 0))
def compare_2_formes(Image1, Image2): mincontour = 500 # minimum size of a form to be detected CVCONTOUR_APPROX_LEVEL = 5 # parameter for call contour img_edge1 = cv.CreateImage(cv.GetSize(Image1), 8, 1) #egde image # img1_8uc3=cv.CreateImage(cv.GetSize(Image1),8,3) img_edge2 = cv.CreateImage(cv.GetSize(Image2), 8, 1) # img2_8uc3=cv.CreateImage(cv.GetSize(Image2),8,3) cv.Threshold(Image1, img_edge1, 123, 255, cv.CV_THRESH_BINARY) # filter threshold cv.Threshold(Image2, img_edge2, 123, 255, cv.CV_THRESH_BINARY) storage1 = cv.CreateMemStorage() storage2 = cv.CreateMemStorage() first_contour1 = cv.FindContours( img_edge1, storage1) # pointer to the first edge of the form 1 first_contour2 = cv.FindContours( img_edge2, storage2) # pointer to the first edge of the form 2 newseq = first_contour1 newseq2 = first_contour2 if not (first_contour1) or not (first_contour2): return 0 current_contour = first_contour1 while 1: current_contour = current_contour.h_next( ) # path in the sequence of edges of the first form if (not (current_contour) ): # stop condition if the contour pointer = NULL break if cv.ContourArea(current_contour) > mincontour: newseq = cv.ApproxPoly(current_contour, storage1, cv.CV_POLY_APPROX_DP, CVCONTOUR_APPROX_LEVEL, 0) # cv.CvtColor(Image1,img1_8uc3,cv.CV_GRAY2BGR ); # cv.DrawContours(img1_8uc3,newseq,cv.CV_RGB(0,255,0),cv.CV_RGB(255,0,0),0,2,8); # cv.NamedWindow("ContourImage2",cv.CV_WINDOW_AUTOSIZE) # cv.ShowImage("ContourImage2",img1_8uc3) current_contour = first_contour2 # path of the second form of contours while 1: current_contour = current_contour.h_next() if (not (current_contour)): break if cv.ContourArea(current_contour) > mincontour: newseq2 = cv.ApproxPoly(current_contour, storage2, cv.CV_POLY_APPROX_DP, CVCONTOUR_APPROX_LEVEL, 0) # cv.CvtColor(Image2,img2_8uc3,cv.CV_GRAY2BGR); # cv.DrawContours(img2_8uc3,newseq2,cv.CV_RGB(0,255,0),cv.CV_RGB(255,0,0),0,2,8); # cv.NamedWindow("ContourImage",cv.CV_WINDOW_AUTOSIZE) # cv.ShowImage("ContourImage",img2_8uc3) matchresult = 1 matchresult = cv.MatchShapes(newseq, newseq2, 1, 2) return matchresult
def findSquares4(img, storage): N = 11 sz = (img.width & -2, img.height & -2) timg = cv.CloneImage(img); # make a copy of input image gray = cv.CreateImage(sz, 8, 1) pyr = cv.CreateImage((sz.width/2, sz.height/2), 8, 3) # create empty sequence that will contain points - # 4 points per square (the square's vertices) squares = cv.CreateSeq(0, sizeof_CvSeq, sizeof_CvPoint, storage) squares = CvSeq_CvPoint.cast(squares) # select the maximum ROI in the image # with the width and height divisible by 2 subimage = cv.GetSubRect(timg, cv.Rect(0, 0, sz.width, sz.height)) # down-scale and upscale the image to filter out the noise cv.PyrDown(subimage, pyr, 7) cv.PyrUp(pyr, subimage, 7) tgray = cv.CreateImage(sz, 8, 1) # find squares in every color plane of the image for c in range(3): # extract the c-th color plane channels = [None, None, None] channels[c] = tgray cv.Split(subimage, channels[0], channels[1], channels[2], None) for l in range(N): # hack: use Canny instead of zero threshold level. # Canny helps to catch squares with gradient shading if(l == 0): # apply Canny. Take the upper threshold from slider # and set the lower to 0 (which forces edges merging) cv.Canny(tgray, gray, 0, thresh, 5) # dilate canny output to remove potential # holes between edge segments cv.Dilate(gray, gray, None, 1) else: # apply threshold if l!=0: # tgray(x, y) = gray(x, y) < (l+1)*255/N ? 255 : 0 cv.Threshold(tgray, gray, (l+1)*255/N, 255, cv.CV_THRESH_BINARY) # find contours and store them all as a list count, contours = cv.FindContours(gray, storage, sizeof_CvContour, cv.CV_RETR_LIST, cv. CV_CHAIN_APPROX_SIMPLE, (0, 0)) if not contours: continue # test each contour for contour in contours.hrange(): # approximate contour with accuracy proportional # to the contour perimeter result = cv.ApproxPoly(contour, sizeof_CvContour, storage, cv.CV_POLY_APPROX_DP, cv.ContourPerimeter(contours)*0.02, 0) # square contours should have 4 vertices after approximation # relatively large area (to filter out noisy contours) # and be convex. # Note: absolute value of an area is used because # area may be positive or negative - in accordance with the # contour orientation if(result.total == 4 and abs(cv.ContourArea(result)) > 1000 and cv.CheckContourConvexity(result)): s = 0 for i in range(5): # find minimum angle between joint # edges (maximum of cosine) if(i >= 2): t = abs(angle(result[i], result[i-2], result[i-1])) if s<t: s=t # if cosines of all angles are small # (all angles are ~90 degree) then write quandrange # vertices to resultant sequence if(s < 0.3): for i in range(4): squares.append(result[i]) return squares