def edge_threshold(image, roi=None, debug=0): thresholded = cv.CloneImage(image) horizontal = cv.CreateImage(cv.GetSize(image), cv.IPL_DEPTH_16S, 1) magnitude32f = cv.CreateImage(cv.GetSize(image), cv.IPL_DEPTH_32F, 1) vertical = cv.CloneImage(horizontal) v_edge = cv.CloneImage(image) magnitude = cv.CloneImage(horizontal) storage = cv.CreateMemStorage(0) mag = cv.CloneImage(image) cv.Sobel(image, horizontal, 0, 1, 1) cv.Sobel(image, vertical, 1, 0, 1) cv.Pow(horizontal, horizontal, 2) cv.Pow(vertical, vertical, 2) cv.Add(vertical, horizontal, magnitude) cv.Convert(magnitude, magnitude32f) cv.Pow(magnitude32f, magnitude32f, 0.5) cv.Convert(magnitude32f, mag) if roi: cv.And(mag, roi, mag) cv.Normalize(mag, mag, 0, 255, cv.CV_MINMAX, None) cv.Threshold(mag, mag, 122, 255, cv.CV_THRESH_BINARY) draw_image = cv.CloneImage(image) and_image = cv.CloneImage(image) results = [] threshold_start = 17 for window_size in range(threshold_start, threshold_start + 1, 1): r = 20 for threshold in range(0, r): cv.AdaptiveThreshold(image, thresholded, 255, \ cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY_INV, window_size, threshold) contour_image = cv.CloneImage(thresholded) contours = cv.FindContours(contour_image, storage, cv.CV_RETR_LIST) cv.Zero(draw_image) cv.DrawContours(draw_image, contours, (255, 255, 255), (255, 255, 255), 1, 1) if roi: cv.And(draw_image, roi, draw_image) cv.And(draw_image, mag, and_image) m1 = np.asarray(cv.GetMat(draw_image)) m2 = np.asarray(cv.GetMat(mag)) total = mag.width * mag.height #cv.Sum(draw_image)[0] coverage = cv.Sum(and_image)[0] / (mag.width * mag.height) if debug: print threshold, coverage cv.ShowImage("main", draw_image) cv.ShowImage("main2", thresholded) cv.WaitKey(0) results.append((coverage, threshold, window_size)) results.sort(lambda x, y: cmp(y, x)) _, threshold, window_size = results[0] cv.AdaptiveThreshold(image, thresholded, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, \ cv.CV_THRESH_BINARY, window_size, threshold) return thresholded
def find_blobs(self, frame, debug_image): '''Find blobs in an image. Hopefully this gets blobs that correspond with buoys, but any intelligent checking is done outside of this function. ''' # Get Channels hsv = cv.CreateImage(cv.GetSize(frame), 8, 3) cv.CvtColor(frame, hsv, cv.CV_BGR2HSV) saturation = libvision.misc.get_channel(hsv, 1) red = libvision.misc.get_channel(frame, 2) # Adaptive Threshold cv.AdaptiveThreshold( saturation, saturation, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY_INV, self.saturation_adaptive_thresh_blocksize - self.saturation_adaptive_thresh_blocksize % 2 + 1, self.saturation_adaptive_thresh, ) cv.AdaptiveThreshold( red, red, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY, self.red_adaptive_thresh_blocksize - self.red_adaptive_thresh_blocksize % 2 + 1, -1 * self.red_adaptive_thresh, ) kernel = cv.CreateStructuringElementEx(9, 9, 4, 4, cv.CV_SHAPE_ELLIPSE) cv.Erode(saturation, saturation, kernel, 1) cv.Dilate(saturation, saturation, kernel, 1) cv.Erode(red, red, kernel, 1) cv.Dilate(red, red, kernel, 1) buoys_filter = cv.CreateImage(cv.GetSize(frame), 8, 1) cv.And(saturation, red, buoys_filter) if debug_image: svr.debug("Saturation", saturation) svr.debug("Red", red) svr.debug("AdaptiveThreshold", buoys_filter) # Get blobs labeled_image = cv.CreateImage(cv.GetSize(buoys_filter), 8, 1) blobs = libvision.blob.find_blobs(buoys_filter, labeled_image, MIN_BLOB_SIZE, 10) return blobs, labeled_image
def process(self, image): image_gray = cv.CreateImage(cv.GetSize(image), cv.IPL_DEPTH_8U, 1) cv.CvtColor(image, image_gray, cv.CV_BGR2GRAY) cv.AdaptiveThreshold(image_gray, image_gray, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY_INV, self.block_size, self.c) return image_gray
def main(): global val1, val2 img = cv.LoadImage(sys.argv[1]) if img: cv.NamedWindow("bar") img2 = cv.CreateImage(cv.GetSize(img), cv.IPL_DEPTH_8U, 1) img21 = cv.CreateImage(cv.GetSize(img), cv.IPL_DEPTH_8U, 1) img3 = cv.CreateImage(cv.GetSize(img), cv.IPL_DEPTH_16S, 1) img4 = cv.CreateImage(cv.GetSize(img), cv.IPL_DEPTH_8U, 1) cv.CvtColor(img, img2, cv.CV_BGR2GRAY) cv.EqualizeHist(img2, img21) stor = cv.CreateMemStorage() cv.AdaptiveThreshold(img21, img4, 255, cv.CV_ADAPTIVE_THRESH_GAUSSIAN_C, cv.CV_THRESH_BINARY_INV, 7, 7) cont = cv.FindContours(img4, stor, cv.CV_RETR_LIST, cv.CV_CHAIN_APPROX_NONE) img5 = cv.CloneImage(img) while cont: if validate_contour(cont): cv.DrawContours(img5, cont, (255, 255, 255), (255, 255, 255), 0, 2, 8, (0, 0)) cont = cont.h_next() cv.ShowImage("bar", img5) cv.WaitKey(0)
def threshold_green(image): #cv.InRange(blurred_image,GREEN_MIN,GREEN_MAX,green_adaptive) cv.AdaptiveThreshold(image, green_adaptive, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY_INV, 101, 40) #25 cv.Erode(green_adaptive, green_eroded_image, None, 5) #9 cv.Dilate(green_eroded_image, green_dilated_image, None, 6) #27
def traitements(img): src = cv.LoadImageM(norm_path+img, 1) dst = cv.CreateImage(cv.GetSize(src), cv.IPL_DEPTH_16S, 3) # --- Corners --- # print "CORNERS" #eig_image = cv.CreateMat(src.rows, src.cols, cv.CV_32FC1) #temp_image = cv.CreateMat(src.rows, src.cols, cv.CV_32FC1) #corners = cv.GoodFeaturesToTrack(src, eig_image, temp_image, 100, 0.04, 1.0, useHarris = True) #affichage_corners(corners, src, 2) #save(traitement_path, img, src) print "FIN CORNERS" # --- Seuil --- # print "SEUIL" src = cv.LoadImageM(norm_path+img, cv.CV_LOAD_IMAGE_GRAYSCALE) cv.AdaptiveThreshold(src,src,255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY_INV, 7, 10) #cv.Erode(src,src,None,1) #cv.Dilate(src,src,None,1) print src[56,56] save(traitement_path, dossier+"seuil."+img, src) print "FIN SEUIL" '''
def threshold_red(image): #bright cv.AdaptiveThreshold(image,red_adaptive,255,cv.CV_ADAPTIVE_THRESH_MEAN_C,cv.CV_THRESH_BINARY,17,-30) cv.AdaptiveThreshold(image, red_adaptive, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY, 17, -14) cv.Erode(red_adaptive, red_eroded_image, None, 1) cv.Dilate(red_eroded_image, red_dilated_image, None, 5)
def main(): """Parse the command line and set off processing.""" # parse command line opts,args = getopt(sys.argv[1:], "i") if len(args) != 1: syntax() return 1 # grab options invert = False for n,v in opts: if n == '-i': invert = True # load image grey = prepare_image(args[0], invert) size = cv.GetSize(grey) # a bit of smoothing to reduce noise smoothed = cv.CreateImage(size, cv.IPL_DEPTH_8U, 1) cv.Smooth(grey, smoothed, cv.CV_GAUSSIAN, 5, 5) # adaptive thresholding finds the letters against the numberplate # background thresholded = cv.CloneImage(grey) cv.AdaptiveThreshold(smoothed, thresholded, 255, cv.CV_ADAPTIVE_THRESH_GAUSSIAN_C, cv.CV_THRESH_BINARY_INV, 19, 9) # use a hough transform to find straight edges in the image and then # remove them - removes number plate edges to ensure that characters # don't join with the edges of the plate storage = cv.CreateMemStorage() #lines = cv.HoughLines2(thresholded, storage, cv.CV_HOUGH_PROBABILISTIC, # 1, math.pi/180, 50, 50, 2) #for line in lines: # cv.Line(thresholded, line[0], line[1], 0, 3, 4) # grab the contours from the image cont = cv.FindContours(thresholded, storage, cv.CV_RETR_CCOMP, cv.CV_CHAIN_APPROX_NONE) # grab 'good' contours col = 128 validated = [] while cont: v = validate_contour(cont,grey) if v is not None: validated.append(v) cont = cont.h_next() # overlay bounding boxes of 'good' contours on the original image result = cv.LoadImage(args[0]) clusters = cluster_fuck(set(validated)) for cluster in clusters: cv.Rectangle(result, (int(min([c.x1 for c in cluster])), int(min([c.y1 for c in cluster]))), (int(max([c.x2 for c in cluster])), int(max([c.y2 for c in cluster]))), (0,0,255)) for bbox in cluster: cv.Rectangle(result, (int(bbox.x1),int(bbox.y1)), (int(bbox.x2), int(bbox.y2)), (255,0,0)) quick_show(result)
def treatments(img): # --- Seuil --- # cv.AdaptiveThreshold(img, img, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY_INV, 7, 10) #cv.Erode(src,src,None,1) #cv.Dilate(src,src,None,1) return img
def threshhold(img): bwdst = cv.CreateImage(cv.GetSize(img), cv.IPL_DEPTH_8U, 1) cv.CvtColor(img, bwdst, cv.CV_BGR2GRAY) cv.AdaptiveThreshold(bwdst, bwdst, 255.0, cv.CV_THRESH_BINARY, cv.CV_ADAPTIVE_THRESH_MEAN_C, 11) cv.Dilate(bwdst, bwdst) cv.Erode(bwdst, bwdst) return bwdst
def channel_processing(channel): pass cv.AdaptiveThreshold(channel, channel, 255, adaptive_method=cv.CV_ADAPTIVE_THRESH_MEAN_C, thresholdType=cv.CV_THRESH_BINARY, blockSize=55, param1=7) #mop up the dirt cv.Dilate(channel, channel, None, 1) cv.Erode(channel, channel, None, 1)
def comptage_pixel_sur_image(src, div = 8): res = [] largeur = NORM_W/div hauteur = NORM_H/div cv.AdaptiveThreshold(src,src,255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY_INV, 7, 10) # div*div images de largeur NORM_W/div for l in range(0, NORM_W, largeur): for h in range(0, NORM_H, hauteur): nb_pixel = 0 for l2 in range(largeur): for h2 in range(hauteur): # On prend le premier du pixel (niveau de gris => R=G=B #print src[l+l2,h+h2] if(src[l+l2,h+h2] > 128) : nb_pixel += 1 res.append(nb_pixel) return res
def NormalizeImage(cvmat, cilp_rect, perspective_points): u'''読み取りやすくするために画像を正規化する''' # 液晶部分の抽出 lcd = cv.CreateMat(cilp_rect.height, cilp_rect.width, cv.CV_8UC3) cv.GetRectSubPix(cvmat, lcd, (cilp_rect.cx, cilp_rect.cy)) # グレイスケール化 grayed = cv.CreateMat(lcd.height, lcd.width, cv.CV_8UC1) cv.CvtColor(lcd, grayed, cv.CV_BGR2GRAY) # 適応的2値化 filterd = cv.CreateMat(grayed.height, grayed.width, cv.CV_8UC1) cv.AdaptiveThreshold( grayed, filterd, 255, adaptive_method=cv.CV_ADAPTIVE_THRESH_GAUSSIAN_C, thresholdType=cv.CV_THRESH_BINARY, blockSize=15, ) # ゆがみ補正 transformed = cv.CreateMat(grayed.height, grayed.width, filterd.type) matrix = cv.CreateMat(3, 3, cv.CV_32F) cv.GetPerspectiveTransform( ((perspective_points.tl.x, perspective_points.tl.y), (perspective_points.tr.x, perspective_points.tr.y), (perspective_points.bl.x, perspective_points.bl.y), (perspective_points.br.x, perspective_points.br.y)), ((0, 0), (filterd.width, 0), (0, filterd.height), (filterd.width, filterd.height)), matrix) cv.WarpPerspective( filterd, transformed, matrix, flags=cv.CV_WARP_FILL_OUTLIERS, fillval=255, ) return transformed
def threshold_image(pil_image, file_name): cv_i = piltocv(pil_image) #calculate_histogram(pil_image) #split channels: r = cv.CreateImage(cv.GetSize(cv_i), cv_i.depth, 1) g = cv.CreateImage(cv.GetSize(cv_i), cv_i.depth, 1) b = cv.CreateImage(cv.GetSize(cv_i), cv_i.depth, 1) #cv.Histogram(r) #cv.Split(cv_i, r, g, b, None) #return #calculate image brightness: cv_brightness = cv.CreateImage(cv.GetSize(cv_i), cv_i.depth, 1) cv.AddWeighted(r, 1./3., g, 1./3., 0.0, cv_brightness) cv.AddWeighted(cv_brightness, 2./3., b, 1./3., 0.0, cv_brightness) cv_union = cv.CreateImage(cv.GetSize(cv_i), cv_i.depth, 1) cv.Set(cv_union, cv.CV_RGB(0, 0, 0)); band_names = ['r','g','b'] idx = 0 cutoff = 15 print cv.GetSize(cv_i), cv_i.depth for band in [r, g, b]: dst = cv.CreateImage(cv.GetSize(cv_i), cv_i.depth, 1) cv.AdaptiveThreshold(band, dst, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY, 75, 10) cv.SaveImage("%sthresh_%s_%s.png" % \ (path, 'adaptive', band_names[idx]), dst) '''for threshold in range(0, 21, 1): dst = cv.CreateImage(cv.GetSize(cv_i), cv_i.depth, 1) #cv.Threshold(band, dst, threshold, 255, cv.CV_THRESH_BINARY ) cv.AdaptiveThreshold(band, dst, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY, 25, 1) if threshold == cutoff: cv.Or(cv_union, dst, cv_union) cv.SaveImage("/usr/local/django/localground/jobs/stats/canny/thresh_%s_%s.png" % \ (band_names[idx], threshold), dst)''' idx += 1 cv.SaveImage("/usr/local/django/localground/jobs/stats/canny/%s_mask.png" % file_name, cv_union)
def preprocess(image, otsu_thresh=False): """Pre-process an image ready for character contour detection.""" size = cv.GetSize(image) # convert to single channel grey = extract_v(image) # maximise contrast max_grey = max_contrast(grey) # a bit of smoothing to reduce noise smoothed = cv.CreateImage(size, cv.IPL_DEPTH_8U, 1) cv.Smooth(max_grey, smoothed, cv.CV_GAUSSIAN, SMOOTH_FILTER_SIZE) # adaptive thresholding finds the letters against the numberplate # background thresholded = cv.CreateImage(size, cv.IPL_DEPTH_8U, 1) if otsu_thresh: cv.Threshold(smoothed, thresholded, 0, 255, cv.CV_THRESH_BINARY_INV | cv.CV_THRESH_OTSU) else: cv.AdaptiveThreshold(smoothed, thresholded, 255, cv.CV_ADAPTIVE_THRESH_GAUSSIAN_C, cv.CV_THRESH_BINARY_INV, ADAPTIVE_THRESH_BLOCK_SIZE, ADAPTIVE_THRESH_WEIGHT) return grey, thresholded
def threshold_rock(image): cv.AdaptiveThreshold(image,rock_adaptive,255,cv.CV_ADAPTIVE_THRESH_MEAN_C,cv.CV_THRESH_BINARY,203,-46) cv.Erode(rock_adaptive,rock_eroded,None,3) cv.Dilate(rock_eroded,rock_dilated,None,6)
def detect(image, debug=False, display=None): work_image = cv.CreateImage((image.width, image.height), 8, 1) cv.CvtColor(image, work_image, cv.CV_BGR2GRAY) image = work_image edge = cv.CloneImage(image) thresholded = cv.CloneImage(image) v_edges = cv.CloneImage(image) h_edges = cv.CloneImage(image) vertical = cv.CreateImage(cv.GetSize(image), cv.IPL_DEPTH_16S, 1) cv.Sobel(image, vertical, 1, 0, 1) cv.Abs(vertical, vertical) cv.Convert(vertical, v_edges) storage = cv.CreateMemStorage(0) result = np.asarray(cv.GetMat(v_edges), dtype=np.float) threshold = 6 rects = [] while len(rects) < 1 and threshold > 0: rects = [] cv.Convert(vertical, v_edges) cv.AdaptiveThreshold(v_edges, v_edges, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY_INV, 17, threshold) threshold -= 1 storage = cv.CreateMemStorage(0) contour_image = cv.CloneImage(v_edges) contours = cv.FindContours(contour_image, storage, cv.CV_RETR_LIST, cv.CV_CHAIN_APPROX_NONE, (0, 0)) ext.filter_contours(contours, 30, ext.LESSTHAN) max_size = int(image.width * image.height * 0.1) # ext.filter_contours(contours, 200**2, ext.GREATERTHAN) ext.filter_contours(contours, max_size, ext.GREATERTHAN) if display: cv.Merge(v_edges, v_edges, v_edges, None, display) seeds = [] if contours: seq = contours rects = [] while seq: c = ext.as_contour(ext.wrapped(seq)) r = (c.rect.x, c.rect.y, c.rect.width, c.rect.height) rects.append(r) if display: cv.Rectangle( display, (c.rect.x, c.rect.y), (c.rect.x + c.rect.width, c.rect.y + c.rect.height), (0, 0, 255), 1) seq = seq.h_next() rects.sort(lambda x, y: cmp(x[0] + x[2] / 2, y[0] + y[2] / 2)) seeds = rects[:] seeds.sort(lambda x, y: cmp(y[2] * y[3], x[2] * x[3])) groups = [] skip = False for seed in seeds: if seed not in rects: break found = False for group in groups: if seed in group: found = True if found: continue r = seed start = seed start_index = rects.index(seed) groups.append([seed]) i = start_index - 1 # delta = max(150, seed[2]/2) delta = seed[2] * 0.66 if debug: print "left", seed, delta col = (randint(0, 255), randint(0, 255), randint(0, 255)) cv.Rectangle(display, (r[0], r[1]), (r[0] + r[2], r[1] + r[3]), (255, 255, 255), 3) cv.Rectangle(display, (r[0], r[1]), (r[0] + r[2], r[1] + r[3]), col, -1) cv.ShowImage("main", display) if not skip: c = cv.WaitKey(0) if c == ord("a"): skip = True # scan left while 1: if i < 0: break rect = rects[i] if rect[0] + rect[2] < seed[0] - delta: if debug: print "esc1", rect break if in_vertical(seed, start, rect): seed = rect groups[-1].append(rect) r = rect if debug: print rect cv.Rectangle(display, (r[0], r[1]), (r[0] + r[2], r[1] + r[3]), col, -1) cv.ShowImage("main", display) if not skip: c = cv.WaitKey(0) if c == ord("a"): skip = True else: if debug: print "rej1", rect i -= 1 # scan right seed = start start_index = rects.index(seed) i = start_index + 1 if debug: print print "right", seed while 1: if i >= len(rects): break rect = rects[i] if rect[0] > seed[0] + seed[2] + delta: if debug: print "esc2", rect, rect[0] + rect[2] / 2, seed[ 0] + seed[2] / 2 + delta break if in_vertical(seed, start, rect): seed = rect groups[-1].append(rect) r = rect if debug: print rect cv.Rectangle(display, (r[0], r[1]), (r[0] + r[2], r[1] + r[3]), col, -1) cv.ShowImage("main", display) if not skip: c = cv.WaitKey(0) if c == ord("a"): skip = True else: if debug: print "rej2", rect i += 1 if debug: print # find min and max extent of group group_rects = [] for group in groups: min_x, min_y = 1E6, 1E6 max_x, max_y = -1, -1 dev = [] col = (randint(0, 255), randint(0, 255), randint(0, 255)) for rect in group: r = rect if display: if r == group[0]: cv.Rectangle(display, (r[0], r[1]), (r[0] + r[2], r[1] + r[3]), (255, 255, 255), 3) cv.Rectangle(display, (r[0], r[1]), (r[0] + r[2], r[1] + r[3]), col, -1) min_x = min(min_x, r[0]) min_y = min(min_y, r[1]) max_x = max(max_x, r[0] + r[2]) max_y = max(max_y, r[1] + r[3]) if display: cv.Rectangle(display, (min_x, min_y), (max_x, max_y), (0, 255, 0), 1) width = max_x - min_x height = max_y - min_y rect = (min_x, min_y, width, height) group_rects.append(rect) return group_rects
def segment_rect(image, rect, debug=False, display=None, target_size=None, group_range=(3, 25)): global next skip = False best_chars = [] best_threshold = None thresholded = cv.CloneImage(image) contour_image = cv.CloneImage(image) edges = cv.CloneImage(image) min_x, min_y, width, height = rect # cv.SetImageROI(thresholded, rect) cv.SetImageROI(contour_image, rect) cv.SetImageROI(image, rect) cv.SetImageROI(edges, rect) horizontal = cv.CreateImage(cv.GetSize(image), cv.IPL_DEPTH_16S, 1) magnitude32f = cv.CreateImage(cv.GetSize(image), cv.IPL_DEPTH_32F, 1) vertical = cv.CloneImage(horizontal) magnitude = cv.CloneImage(horizontal) cv.Sobel(image, horizontal, 0, 1, 3) cv.Sobel(image, vertical, 1, 0, 3) cv.Pow(horizontal, horizontal, 2) cv.Pow(vertical, vertical, 2) cv.Add(vertical, horizontal, magnitude) cv.Convert(magnitude, magnitude32f) cv.Pow(magnitude32f, magnitude32f, 0.5) cv.Convert(magnitude32f, edges) original_rect = rect if display: cv.SetImageROI(display, rect) for threshold in range(1, 20, 1): cv.SetImageROI(thresholded, original_rect) #for i in range(30, 60, 1): if display: cv.Merge(image, image, image, None, display) cv.Copy(image, thresholded) #cv.Threshold(thresholded, thresholded, i, 255, cv.CV_THRESH_BINARY_INV) cv.AdaptiveThreshold(thresholded, thresholded, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY_INV, 17, threshold) #cv.AdaptiveThreshold(thresholded, thresholded, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY_INV, 5, i) # skip rects greater than 50% thresholded summed = cv.Norm(thresholded, None, cv.CV_L1, None) / 255 / thresholded.width / thresholded.height if summed > 0.5: continue if debug: cv.ShowImage("edge", thresholded) storage = cv.CreateMemStorage(0) cv.Copy(thresholded, contour_image) contours = cv.FindContours(contour_image, storage, cv.CV_RETR_LIST, cv.CV_CHAIN_APPROX_SIMPLE, (0, 0)) ext.filter_contours(contours, 20, ext.LESSTHAN) groups = [] rects = [] edge_counts = [] overlappings = {} if contours: seq = contours while seq: c = ext.as_contour(ext.wrapped(seq)) r = (c.rect.x, c.rect.y, c.rect.width, c.rect.height) rects.append(r) seq = seq.h_next() similarity = 0.45 #0.3 rects.sort(lambda x, y: cmp(y[2] * y[3], x[2] * x[3])) for rect in rects: if debug: print print "R", rect, len(groups) cv.SetImageROI(edges, (original_rect[0] + rect[0], original_rect[1] + rect[1], rect[2], rect[3])) edge_count = cv.Sum(edges)[0] / 255 / (rect[2] * rect[3]) edge_counts.append(edge_count) # cv.ShowImage("edges", edges) # cv.WaitKey(0) if debug and target_size: print "X", target_size, rect print(target_size[0] - rect[2]) / target_size[0] print(target_size[1] - rect[3]) / target_size[1] if rect[2] > rect[3] or float(rect[3])/rect[2] < 3./3 or edge_count < 0.1\ or (rect[2] == image.width and rect[3] == image.height) \ or (target_size and not 0 < (target_size[0] - rect[2]) / target_size[0] < 0.3 \ and not 0 < (target_size[1] - rect[3]) / target_size[1] < 0.05): if debug: print "rej", rect[2], ">", rect[3], "edge=", edge_count cv.Rectangle(display, (rect[0], rect[1]), (rect[0] + rect[2], rect[1] + rect[3]), (0, 0, 255), 1) cv.ShowImage("main", display) if not skip and not next: c = cv.WaitKey(0) if c == ord("a"): skip = True if c == ord("z"): next = True continue added = False for group_id, group in enumerate(groups): avg_width, avg_height, avg_y = 0, 0, 0 overlap = None c = 0 for r in group: avg_y += r[1] + r[3] / 2.0 avg_width += r[2] avg_height += r[3] irect = intersect(r, rect) if irect[2] * irect[3] > 0.2 * r[2] * r[3]: overlappings.setdefault(group_id, []).append([r, rect]) avg_y /= float(len(group)) avg_width /= float(len(group)) avg_height /= float(len(group)) if debug: print group if (abs(avg_width - rect[2]) / avg_width < similarity or \ (rect[2] < avg_width)) and \ abs(avg_height - rect[3])/ avg_height < similarity and \ abs(avg_y - (rect[1] + rect[3]/2.0)) / avg_y < similarity: group.append(rect) added = True else: pass if not added: # first char in group groups.append([rect]) if debug: print "now:" for g in groups: print g cv.Rectangle(display, (rect[0], rect[1]), (rect[0] + rect[2], rect[1] + rect[3]), (255, 0, 0), 1) cv.ShowImage("main", display) if not skip and not next: c = cv.WaitKey(0) if c == ord("a"): skip = True if c == ord("z"): next = True if groups: #handle overlapping regions, default to average width match for group_id, over in overlappings.items(): group = groups[group_id] avg_width = 0 avg_height = 0 for r in group: avg_width += r[2] avg_height += r[3] avg_width /= float(len(group)) avg_height /= float(len(group)) for r1, r2 in over: if r2 not in group or r1 not in group: continue if debug: print "over", r1, r2, r1[2] * r1[3], r2[2] * r2[ 3], avg_width d1 = abs(r1[2] - avg_width) + abs(r1[3] - avg_height) d2 = abs(r2[2] - avg_width) + abs(r2[3] - avg_height) if d1 < d2: group.remove(r2) else: group.remove(r1) #group = max(groups, key=len) # from longest groups, find largest area groups.sort(key=len) groups.reverse() max_area = 0 mad_index = -1 for i, g in enumerate(groups[:5]): area = 0 for r in g: area += r[2] * r[3] if area > max_area: max_area = area max_index = i group = groups[max_index] # vertical splitting avg_width, avg_height, avg_y = 0, 0, 0 if debug: print "G", group for r in group: avg_y += r[1] + r[3] / 2.0 avg_width += r[2] avg_height += r[3] avg_y /= float(len(group)) avg_width /= float(len(group)) avg_height /= float(len(group)) band_rects = [] bound = bounding_rect(group) for i, rect in enumerate(rects): if edge_counts[i] < 0.1: continue if (abs(avg_width - rect[2]) / avg_width < similarity or \ (rect[2] < avg_width)) and \ (abs(avg_height - rect[3]) / avg_height < similarity or \ (rect[3] < avg_height)) and \ abs(avg_y - (rect[1] + rect[3]/2.0)) < avg_height/2: band_rects.append(rect) band_rects.sort(lambda x, y: cmp(y[2] * y[3], x[2] * x[3])) for i, rect_a in enumerate(band_rects[:-1]): if rect_a[2] * rect_a[3] < 0.2 * avg_width * avg_height: continue merge_rects = [] for rect_b in band_rects[i + 1:]: w = avg_width m1 = rect_a[0] + rect_a[2] / 2 m2 = rect_b[0] + rect_b[2] / 2 if abs(m1 - m2) < w: merge_rects.append(rect_b) if debug: print "M", merge_rects if merge_rects: merge_rects.append(rect_a) rect = bounding_rect(merge_rects) area = 0 for r in merge_rects: area += r[2] * r[3] if (abs(avg_width - rect[2]) / avg_width < similarity or \ (rect[2] < avg_width)) and \ abs(avg_height - rect[3])/ avg_height < similarity and \ area > 0.5*(avg_width*avg_height) and \ abs(avg_y - (rect[1] + rect[3]/2.0)) / avg_y < similarity: for r in merge_rects: if r in group: group.remove(r) # merge into group new_group = [] merged = False for gr in group: area2 = max(gr[2] * gr[3], rect[2] * rect[3]) isect = intersect(gr, rect) if isect[2] * isect[3] > 0.4 * area2: x = min(gr[0], rect[0]) y = min(gr[1], rect[1]) x2 = max(gr[0] + gr[2], rect[0] + rect[2]) y2 = max(gr[1] + gr[3], rect[1] + rect[3]) new_rect = (x, y, x2 - x, y2 - y) new_group.append(new_rect) merged = True else: new_group.append(gr) if not merged: new_group.append(rect) group = new_group cv.Rectangle(display, (rect[0], rect[1]), (rect[0] + rect[2], rect[1] + rect[3]), (255, 0, 255), 2) # avoid splitting split = False # select higher threshold if innovates significantly best_width = 0.0 if best_chars: best_area = 0.0 for rect in best_chars: best_area += rect[2] * rect[3] best_width += rect[2] best_width /= len(best_chars) area = 0.0 overlapped = 0.0 avg_width = 0.0 avg_height = 0.0 for rect in group: area += rect[2] * rect[3] avg_width += rect[2] avg_height += rect[3] for char in best_chars: section = intersect(rect, char) if section[2] * section[3] > 0: overlapped += section[2] * section[3] avg_width /= len(group) avg_height /= len(group) quotient = overlapped / area quotient2 = (area - overlapped) / best_area if debug: print area, overlapped, best_area print group print "QUO", quotient print "QUO2", quotient2 else: quotient = 0 quotient2 = 1 best_area = 0 group.sort(lambda x, y: cmp(x[0] + x[2] / 2, y[0] + y[2] / 2)) best_chars.sort(lambda x, y: cmp(x[0] + x[2] / 2, y[0] + y[2] / 2)) if group_range[0] <= len(group) <= group_range[1] and avg_width > 5 and avg_height > 10 and \ ((quotient2 > 0.05 and (best_area == 0 or abs(area - best_area)/best_area < 0.4)) or (quotient2 > 0.3 and area > best_area)): if debug: print "ASSIGNED", group best_chars = group best_threshold = threshold #get_patch(thresholded, original_rect) else: if debug: print "not", quotient2, len( group), avg_width, avg_height, area, best_area # best_chars = groups if debug: for rect in best_chars: cv.Rectangle(display, (rect[0], rect[1]), (rect[0] + rect[2], rect[1] + rect[3]), (0, 255, 0), 1) cv.ShowImage("main", display) if not skip and not next: c = cv.WaitKey(0) if c == ord("a"): skip = True if c == ord("z"): next = True best_chars.sort(lambda x, y: cmp(x[0], y[0])) cv.ResetImageROI(thresholded) cv.ResetImageROI(contour_image) cv.ResetImageROI(image) cv.ResetImageROI(edges) if display: cv.ResetImageROI(display) return best_chars, best_threshold
def process_frame(self, frame): debug_frame = cv.CreateImage(cv.GetSize(frame), 8, 3) cv.Copy(frame, debug_frame) cv.Smooth(frame, frame, cv.CV_MEDIAN, 7, 7) # Set binary image to have saturation channel hsv = cv.CreateImage(cv.GetSize(frame), 8, 3) binary = cv.CreateImage(cv.GetSize(frame), 8, 1) cv.CvtColor(frame, hsv, cv.CV_BGR2HSV) cv.SetImageCOI(hsv, 2) cv.Copy(hsv, binary) cv.SetImageCOI(hsv, 0) cv.AdaptiveThreshold( binary, binary, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY_INV, self.adaptive_thresh_blocksize, self.adaptive_thresh, ) # Morphology kernel = cv.CreateStructuringElementEx(5, 5, 3, 3, cv.CV_SHAPE_ELLIPSE) cv.Erode(binary, binary, kernel, 1) cv.Dilate(binary, binary, kernel, 1) # Get Edges #cv.Canny(binary, binary, 30, 40) cv.CvtColor(binary, debug_frame, cv.CV_GRAY2RGB) # Hough Transform line_storage = cv.CreateMemStorage() raw_lines = cv.HoughLines2(binary, line_storage, cv.CV_HOUGH_STANDARD, rho=1, theta=math.pi / 180, threshold=self.hough_threshold, param1=0, param2=0) line_groups = [] # A list of line groups which are each a line list for line in raw_lines: group_found = False for line_group in line_groups: if line_group_accept_test(line_group, line, self.max_range): line_group.append(line) group_found = True if not group_found: line_groups.append([line]) # Average line groups into lines lines = [] for line_group in line_groups: rhos = map(lambda line: line[0], line_group) angles = map(lambda line: line[1], line_group) line = (sum(rhos) / len(rhos), circular_average(angles, math.pi)) lines.append(line) libvision.misc.draw_lines(debug_frame, raw_lines) # cv.CvtColor(color_filtered,debug_frame, cv.CV_GRAY2RGB) svr.debug("Bins", debug_frame)
def process_frame(self, frame): ################ #setup CV ###### ################ print "processing frame" (w, h) = cv.GetSize(frame) #generate hue selection frames ones = np.ones((h, w, 1), dtype='uint8') a = ones * (180 - self.target_hue) b = ones * (180 - self.target_hue + 20) a_array = cv.fromarray(a) b_array = cv.fromarray(b) #create locations for the test frame and binary frame frametest = cv.CreateImage(cv.GetSize(frame), 8, 3) binarytest = cv.CreateImage(cv.GetSize(frame), 8, 1) #use the red channel for the binary frame (just for debugging purposes) cv.Copy(frame, frametest) cv.SetImageCOI(frametest, 3) cv.Copy(frametest, binarytest) #reset the COI for test frame to RGB. cv.SetImageCOI(frametest, 0) # Resize image to 320x240 #copy = cv.CreateImage(cv.GetSize(frame), 8, 3) #cv.Copy(frame, copy) #cv.SetImageROI(frame, (0, 0, 320, 240)) #cv.Resize(copy, frame, cv.CV_INTER_NN) found_gate = False #create a new frame for comparison purposes unchanged_frame = cv.CreateImage(cv.GetSize(frame), 8, 3) cv.Copy(frame, unchanged_frame) #apply noise filter #1 cv.Smooth(frame, frame, cv.CV_MEDIAN, 7, 7) # Set binary image to have saturation channel hsv = cv.CreateImage(cv.GetSize(frame), 8, 3) binary = cv.CreateImage(cv.GetSize(frame), 8, 1) cv.CvtColor(frame, hsv, cv.CV_BGR2HSV) cv.SetImageCOI(hsv, 1) cv.Copy(hsv, binary) #spin the color wheel (psuedo-code for later if necessary) # truncate spectrum marked as end # shift all values up based on truncating value (mask out 0 regions) # take truncated bits, and flip them (180->0, 179->1...) # dnow that truncated bits are flipped, add them back in to final image #Reset hsv COI cv.SetImageCOI(hsv, 0) #correct for wraparound on red spectrum cv.InRange(binary, a_array, b_array, binarytest) #generate mask cv.Add(binary, cv.fromarray(ones * 180), binary, mask=binarytest) #use mask to selectively add values #run adaptive threshold for edge detection cv.AdaptiveThreshold( binary, binary, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY_INV, self.adaptive_thresh_blocksize, self.adaptive_thresh, ) # Morphology kernel = cv.CreateStructuringElementEx(5, 5, 3, 3, cv.CV_SHAPE_ELLIPSE) cv.Erode(binary, binary, kernel, 1) cv.Dilate(binary, binary, kernel, 1) if self.debug: color_filtered = cv.CloneImage(binary) # Get Edges cv.Canny(binary, binary, 30, 40) # Hough Transform line_storage = cv.CreateMemStorage() raw_lines = cv.HoughLines2(binary, line_storage, cv.CV_HOUGH_STANDARD, rho=1, theta=math.pi / 180, threshold=self.hough_threshold, param1=0, param2=0) # Get vertical lines vertical_lines = [] i = 0 for line in raw_lines: if line[1] < self.vertical_threshold or \ line[1] > (math.pi-self.vertical_threshold): #absolute value does better grouping currently vertical_lines.append((abs(line[0]), line[1])) i += 1 # print message to user for performance purposes logging.debug("{} possibilities reduced to {} lines".format( i, len(vertical_lines))) # Group vertical lines vertical_line_groups = [ ] #A list of line groups which are each a line list i = 0 for line in vertical_lines: group_found = False for line_group in vertical_line_groups: i += 1 if line_group_accept_test(line_group, line, self.max_range): line_group.append(line) group_found = True if not group_found: vertical_line_groups.append([line]) #quick debugging statement logging.debug("{} internal iterations for {} groups".format( i, len(vertical_line_groups))) # Average line groups into lines vertical_lines = [] for line_group in vertical_line_groups: rhos = map(lambda line: line[0], line_group) #get rho of each line angles = map(lambda line: line[1], line_group) line = (sum(rhos) / len(rhos), circular_average(angles, math.pi)) vertical_lines.append(line) self.left_pole = None self.right_pole = None self.returning = 0 self.found = False if len(vertical_lines) is 2: roi = cv.GetImageROI(frame) width = roi[2] height = roi[3] self.left_pole = round( min(vertical_lines[0][0], vertical_lines[1][0]), 2) - width / 2 self.right_pole = round( max(vertical_lines[0][0], vertical_lines[1][0]), 2) - width / 2 self.returning = (self.left_pole + self.right_pole) / 2 logging.info("Returning {}".format(self.returning)) #If this is first iteration, count this as seeing the gate if self.last_seen < 0: self.last_center = None self.last_seen = 0 #increment a counter if result is good. if self.last_center is None: self.last_center = self.returning self.seen_count = 1 elif math.fabs(self.last_center - self.returning) < self.center_trans_thresh: self.seen_count += 1 self.last_seen += 2 else: self.last_seen -= 1 #if not convinced, forget left/right pole. Else, proclaim success. if self.seen_count < self.seen_count_thresh: self.left_pole = None self.right_pole = None else: print "FOUND CENTER AND RETURNED IT" self.found = True else: self.returning = 0 if self.last_seen < 0: self.last_center = None self.last_seen = 0 self.last_seen -= 1 self.left_pole = None self.right_POLE = None #extra debugging stuff if self.debug: cv.CvtColor(color_filtered, frame, cv.CV_GRAY2RGB) libvision.misc.draw_lines(frame, vertical_lines) if self.found: cv.Circle(frame, (int(frame.width / 2 + self.returning), int(frame.height / 2)), 15, (0, 255, 0), 2, 8, 0) font = cv.InitFont(cv.CV_FONT_HERSHEY_SIMPLEX, 1, 1, 1, 3) cv.PutText(frame, "Gate Sent to Mission Control", (100, 400), font, (255, 255, 0)) #print frame.width #cv.ShowImage("Gate", cv.CloneImage(frame)) svr.debug("Gate", cv.CloneImage(frame)) svr.debug("Unchanged", cv.CloneImage(unchanged_frame)) self.return_output()
def scanReceipt(file_name): #load image - eventually pass as argument to python image = cv.LoadImage(RECEIPT_PATH + file_name) image_size = cv.GetSize(image) if not image: print "Error opening image" sys.exit(1) #cv.NamedWindow('output',cv.CV_WINDOW_NORMAL) #cv.ShowImage('output',image) #cv.WaitKey() #convert to grayscale grayscale = cv.CreateImage(cv.GetSize(image), 8, 1) cv.CvtColor(image, grayscale, cv.CV_RGB2GRAY) #cv.ShowImage('output',grayscale) #cv.WaitKey() #binarize mask_size = min(image_size[0], image_size[1]) mask_size = int(round(mask_size * 0.01)) mask_size = max(mask_size, 3) if mask_size % 2 == -0: mask_size = mask_size + 1 binary = cv.CreateImage(cv.GetSize(grayscale), cv.IPL_DEPTH_8U, 1) cv.AdaptiveThreshold(grayscale, binary, 255, cv.CV_ADAPTIVE_THRESH_GAUSSIAN_C, cv.CV_THRESH_BINARY, mask_size, 10) #cv.ShowImage('output',binary) #cv.WaitKey() #pre-processing [remove blobs of size 1] cv.SaveImage('TempBin' + file_name, binary) im = scipy.misc.imread('TempBin' + file_name, flatten=1) im[im > 100] = 255 im[im <= 100] = 0 im = 255 - im mask = [[1, 1, 1], [1, 1, 1], [1, 1, 1]] blob, num_blob = ndimage.label(im, structure=mask) blob_sizes = ndimage.sum(im, blob, range(num_blob + 1)) #clean up small blobs small_blob = blob_sizes < 5e3 remove_small_blob = small_blob[blob] im[remove_small_blob] = 0 #connect large blobs struct2 = ndimage.generate_binary_structure(2, 2) im2 = ndimage.binary_dilation(im, structure=struct2, iterations=1).astype(im.dtype) #clean up large blobs blob2, num_blob2 = ndimage.label(im2, structure=mask) blob2_sizes = ndimage.sum(im, blob2, range(num_blob2 + 1)) large_blob = blob2_sizes > 200e3 remove_large_blob = large_blob[blob2] #im2[remove_large_blob] = 0 #cv.DestroyWindow('output') #write to image scipy.misc.imsave('FinalBin' + file_name, im2) image = cv.LoadImage('FinalBin' + file_name) #do OCR api = tesseract.TessBaseAPI() api.Init(".", "eng", tesseract.OEM_DEFAULT) api.SetPageSegMode(tesseract.PSM_AUTO) tesseract.SetCvImage(image, api) text = api.GetUTF8Text() conf = api.AllWordConfidences() print(type(text)) print 'Output of OCR machine:' print text
files = os.listdir('data/examples') counter = 0 for f in files: image = cv.LoadImage('data/examples/' + f) for plate in anpr.detect_plates(image): zzz = cv.CreateImage(cv.GetSize(plate), cv.IPL_DEPTH_8U, 3) cv.Smooth(plate, zzz) # cv.PyrMeanShiftFiltering(plate, zzz, 40, 15) foo = anpr.greyscale(plate) segmented = cv.CreateImage(cv.GetSize(plate), cv.IPL_DEPTH_8U, 1) bar = cv.CreateImage(cv.GetSize(plate), cv.IPL_DEPTH_8U, 1) cv.EqualizeHist(foo, segmented) cv.AdaptiveThreshold( segmented, bar, 255, cv.CV_ADAPTIVE_THRESH_GAUSSIAN_C, cv.CV_THRESH_BINARY_INV, plate.height % 2 == 0 and (plate.height + 1) or plate.height, plate.height / 2) baz = cv.CreateImage(cv.GetSize(plate), cv.IPL_DEPTH_8U, 1) el = cv.CreateStructuringElementEx(1, 2, 0, 0, cv.CV_SHAPE_RECT) cv.Erode(bar, baz, el) #quick_show(plate) #quick_show(segmented) #quick_show(bar) quick_show(baz) for char in anpr.find_characters(foo, baz): cv.Rectangle(plate, (int(char.x1), int(char.y1)), (int(char.x2), int(char.y2)), (255, 0, 0)) quick_show(plate)
from numpy import median def wait(): while True: k = cv.WaitKey(0) % 0x100 if k == 27: break fname = sys.argv[1] original= cv.LoadImage(fname) img = cv.CreateImage( cv.GetSize(original), cv.IPL_DEPTH_8U, 1) cv.CvtColor(original,img, cv.CV_BGR2GRAY) cv.AdaptiveThreshold(img, img, 255.0, cv.CV_THRESH_BINARY, cv.CV_ADAPTIVE_THRESH_MEAN_C,9) # down-scale and upscale the image to filter out the noise pyr = cv.CreateImage((img.width/2, img.height/2), cv.IPL_DEPTH_8U, 1) cv.PyrDown(img, pyr, 7) cv.PyrUp(pyr, img, 7) cv.Smooth(img, img, cv.CV_MEDIAN, 1, 5 ) #cv.Dilate(img,img,None,1) #cv.Erode(img,img,None,1) cv.AdaptiveThreshold(img, img, 255.0, cv.CV_THRESH_BINARY, cv.CV_ADAPTIVE_THRESH_MEAN_C,9)
def threshold_scissors(image): cv.AdaptiveThreshold(image,scissors_adaptive,255,cv.CV_ADAPTIVE_THRESH_MEAN_C,cv.CV_THRESH_BINARY,203,-116) cv.Erode(scissors_adaptive,scissors_eroded,None,3) cv.Dilate(scissors_eroded,scissors_dilated,None,6)
def process_frame(self, frame, debug=True): """ process this frame, then place output in self.output """ if debug: # display frame svr.debug("Frame", frame) # create a new image, the size of frame gray = cv.CreateImage(cv.GetSize(frame), 8, 1) edge = cv.CreateImage(cv.GetSize(frame), 8, 1) lines = cv.CloneImage(frame) # copy BW frame into binary cv.CvtColor(frame, gray, cv.CV_BGR2GRAY) # Get Edges cv.Canny(gray, edge, 60, 80) # Create a Binary Image binary = cv.CreateImage(cv.GetSize(frame), 8, 1) # Run Adaptive Threshold cv.AdaptiveThreshold(gray, binary, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY_INV, 19, 4, ) # display adaptive threshold svr.debug("Thresh", binary) # Hough Transform line_storage = cv.CreateMemStorage() raw_lines = cv.HoughLines2(edge, line_storage, cv.CV_HOUGH_STANDARD, rho=1, theta=math.pi / 180, threshold=50, param1=0, param2=0 ) # process line data found_lines = [] for line in raw_lines[:10]: found_lines.append((abs(line[0]), line[1])) print found_lines # display our transformed image svr.debug("Edges", edge) # draw found lines libvision.misc.draw_lines(lines, found_lines) # display image with lines svr.debug("Lines", lines) cv.WaitKey(10) self.output = "test data"
def process_frame(self, frame): (w, h) = cv.GetSize(frame) #generate hue selection frames #create locations for the a pair of test frames frametest = cv.CreateImage(cv.GetSize(frame), 8, 3) binarytest = cv.CreateImage(cv.GetSize(frame), 8, 1) #use the red channel for the binary frame (just for debugging purposes) cv.Copy(frame, frametest) cv.SetImageCOI(frametest, 3) cv.Copy(frametest, binarytest) cv.SetImageCOI(frametest, 0) #reset COI #svr.debug("R?",binarytest) # Resize image to 320x240 #copy = cv.CreateImage(cv.GetSize(frame), 8, 3) #cv.Copy(frame, copy) #cv.SetImageROI(frame, (0, 0, 320, 240)) #cv.Resize(copy, frame, cv.CV_INTER_NN) found_gate = False #create a new frame just for comparison purposes unchanged_frame = cv.CreateImage(cv.GetSize(frame), 8, 3) cv.Copy(frame, unchanged_frame) #apply a course noise filter cv.Smooth(frame, frame, cv.CV_MEDIAN, 7, 7) # Set binary image to have saturation channel hsv = cv.CreateImage(cv.GetSize(frame), 8, 3) binary = cv.CreateImage(cv.GetSize(frame), 8, 1) cv.CvtColor(frame, hsv, cv.CV_BGR2HSV) cv.SetImageCOI(hsv, 1) cv.Copy(hsv, binary) cv.SetImageCOI(hsv, 0) #reset COI #shift hue of image such that orange->red are at top of spectrum ''' binary = libvision.misc.cv_to_cv2(binary) binary = libvision.misc.shift_hueCV2(binary, self.target_shift) binary = libvision.misc.cv2_to_cv(binary) ''' #correct for wraparound on red spectrum #cv.InRange(binary,a_array,b_array,binarytest) #generate mask #cv.Add(binary,cv.fromarray(ones*180),binary,mask=binarytest) #use mask to selectively add values svr.debug("R2?", binary) svr.debug("R2?", binary) #run adaptive threshold for edge detection and more noise filtering cv.AdaptiveThreshold( binary, binary, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY_INV, self.adaptive_thresh_blocksize, self.adaptive_thresh, ) # Morphology kernel = cv.CreateStructuringElementEx(5, 5, 3, 3, cv.CV_SHAPE_ELLIPSE) cv.Erode(binary, binary, kernel, 1) cv.Dilate(binary, binary, kernel, 1) if self.debug: color_filtered = cv.CloneImage(binary) # Get Edges cv.Canny(binary, binary, 30, 40) # Hough Transform line_storage = cv.CreateMemStorage() raw_lines = cv.HoughLines2(binary, line_storage, cv.CV_HOUGH_STANDARD, rho=1, theta=math.pi / 180, threshold=self.hough_threshold, param1=0, param2=0) # Get vertical lines vertical_lines = [] for line in raw_lines: if line[1] < self.vertical_threshold or \ line[1] > math.pi-self.vertical_threshold: #absolute value does better grouping currently vertical_lines.append((abs(line[0]), line[1])) #print message to user for performance purposes logging.debug("{} possibilities reduced to {} lines".format( len(raw_lines), len(vertical_lines))) # Group vertical lines vertical_line_groups = [ ] # A list of line groups which are each a line list i = 0 for line in vertical_lines: group_found = False for line_group in vertical_line_groups: i += 1 if line_group_accept_test(line_group, line, self.max_range): line_group.append(line) group_found = True if not group_found: vertical_line_groups.append([line]) #quick debugging statement logging.debug("{} internal iterations for {} groups".format( i, len(vertical_line_groups))) # Average line groups into lines vertical_lines = [] for line_group in vertical_line_groups: rhos = map(lambda line: line[0], line_group) angles = map(lambda line: line[1], line_group) line = (sum(rhos) / len(rhos), circular_average(angles, math.pi)) vertical_lines.append(line) #################################################### #vvvv Horizontal line code isn't used for anything # Get horizontal lines horizontal_lines = [] for line in raw_lines: dist_from_horizontal = (math.pi / 2 + line[1]) % math.pi if dist_from_horizontal < self.horizontal_threshold or \ dist_from_horizontal > math.pi-self.horizontal_threshold: horizontal_lines.append((abs(line[0]), line[1])) # Group horizontal lines horizontal_line_groups = [ ] # A list of line groups which are each a line list for line in horizontal_lines: group_found = False for line_group in horizontal_line_groups: if line_group_accept_test(line_group, line, self.max_range): line_group.append(line) group_found = True if not group_found: horizontal_line_groups.append([line]) if len(horizontal_line_groups) is 1: self.seen_crossbar = True if self.debug: rhos = map(lambda line: line[0], horizontal_line_groups[0]) angles = map(lambda line: line[1], horizontal_line_groups[0]) line = (sum(rhos) / len(rhos), circular_average(angles, math.pi)) horizontal_lines = [line] else: self.seen_crossbar = False horizontal_lines = [] #^^^ Horizontal line code isn't used for anything ################################################### self.left_pole = None self.right_pole = None #print vertical_lines self.returning = 0 self.found = False if len(vertical_lines) is 2: roi = cv.GetImageROI(frame) width = roi[2] height = roi[3] self.left_pole = round( min(vertical_lines[0][0], vertical_lines[1][0]), 2) - width / 2 self.right_pole = round( max(vertical_lines[0][0], vertical_lines[1][0]), 2) - width / 2 self.returning = (self.left_pole + self.right_pole) / 2 logging.info("Returning {} as gate center delta.".format( self.returning)) #initialize first iteration with 2 known poles if self.last_seen < 0: self.last_center = None self.last_seen = 0 #increment a counter if result is good. if self.last_center is None: self.last_center = self.returning self.seen_count = 1 elif math.fabs(self.last_center - self.returning) < self.center_trans_thresh: self.seen_count += 1 self.last_seen += 2 else: self.last_seen -= 1 #if not conviced, forget left/right pole. Else proclaim success. if self.seen_count < self.seen_count_thresh: self.left_pole = None self.right_pole = None else: print "FOUND CENTER AND RETURNED IT" self.found = True else: self.returning = 0 if self.last_seen < 0: self.last_center = None self.last_seen = 0 self.last_seen -= 1 self.left_pole = None self.right_pole = None #TODO: If one pole is seen, is it left or right pole? if self.debug: cv.CvtColor(color_filtered, frame, cv.CV_GRAY2RGB) libvision.misc.draw_lines(frame, vertical_lines) libvision.misc.draw_lines(frame, horizontal_lines) if self.found: cv.Circle(frame, (int(frame.width / 2 + self.returning), int(frame.height / 2)), 15, (0, 255, 0), 2, 8, 0) font = cv.InitFont(cv.CV_FONT_HERSHEY_SIMPLEX, 1, 1, 1, 3) cv.PutText(frame, "Gate Sent to Mission Control", (100, 400), font, (255, 255, 0)) #print frame.width #cv.ShowImage("Gate", cv.CloneImage(frame)) svr.debug("Gate", cv.CloneImage(frame)) svr.debug("Unchanged", cv.CloneImage(unchanged_frame)) #populate self.output with infos self.output.seen_crossbar = self.seen_crossbar self.output.left_pole = self.left_pole self.output.right_pole = self.right_pole self.return_output()
Converted to Python by Abid.K --mail me at [email protected] ''' ######################################################################################## import cv, sys # this time input is given at commandline like this: python example_5_4.py <imagename> filename = str(sys.argv[1]) # load grayscale image img = cv.LoadImage(filename, cv.CV_LOAD_IMAGE_GRAYSCALE) img_th = cv.CreateImage((img.width, img.height), cv.IPL_DEPTH_8U, 1) img_adth = cv.CreateImage((img.width, img.height), cv.IPL_DEPTH_8U, 1) cv.NamedWindow("Input Image") cv.NamedWindow("Threshold") cv.NamedWindow("Adaptive Threshold") # thresholding and adaptive threshold cv.Threshold(img, img_th, 100, 255, cv.CV_THRESH_BINARY_INV) cv.AdaptiveThreshold(img, img_adth, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY_INV, 3, 5) cv.ShowImage("Input Image", img) cv.ShowImage("Threshold", img_th) cv.ShowImage("Adaptive Threshold", img_adth) if cv.WaitKey(0) % 0x100 == 27: # waiting for esc key cv.DestroyWindow("Input Image") cv.DestroyWindow("Threshold") cv.DestroyWindow("Adaptive Threshold")
def threshold_purple(image): cv.AdaptiveThreshold(image, purple_adaptive, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY, 43, -9) cv.Erode(purple_adaptive, purple_eroded_image, None, 1) cv.Dilate(purple_adaptive, purple_dilated_image, None, 1)
def process_frame(self, frame): self.debug_frame = cv.CreateImage(cv.GetSize(frame), 8, 3) self.test_frame = cv.CreateImage(cv.GetSize(frame), 8, 3) cv.Copy(frame, self.debug_frame) cv.Copy(frame, self.test_frame) cv.Smooth(frame, frame, cv.CV_MEDIAN, 7, 7) # Set binary image to have saturation channel hsv = cv.CreateImage(cv.GetSize(frame), 8, 3) binary = cv.CreateImage(cv.GetSize(frame), 8, 1) cv.CvtColor(frame, hsv, cv.CV_BGR2HSV) cv.SetImageCOI(hsv, 1) cv.Copy(hsv, binary) cv.SetImageCOI(hsv, 0) # Adaptive Threshold cv.AdaptiveThreshold(binary, binary, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY_INV, self.adaptive_thresh_blocksize, self.adaptive_thresh, ) # Morphology kernel = cv.CreateStructuringElementEx(5, 5, 3, 3, cv.CV_SHAPE_ELLIPSE) cv.Erode(binary, binary, kernel, 1) cv.Dilate(binary, binary, kernel, 1) cv.CvtColor(binary, self.debug_frame, cv.CV_GRAY2RGB) # Find Corners temp1 = cv.CreateImage(cv.GetSize(frame), 8, 1) temp2 = cv.CreateImage(cv.GetSize(frame), 8, 1) self.corners = cv.GoodFeaturesToTrack(binary, temp1, temp2, self.max_corners, self.quality_level, self.min_distance, None, self.good_features_blocksize, 0, 0.4) # Display Corners for corner in self.corners: corner_color = (0, 0, 255) text_color = (0, 255, 0) font = cv.InitFont(cv.CV_FONT_HERSHEY_SIMPLEX, .6, .6, 0, 1, 1) cv.Circle(self.debug_frame, (int(corner[0]), int(corner[1])), 15, corner_color, 2, 8, 0) # Find Candidates for confirmed in self.confirmed: confirmed.corner1_repl_check = 0 confirmed.corner2_repl_check = 0 confirmed.corner3_repl_check = 0 confirmed.corner4_repl_check = 0 for corner in self.corners: if math.fabs(confirmed.corner1[0] - corner[0]) < self.MaxCornerTrans and \ math.fabs(confirmed.corner1[1] - corner[1]) < self.MaxCornerTrans: confirmed.corner1_repl_check = 1 confirmed.corner1_repl = corner elif math.fabs(confirmed.corner2[0] - corner[0]) < self.MaxCornerTrans and \ math.fabs(confirmed.corner2[1] - corner[1]) < self.MaxCornerTrans: confirmed.corner2_repl_check = 1 confirmed.corner2_repl = corner elif math.fabs(confirmed.corner3[0] - corner[0]) < self.MaxCornerTrans and \ math.fabs(confirmed.corner3[1] - corner[1]) < self.MaxCornerTrans: confirmed.corner3_repl_check = 1 confirmed.corner3_repl = corner elif math.fabs(confirmed.corner4[0] - corner[0]) < self.MaxCornerTrans and \ math.fabs(confirmed.corner4[1] - corner[1]) < self.MaxCornerTrans: confirmed.corner4_repl_check = 1 confirmed.corner4_repl = corner if confirmed.corner4_repl_check == 1 and confirmed.corner3_repl_check == 1 and confirmed.corner2_repl_check == 1 and confirmed.corner1_repl_check == 1: confirmed.corner1 = confirmed.corner1_repl confirmed.corner2 = confirmed.corner2_repl confirmed.corner3 = confirmed.corner3_repl confirmed.corner4 = confirmed.corner4_repl confirmed.midx = rect_midpointx(confirmed.corner1, confirmed.corner2, confirmed.corner3, confirmed.corner4) confirmed.midy = rect_midpointy(confirmed.corner1, confirmed.corner2, confirmed.corner3, confirmed.corner4) if confirmed.last_seen < self.last_seen_max: confirmed.last_seen += 5 for corner1 in self.corners: for corner2 in self.corners: for corner3 in self.corners: for corner4 in self.corners: # Checks that corners are not the same and are in the proper orientation if corner4[0] != corner3[0] and corner4[0] != corner2[0] and corner4[0] != corner1[0] and \ corner3[0] != corner2[0] and corner3[0] != corner1[0] and corner2[0] != corner1[0] and \ corner4[1] != corner3[1] and corner4[1] != corner2[1] and corner4[1] != corner1[1] and \ corner3[1] != corner2[1] and corner3[1] != corner1[1] and corner2[1] != corner1[1] and \ corner2[0] >= corner3[0] and corner1[1] >= corner4[1] and corner2[0] >= corner1[0]: # Checks that the side ratios are correct if math.fabs(line_distance(corner1, corner3) - line_distance(corner2, corner4)) < self.size_threshold and \ math.fabs(line_distance(corner1, corner2) - line_distance(corner3, corner4)) < self.size_threshold and \ math.fabs(line_distance(corner1, corner3) / line_distance(corner1, corner2)) < self.ratio_threshold or \ math.fabs(line_distance(corner1, corner2) / line_distance(corner1, corner3)) < self.ratio_threshold: # Checks that angles are roughly 90 degrees angle_cnr_2 = math.fabs(angle_between_lines(line_slope(corner1, corner2), line_slope(corner2, corner4))) if self.angle_min < angle_cnr_2 < self.angle_max: angle_cnr_3 = math.fabs(angle_between_lines(line_slope(corner1, corner3), line_slope(corner3, corner4))) if self.angle_min2 < angle_cnr_3 < self.angle_max2: new_bin = Bin(corner1, corner2, corner3, corner4) self.match_bins(new_bin) self.sort_bins() ''' #START SHAPE PROCESSING #TODO load these ONCE somewhere samples = np.loadtxt('generalsamples.data',np.float32) responses = np.loadtxt('generalresponses.data',np.float32) responses = responses.reshape((responses.size,1)) model = cv2.KNearest() model.train(samples,responses) for bin in self.confirmed: try: bin.speedlimit except: continue transf = cv.CreateMat(3, 3, cv.CV_32FC1) corner_orders = [ [bin.corner1, bin.corner2, bin.corner3, bin.corner4], #0 degrees [bin.corner4, bin.corner3, bin.corner2, bin.corner1], #180 degrees [bin.corner2, bin.corner4, bin.corner1, bin.corner3], #90 degrees [bin.corner3, bin.corner1, bin.corner4, bin.corner2], #270 degrees [bin.corner3, bin.corner4, bin.corner1, bin.corner2], #0 degrees and flipped X [bin.corner2, bin.corner1, bin.corner4, bin.corner3], #180 degrees and flipped X [bin.corner1, bin.corner3, bin.corner2, bin.corner4], #90 degrees and flipped X [bin.corner4, bin.corner2, bin.corner3, bin.corner1]] #270 degrees andf flipped X for i in range(0, 8): cv.GetPerspectiveTransform( corner_orders[i], [(0, 0), (0, 256), (128, 0), (128, 256)], transf ) shape = cv.CreateImage([128, 256], 8, 3) cv.WarpPerspective(frame, shape, transf) shape_thresh = np.zeros((256-104,128,1), np.uint8) j = 104 while j<256: i = 0 while i<128: pixel = cv.Get2D(shape, j, i) if int(pixel[2]) > (int(pixel[1]) + int(pixel[0])) * 0.7: shape_thresh[j-104,i] = 255 else: shape_thresh[j-104,i] = 0 i = i+1 j = j+1 cv2.imshow("Bin " + str(i), shape_thresh) contours,hierarchy = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_NONE) for cnt in contours: if cv2.contourArea(cnt)>50: [x,y,w,h] = cv2.boundingRect(cnt) if h>54 and w>36: roi = thresh[y:y+h,x:x+w] roismall = cv2.resize(roi,(10,10)) roismall = roismall.reshape((1,100)) roismall = np.float32(roismall) retval, results, neigh_resp, dists = model.find_nearest(roismall, k = 1) digit_tuples.append( (x, int((results[0][0]))) ) if len(digit_tuples) == 2: digit_tuples_sorted = sorted(digit_tuples, key=lambda digit_tuple: digit_tuple[0]) speedlimit = 0 for i in range(0, len(digit_tuples_sorted)): speedlimit = speedlimit * 10 + digit_tuples_sorted[i][1] bin.speedlimit = speedlimit print "Found speed limit: " + str(speedlimit) break else: print "Unable to determine speed limit" #... TODO more #END SHAPE PROCESSING ''' svr.debug("Bins", self.debug_frame) svr.debug("Bins2", self.test_frame) # Output bins self.output.bins = self.confirmed anglesum = 0 for bins in self.output.bins: bins.theta = (bins.midx - frame.width / 2) * 37 / (frame.width / 2) bins.phi = -1 * (bins.midy - frame.height / 2) * 36 / (frame.height / 2) bins.shape = bins.object anglesum += bins.angle # bins.orientation = bins.angle if len(self.output.bins) > 0: self.output.orientation = anglesum / len(self.output.bins) else: self.output.orientation = None self.return_output()
def process_frame(self, frame): self.debug_frame = cv.CreateImage(cv.GetSize(frame), 8, 3) og_frame = cv.CreateImage(cv.GetSize(frame), 8, 3) cv.Copy(frame, self.debug_frame) cv.Copy(self.debug_frame, og_frame) cv.Smooth(frame, frame, cv.CV_MEDIAN, 7, 7) # Set binary image to have saturation channel hsv = cv.CreateImage(cv.GetSize(frame), 8, 3) binary = cv.CreateImage(cv.GetSize(frame), 8, 1) cv.CvtColor(frame, hsv, cv.CV_BGR2HSV) cv.SetImageCOI(hsv, 1) #3 before competition #2 at competition cv.Copy(hsv, binary) cv.SetImageCOI(hsv, 0) cv.AdaptiveThreshold(binary, binary, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY_INV, self.adaptive_thresh_blocksize, self.adaptive_thresh, ) # Morphology kernel = cv.CreateStructuringElementEx(5, 5, 3, 3, cv.CV_SHAPE_ELLIPSE) cv.Erode(binary, binary, kernel, 1) cv.Dilate(binary, binary, kernel, 1) # Get Edges #cv.Canny(binary, binary, 30, 40) cv.CvtColor(binary, self.debug_frame, cv.CV_GRAY2RGB) # Hough Transform line_storage = cv.CreateMemStorage() raw_lines = cv.HoughLines2(binary, line_storage, cv.CV_HOUGH_PROBABILISTIC, rho=1, theta=math.pi / 180, threshold=self.hough_threshold, param1=self.min_length, param2=self.max_gap ) lines = [] for line in raw_lines: lines.append(line) #Grouping lines depending on endpoint similarities for line1 in lines[:]: for line2 in lines[:]: if line1 in lines and line2 in lines and line1 != line2: if math.fabs(line1[0][0] - line2[0][0]) < self.max_corner_range and \ math.fabs(line1[0][1] - line2[0][1]) < self.max_corner_range and \ math.fabs(line1[1][0] - line2[1][0]) < self.max_corner_range and \ math.fabs(line1[1][1] - line2[1][1]) < self.max_corner_range: if line_distance(line1[0], line1[1]) > line_distance(line2[0], line2[1]): lines.remove(line2) else: lines.remove(line1) elif math.fabs(line1[0][0] - line2[1][0]) < self.max_corner_range and \ math.fabs(line1[0][1] - line2[1][1]) < self.max_corner_range and \ math.fabs(line1[1][0] - line2[0][0]) < self.max_corner_range and \ math.fabs(line1[1][1] - line2[0][1]) < self.max_corner_range: if line_distance(line1[0], line1[1]) > line_distance(line2[0], line2[1]): lines.remove(line2) else: lines.remove(line1) self.hough_corners = [] for line in lines: self.hough_corners.append(line[0]) self.hough_corners.append(line[1]) for corner1 in self.hough_corners[:]: for corner2 in self.hough_corners[:]: if corner1 is not corner2 and corner1 in self.hough_corners and corner2 in self.hough_corners: if math.fabs(corner1[0] - corner2[0]) < self.max_corner_range4 and \ math.fabs(corner1[1] - corner2[1]) < self.max_corner_range4: corner1 = [(corner1[0] + corner2[0]) / 2, (corner1[1] + corner2[1]) / 2] self.hough_corners.remove(corner2) for line1 in lines: #cv.Line(self.debug_frame,line1[0],line1[1], (0,0,255), 10, cv.CV_AA, 0) for line2 in lines: if line1 is not line2: self.find_corners(line1, line2) for corner1 in self.corners: for corner2 in self.corners: if math.fabs(corner1[1][0] - corner2[1][0]) < self.max_corner_range2 and \ math.fabs(corner1[1][1] - corner2[1][1]) < self.max_corner_range2 and \ math.fabs(corner1[2][0] - corner2[2][0]) < self.max_corner_range2 and \ math.fabs(corner1[2][1] - corner2[2][1]) < self.max_corner_range2 and \ math.fabs(corner1[0][0] - corner2[0][0]) > self.max_corner_range2 and \ math.fabs(corner1[0][1] - corner2[0][1]) > self.max_corner_range2: pt1 = (int(corner1[0][0]), int(corner1[0][1])) pt4 = (int(corner2[0][0]), int(corner2[0][1])) pt3 = (int(corner1[1][0]), int(corner1[1][1])) pt2 = (int(corner1[2][0]), int(corner1[2][1])) #line_color = (0,255,0)s #cv.Line(self.debug_frame,pt1,pt2, line_color, 10, cv.CV_AA, 0) #cv.Line(self.debug_frame,pt1,pt3, line_color, 10, cv.CV_AA, 0) #cv.Line(self.debug_frame,pt4,pt2, line_color, 10, cv.CV_AA, 0) #cv.Line(self.debug_frame,pt4,pt3, line_color, 10, cv.CV_AA, 0) new_bin = Bin(pt1, pt2, pt3, pt4) new_bin.id = self.bin_id self.bin_id += 1 if math.fabs(line_distance(pt1, pt2) - line_distance(pt3, pt4)) < self.parallel_sides_length_thresh and \ math.fabs(line_distance(pt1, pt3) - line_distance(pt2, pt4)) < self.parallel_sides_length_thresh: self.Bins.append(new_bin) print "new_bin" elif (math.fabs(corner1[1][0] - corner2[2][0]) < self.max_corner_range2 and math.fabs(corner1[1][1] - corner2[2][1]) < self.max_corner_range2 and math.fabs(corner1[2][0] - corner2[1][0]) < self.max_corner_range2 and math.fabs(corner1[2][1] - corner2[1][1]) < self.max_corner_range2 and math.fabs(corner1[0][0] - corner2[0][0]) > self.max_corner_range2 and math.fabs(corner1[0][1] - corner2[0][1]) > self.max_corner_range2): continue self.corners = [] self.final_corners = self.sort_corners() #Results are not used. Experimental corners which have been seen twice, should be only the corners we want, but there were problems self.sort_bins() self.update_bins() self.group_bins() self.draw_bins() for corner in self.hough_corners: line_color = [255, 0, 0] cv.Circle(self.debug_frame, corner, 15, (255, 0, 0), 2, 8, 0) for line in lines: line_color = [255, 0, 0] cv.Line(self.debug_frame, line[0], line[1], line_color, 5, cv.CV_AA, 0) #cv.Circle(self.debug_frame, line[0], 15, (255,0,0), 2,8,0) #cv.Circle(self.debug_frame, line[1], 15, (255,0,0), 2,8,0) #Output bins self.output.bins = self.Bins anglesum = 0 for bins in self.output.bins: bins.theta = (bins.center[0] - frame.width / 2) * 37 / (frame.width / 2) bins.phi = -1 * (bins.center[1] - frame.height / 2) * 36 / (frame.height / 2) anglesum += bins.angle # bins.orientation = bins.angle if len(self.output.bins) > 0: self.output.orientation = anglesum / len(self.output.bins) else: self.output.orientation = None self.return_output() svr.debug("Bins", self.debug_frame) svr.debug("Original", og_frame) #BEGIN SHAPE PROCESSING #constants img_width = 128 img_height = 256 number_x = 23 number_y = 111 number_w = 82 number_h = 90 bin_thresh_blocksize = 11 bin_thresh = 1.9 red_significance_threshold = 0.4 #load templates - run once, accessible to number processor number_templates = [ (10, cv.LoadImage("number_templates/10.png")), (16, cv.LoadImage("number_templates/16.png")), (37, cv.LoadImage("number_templates/37.png")), (98, cv.LoadImage("number_templates/98.png")), ] #Begin Bin Contents Processing for bin in self.Bins: #Take the bin's corners, and get an image containing an img_width x img_height rectangle of it transf = cv.CreateMat(3, 3, cv.CV_32FC1) cv.GetPerspectiveTransform( [bin.corner1, bin.corner2, bin.corner3, bin.corner4], [(0, 0), (0, img_height), (img_width, 0), (img_width, img_height)], transf ) bin_image = cv.CreateImage([img_width, img_height], 8, 3) cv.WarpPerspective(frame, bin_image, transf) #AdaptaveThreshold to get black and white image highlighting the number (still works better than my yellow-vs-red threshold attempt hsv = cv.CreateImage(cv.GetSize(bin_image), 8, 3) bin_thresh_image = cv.CreateImage(cv.GetSize(bin_image), 8, 1) cv.CvtColor(bin_image, hsv, cv.CV_BGR2HSV) cv.SetImageCOI(hsv, 3) cv.Copy(hsv, bin_thresh_image) cv.SetImageCOI(hsv, 0) cv.AdaptiveThreshold(bin_thresh_image, bin_thresh_image, 255, cv.CV_ADAPTIVE_THRESH_MEAN_C, cv.CV_THRESH_BINARY_INV, bin_thresh_blocksize, bin_thresh, ) kernel = cv.CreateStructuringElementEx(5, 5, 3, 3, cv.CV_SHAPE_ELLIPSE) cv.Erode(bin_thresh_image, bin_thresh_image, kernel, 1) cv.Dilate(bin_thresh_image, bin_thresh_image, kernel, 1) #Here, we loop through all four different templates, and figure out which one we think is most likely. #The comparison function counts corresponding pixels that are non-zero in each image, and then corresponding pixels that are different in each image. The ratio of diff_count/both_count is our "unconfidence" ratio. The lower it is, the more confident we are. #There are two nearly identical pieces of code within this loop. One checks the bin right-side-up, and the other one checks it flipped 180. last_thought_number = -1 last_unconfidence_ratio = number_w * number_h + 2 for i in range(0, len(number_templates)): both_count = 0 diff_count = 0 this_number_image = number_templates[i][1] for y in range(0, number_h): for x in range(0, number_w): if (bin_thresh_image[y + number_y, x + number_x] != 0) and (this_number_image[y, x][0] != 0): both_count += 1 elif (bin_thresh_image[y + number_y, x + number_x] != 0) or (this_number_image[y, x][0] != 0): diff_count += 1 if both_count == 0: unconfidence_ratio = number_w * number_h + 1 # max unconfidence else: unconfidence_ratio = 1.0 * diff_count / both_count if unconfidence_ratio < last_unconfidence_ratio: last_thought_number = number_templates[i][0] last_unconfidence_ratio = unconfidence_ratio both_count = 0 diff_count = 0 for y in range(0, number_h): for x in range(0, number_w): if (bin_thresh_image[img_height - number_y - 1 - y, img_width - number_x - 1 - x] != 0) and ( this_number_image[y, x][0] != 0): both_count += 1 elif (bin_thresh_image[img_height - number_y - 1 - y, img_width - number_x - 1 - x] != 0) or ( this_number_image[y, x][0] != 0): diff_count += 1 if both_count == 0: unconfidence_ratio = number_w * number_h + 1 # max unconfidence else: unconfidence_ratio = 1.0 * diff_count / both_count if unconfidence_ratio < last_unconfidence_ratio: last_thought_number = number_templates[i][0] last_unconfidence_ratio = unconfidence_ratio print str(last_thought_number) + " | " + str(last_unconfidence_ratio) try: #check if it's defined bin.number_unconfidence_ratio except: bin.number_unconfidence_ratio = last_unconfidence_ratio bin.number = last_thought_number print "Set Speed Limit Number" else: if last_unconfidence_ratio < bin.number_unconfidence_ratio: bin.number_unconfidence_ratio = last_unconfidence_ratio if bin.number == last_thought_number: print "More Confident on Same Number: Updated" else: print "More Confident on Different Number: Updated" bin.icon = last_thought_number