def findImageContour(img, frame): storage = cv.CreateMemStorage() cont = cv.FindContours(img, storage, cv.CV_RETR_EXTERNAL, cv.CV_CHAIN_APPROX_NONE, (0, 0)) max_center = [None, 0] for c in contour_iterator(cont): # Number of points must be more than or equal to 6 for cv.FitEllipse2 # Use to set minimum size of object to be tracked. if len(c) >= 60: # Copy the contour into an array of (x,y)s PointArray2D32f = cv.CreateMat(1, len(c), cv.CV_32FC2) for (i, (x, y)) in enumerate(c): PointArray2D32f[0, i] = (x, y) # Fits ellipse to current contour. (center, size, angle) = cv.FitEllipse2(PointArray2D32f) # Only consider location of biggest contour -- adapt for multiple object tracking if size > max_center[1]: max_center[0] = center max_center[1] = size angle = angle if True: # Draw the current contour in gray gray = cv.CV_RGB(255, 255, 255) cv.DrawContours(img, c, gray, gray, 0, 1, 8, (0, 0)) if max_center[1] > 0: # Convert ellipse data from float to integer representation. center = (cv.Round(max_center[0][0]), cv.Round(max_center[0][1])) size = (cv.Round(max_center[1][0] * 0.5), cv.Round(max_center[1][1] * 0.5)) color = cv.CV_RGB(255, 0, 0) cv.Ellipse(frame, center, size, angle, 0, 360, color, 3, cv.CV_AA, 0)
def track_keypoints(self, grey, prev_grey): # We are tracking points between the previous frame and the # current frame img0, img1 = prev_grey, grey # Reshape the current keypoints into a numpy array required # by calcOpticalFlowPyrLK() p0 = np.float32([p for p in self.keypoints]).reshape(-1, 1, 2) # Calculate the optical flow from the previous frame to the current frame p1, st, err = cv2.calcOpticalFlowPyrLK(img0, img1, p0, None, **self.lk_params) # Do the reverse calculation: from the current frame to the previous frame try: p0r, st, err = cv2.calcOpticalFlowPyrLK(img1, img0, p1, None, **self.lk_params) # Compute the distance between corresponding points in the two flows d = abs(p0 - p0r).reshape(-1, 2).max(-1) # If the distance between pairs of points is < 1 pixel, set # a value in the "good" array to True, otherwise False good = d < 1 # Initialize a list to hold new keypoints new_keypoints = list() # Cycle through all current and new keypoints and only keep # those that satisfy the "good" condition above for (x, y), good_flag in zip(p1.reshape(-1, 2), good): if not good_flag: continue new_keypoints.append((x, y)) # Draw the keypoint on the image cv2.circle(self.marker_image, (x, y), self.feature_size, (0, 255, 0, 0), cv.CV_FILLED, 8, 0) # Set the global keypoint list to the new list self.keypoints = new_keypoints # If we have enough points, find the best fit ellipse around them if len(self.keypoints) > 6: self.keypoints_matrix = cv.CreateMat(1, len(self.keypoints), cv.CV_32SC2) i = 0 for p in self.keypoints: cv.Set2D(self.keypoints_matrix, 0, i, (int(p[0]), int(p[1]))) i = i + 1 track_box = cv.FitEllipse2(self.keypoints_matrix) else: # Otherwise, find the best fitting rectangle track_box = cv2.boundingRect(self.keypoints_matrix) except: track_box = None return track_box
def process_image(self, slider_pos): """ This function finds contours, draws them and their approximation by ellipses. """ stor = cv.CreateMemStorage() # Create the destination images image02 = cv.CloneImage(self.source_image) cv.Zero(image02) image04 = cv.CreateImage(cv.GetSize(self.source_image), cv.IPL_DEPTH_8U, 3) cv.Zero(image04) # Threshold the source image. This needful for cv.FindContours(). cv.Threshold(self.source_image, image02, slider_pos, 255, cv.CV_THRESH_BINARY) # Find all contours. cont = cv.FindContours(image02, stor, cv.CV_RETR_LIST, cv.CV_CHAIN_APPROX_NONE, (0, 0)) for c in contour_iterator(cont): # Number of points must be more than or equal to 6 for cv.FitEllipse2 if len(c) >= 6: # Copy the contour into an array of (x,y)s PointArray2D32f = cv.CreateMat(1, len(c), cv.CV_32FC2) for (i, (x, y)) in enumerate(c): PointArray2D32f[0, i] = (x, y) # Draw the current contour in gray gray = cv.CV_RGB(100, 100, 100) cv.DrawContours(image04, c, gray, gray, 0, 1, 8, (0, 0)) # Fits ellipse to current contour. (center, size, angle) = cv.FitEllipse2(PointArray2D32f) # Convert ellipse data from float to integer representation. center = (cv.Round(center[0]), cv.Round(center[1])) size = (cv.Round(size[0] * 0.5), cv.Round(size[1] * 0.5)) # Draw ellipse in random color color = cv.CV_RGB(random.randrange(256), random.randrange(256), random.randrange(256)) cv.Ellipse(image04, center, size, angle, 0, 360, color, 2, cv.CV_AA, 0) # Show image. HighGUI use. cv.ShowImage("Result", image04)
def centerRadius(cvImg, ColorLower=None, ColorUpper=None): lowerBound = cv.Scalar(90, 0, 90) upperBound = cv.Scalar(171, 80, 171) size = cv.GetSize(cvImg) output = cv.CreateMat(size[0], size[1], cv.CV_8UC1) cv.InRangeS(cvImg, lowerBound, upperBound, output) yi, xi = np.nonzero(output) #points = np.array([xi,yi]).T #coords = [tuple(points[pt]) for pt in range(len(points))] coords = zip(xi, yi) PointArray2D32f = cv.CreateMat(1, len(coords), cv.CV_32FC2) for (i, (x, y)) in enumerate(coords): PointArray2D32f[0, i] = (x, y) (center, size, angle) = cv.FitEllipse2(PointArray2D32f) h, k = center radius = np.sqrt(np.power((xi[0] - h), 2) + np.power(yi[0] - k, 2)) return tuple(np.around([h, k])), round(radius)
def process_image(self, slider_pos): global cimg, source_image1, ellipse_size, maxf, maxs, eoc, lastcx, lastcy, lastr """ This function finds contours, draws them and their approximation by ellipses. """ stor = cv.CreateMemStorage() # Create the destination images cimg = cv.CloneImage(self.source_image) cv.Zero(cimg) image02 = cv.CloneImage(self.source_image) cv.Zero(image02) image04 = cv.CreateImage(cv.GetSize(self.source_image), cv.IPL_DEPTH_8U, 3) cv.Zero(image04) # Threshold the source image. This needful for cv.FindContours(). cv.Threshold(self.source_image, image02, slider_pos, 255, cv.CV_THRESH_BINARY) # Find all contours. cont = cv.FindContours(image02, stor, cv.CV_RETR_LIST, cv.CV_CHAIN_APPROX_NONE, (0, 0)) maxf = 0 maxs = 0 size1 = 0 for c in contour_iterator(cont): if len(c) > ellipse_size: PointArray2D32f = cv.CreateMat(1, len(c), cv.CV_32FC2) for (i, (x, y)) in enumerate(c): PointArray2D32f[0, i] = (x, y) # Draw the current contour in gray gray = cv.CV_RGB(100, 100, 100) cv.DrawContours(image04, c, gray, gray, 0, 1, 8, (0, 0)) if iter == 0: strng = segF + '/' + 'contour1.png' cv.SaveImage(strng, image04) color = (255, 255, 255) (center, size, angle) = cv.FitEllipse2(PointArray2D32f) # Convert ellipse data from float to integer representation. center = (cv.Round(center[0]), cv.Round(center[1])) size = (cv.Round(size[0] * 0.5), cv.Round(size[1] * 0.5)) if iter == 1: if size[0] > size[1]: size2 = size[0] else: size2 = size[1] if size2 > size1: size1 = size2 size3 = size # Fits ellipse to current contour. if eoc == 0 and iter == 2: rand_val = abs((lastr - ((size[0] + size[1]) / 2))) if rand_val > 20 and float(max(size[0], size[1])) / float( min(size[0], size[1])) < 1.5: lastcx = center[0] lastcy = center[1] lastr = (size[0] + size[1]) / 2 if rand_val > 20 and float(max(size[0], size[1])) / float( min(size[0], size[1])) < 1.4: cv.Ellipse(cimg, center, size, angle, 0, 360, color, 2, cv.CV_AA, 0) cv.Ellipse(source_image1, center, size, angle, 0, 360, color, 2, cv.CV_AA, 0) elif eoc == 1 and iter == 2: (int, cntr, rad) = cv.MinEnclosingCircle(PointArray2D32f) cntr = (cv.Round(cntr[0]), cv.Round(cntr[1])) rad = (cv.Round(rad)) if maxf == 0 and maxs == 0: cv.Circle(cimg, cntr, rad, color, 1, cv.CV_AA, shift=0) cv.Circle(source_image1, cntr, rad, color, 2, cv.CV_AA, shift=0) maxf = rad elif (maxf > 0 and maxs == 0) and abs(rad - maxf) > 30: cv.Circle(cimg, cntr, rad, color, 2, cv.CV_AA, shift=0) cv.Circle(source_image1, cntr, rad, color, 2, cv.CV_AA, shift=0) maxs = len(c) if iter == 1: temp3 = 2 * abs(size3[1] - size3[0]) if (temp3 > 40): eoc = 1
def main(argv): TITLE = "" PURPLE_RADIUS_MM = 3.46 / 2 GROWTH_MM = 600 RGB_Array = [(0, 255, 0), (0, 0, 255), (50, 100, 0), (255, 0, 0), (0, 100, 50), (100, 50, 255)] GRAPHGROWTH = 1 rescale = 1 IMAGE_FORMAT = 'png' parser = argparse.ArgumentParser() parser.add_argument('-i', '--image', required=True, dest='i') parser.add_argument('-d', '--data', required=True, dest='d') parser.add_argument('-t', '--tsnit', dest='t') parser.add_argument('-r', '--rescale', dest='r') parser.add_argument('-m', action='store_true') parser.add_argument('-n', action='store_true') args = parser.parse_args() if args.i is None: sys.exit(1) else: OPTICIMAGE = args.i if args.d is None: sys.exit(1) else: DATAFILE = args.d if args.t is not None: fileName, extension = os.path.splitext(args.t) tsnitData = readData(args.t, extension) if args.m is True: GRAPHGROWTH = 0 TITLE += 'By mic ' else: GRAPHGROWTH = 1 TITLE += 'By Percent ' #if args.n is True: #GRAPHGROWTH = 1 #TITLE += 'By Percent ' fileName, extension = os.path.splitext(DATAFILE) heightData = readData(DATAFILE, extension) if len(heightData) is 0: sys.exit(2) regex = re.compile('^[A-Z]+[0-9]+') basename = os.path.basename(fileName) m = regex.match(basename) whichOIS = m.group() SIDE = 0 if any(s in basename.upper().replace(" ", "_") for s in ['_OD_', ' OD ']): SIDE = 1 TITLE += "Right Eye Clockwise Graph" XLABEL = "Start at 9'o clock" SAVEFILE = whichOIS + '_OD' STARTANG = np.pi elif any(s in basename.upper().replace(" ", "_") for s in ['_OS_', ' OS ']): SIDE = 2 STARTANG = 0 SAVEFILE = whichOIS + '_OS' TITLE += "Left Eye Counter-Clockwise" XLABEL = "Start at 3'o clock" if args.r is not None: RATIOFILE = args.r if SIDE is 1: rescale = readRatio(RATIOFILE, whichOIS, 'OD') else: rescale = readRatio(RATIOFILE, whichOIS, 'OS') SUPRESS_ADJUSTED = False if rescale is 1: SUPRESS_ADJUSTED = True GRAPH_SAVE = SAVEFILE + "_GRAPH" IMAGE_SAVE = SAVEFILE + "_EYE" CSV_SAVE = SAVEFILE + '_DATA' # 0 nothing, 1 right, 2 left if GRAPHGROWTH is 1: GRAPH_SAVE = GRAPH_SAVE + '_PERCENT' IMAGE_SAVE = IMAGE_SAVE + '_PERCENT' CSV_SAVE = CSV_SAVE + '_PERCENT' else: GRAPH_SAVE = GRAPH_SAVE + '_MIC' IMAGE_SAVE = IMAGE_SAVE + '_MIC' CSV_SAVE = CSV_SAVE + '_MIC' dataFile = (open(CSV_SAVE + '.csv', 'w')) imgColor = cv.LoadImage(OPTICIMAGE, cv.CV_LOAD_IMAGE_UNCHANGED) width, height = cv.GetSize(imgColor) center, purpRad = centerRadius(imgColor, 2) xi, yi = getContour(imgColor) coords = zip(xi, yi) PointArray2D32f = cv.CreateMat(1, len(coords), cv.CV_32FC2) for (i, (x, y)) in enumerate(coords): PointArray2D32f[0, i] = (x, y) #(centerCont, size, angle) = cv.FitEllipse2(PointArray2D32f) box2d = cv.FitEllipse2(PointArray2D32f) fig = plt.figure(1) fig.subplots_adjust(hspace=.2) graph1 = fig.add_subplot(2, 1, 1) #graph2 = fig.add_subplot(3,1,2) #norm = fig.add_subplot(2,1,2) tsnitGraph = fig.add_subplot(2, 1, 2) ratio = width / float(len(heightData)) mmperpixel = PURPLE_RADIUS_MM / purpRad addedDist = (GROWTH_MM / 1000. / mmperpixel) #dataFile.write(fmtCSVArr(np.linspace(1,360,360))+"\n") dataFile.write("%s,%s,%s,%s,%s\n" % ('name', 'shape', 'dimensions (um)', "AUC (um)", fmtCSVArr(np.linspace(1, 360, 360)))) writeTheta = np.linspace(STARTANG * 180 / np.pi, (STARTANG + 2 * np.pi) * 180 / np.pi, 361) #dataWriter.writerow(np.around(np.linspace(0,360,len(theta)),decimals=3)) writeTheta = writeTheta * np.pi / 180 writeTheta = offsetGraph(writeTheta, SIDE) #np.savetxt(dataFile, np.linspace(0,360,len(theta)),fmt='%.3f',delimiter='\n',newline=',') def graphShape(ellipBox, grid, ratio, graph=None, label="", color=None, flags=0): # 1 = image # 2 = circle # 4 = ellipse # 8 = other graph ellipse = circle = image = writeOther = False if (flags & 0x01) != 0: image = True if (flags & 0x02) != 0: ellipse = True if (flags & 0x04) != 0: circle = True if (flags & 0x08) != 0: writeOther = True (cent, size, angle) = ellipBox w, l = size circum = circumference(l / 2, w / 2) d = circum / np.pi excelEllipeBox = (tuple(np.divide(cent, ratio)), tuple(np.round(np.divide(size, ratio))), angle) circBox = (tuple(np.divide(cent, ratio)), tuple(np.round((d / ratio, d / ratio))), angle) th = np.linspace(STARTANG, STARTANG + 2 * np.pi, np.round(circum / ratio * 2)) thet, h = mkPeriod(th, circBox, grid) f = interpolate.interp1d( np.concatenate( (thet - 2 * np.pi, thet, thet + 2 * np.pi, thet + 4 * np.pi)), np.concatenate((h, h, h, h))) writeCircHeight = f(writeTheta) thet, h = mkPeriod(th, excelEllipeBox, grid) f = interpolate.interp1d( np.concatenate( (thet - 2 * np.pi, thet, thet + 2 * np.pi, thet + 4 * np.pi)), np.concatenate((h, h, h, h))) writeEllipHeight = f(writeTheta) areaCirc = circum * mmperpixel / len(writeCircHeight) * np.sum( writeCircHeight) areaEllip = circum * mmperpixel / len(writeEllipHeight) * np.sum( writeEllipHeight) r, g, b = color ovalR, ovalG, ovalB = 255 - r, 255 - g, 255 - b if image is True: cv.Circle(imgColor, tuple(np.around(cent).astype('int')), int(d / 2), color=cv.RGB(r, g, b)) cv.EllipseBox(imgColor, ellipBox, cv.RGB(ovalR, ovalG, ovalB)) #dataWriter.writerow(np.around(circHeight,decimals=3)) #dataWriter.writerow(np.around(ellipHeight,decimals=3)) #np.savetxt(dataFile,circHeight,fmt='%.4f',newline=',',delimiter='\n') #np.savetxt(dataFile,ellipHeight,fmt='%.4f',newline=',',delimiter='\n') #f = interpolate.interp1d(th,circHeight-ellipHeight) #diffHeight = f(th) dataFile.write( "%s,%s,%.0fx%.0f,%.3f,%s\n" % (label, 'ellipse', l * mmperpixel * 1000, w * mmperpixel * 1000, areaEllip, fmtCSVArr(writeEllipHeight[1:]))) dataFile.write( "%s,%s,%.0fx%.0f,%.3f,%s\n" % (label, 'circle', d * mmperpixel * 1000, d * mmperpixel * 1000, areaCirc, fmtCSVArr(writeCircHeight[1:]))) if writeOther is True: tsnitGraph.plot(np.linspace(0, 360, len(writeCircHeight)), writeCircHeight, color=(r / 255., g / 255., b / 255.), label=(label + " cir AUC " + str(round(areaCirc / 1000, 3)) + " mm^2")) if ellipse is True: #dataFile.write(label+','++','+fmtCSVArr(writeEllipHeight)+"\n") graph.plot(np.linspace(0, 360, len(writeEllipHeight)), writeEllipHeight, color=(ovalR / 255., ovalG / 255., ovalB / 255.), label=(label + " ellip AUC " + str(round(areaEllip / 1000, 3)) + " mm^2")) if circle is True: #dataFile.write(label+','+'%.0fx%.0f'%()+','+fmtCSVArr(writeCircHeight)+"\n") graph.plot(np.linspace(0, 360, len(writeCircHeight)), writeCircHeight, color=(r / 255., g / 255., b / 255.), label=(label + " cir AUC " + str(round(areaCirc / 1000, 3)) + " mm^2")) #norm.plot(np.linspace(0,360,len(ellipHeight)),diffHeight, label=(label+" height diff")) if GRAPHGROWTH is 1: for i in [50, 100]: (cent, size, ang) = box2d a, b = size circum = circumference(a / 2, b / 2) * (1 + i / 100.) graphShape(mkResizeBox(circum, box2d), heightData, ratio * rescale, graph1, '%' + str(i) + ' larger', color=RGB_Array.pop(), flags=4) if GRAPHGROWTH is 0: for i in [1, 2]: (cent, size, ang) = box2d graphShape((cent, tuple(np.add(size, addedDist * 2 * i)), ang), heightData, ratio * rescale, graph1, str(int(i * GROWTH_MM)) + ' um', color=RGB_Array.pop(), flags=4) (cent, size, ang) = box2d circleBox = (tuple(center), size, ang) graphShape(mkResizeBox(2 * np.pi * purpRad, circleBox), heightData, ratio, graph1, color=RGB_Array.pop(), label=str(3.46), flags=15) if SUPRESS_ADJUSTED is False: graphShape(mkResizeBox(2 * np.pi * purpRad, circleBox), heightData, ratio * rescale, graph1, color=RGB_Array.pop(), label='3.46 adjusted', flags=15) cv.SaveImage(IMAGE_SAVE + '.' + IMAGE_FORMAT, imgColor) graph1.set_title(TITLE + '\nscaling factor: ' + str(round(rescale, 3))) #norm.set_title('Circle and Oval Height Difference') #norm.set_xlabel(XLABEL +'(Degrees)') #norm.legend(bbox_to_anchor=(1.13,1), prop={'size':6}) tsnitCircum = np.pi * PURPLE_RADIUS_MM * 2 / 1000 tsnitArea = tsnitCircum / len(tsnitData) * np.sum(tsnitData) tsnitGraph.plot(np.linspace(0, 360, len(tsnitData)), tsnitData, color=tuple(np.divide(RGB_Array.pop(), 255.)), label=("3.46 TSNIT " + str(round(tsnitArea, 3)) + 'mm^2')) dataFile.write("%s,%s,%.0fx%.0f,%.3f,%s\n" % ("tsnit", 'circle', PURPLE_RADIUS_MM * 2 * 1000, PURPLE_RADIUS_MM * 2 * 1000, tsnitArea * 1000, '')) tsnitGraph.set_title('TSNIT GRAPH') tsnitGraph.set_xlabel(XLABEL + '(Degrees)') tsnitGraph.legend(bbox_to_anchor=(1.13, 1), prop={'size': 6}) plt.ylabel('Heights (nm)') #graph.set_xlabel(XLABEL +'(Degrees)') graph1.legend(bbox_to_anchor=(1.13, 1), prop={'size': 6}) #graph2.legend(bbox_to_anchor=(1.13,1),prop={'size':8}) fontP = FontProperties() fontP.set_size('xx-small') plt.savefig(GRAPH_SAVE + "." + IMAGE_FORMAT) dataFile.close()