def fit_circle(points_l, scale, debug=False): """Get information about a circle from a list of points `points_l`. This may involve fitting a circle or ellipse to a set of points? pip install circle-fit https://github.com/AlliedToasters/circle-fit Assuing for now that points_l contains a list of (x,y,z) points, so we take only (x,y) and scale according to `scale`. Both methods return a tuple of four values: xc: x-coordinate of solution center (float) yc: y-coordinate of solution center (float) R: Radius of solution (float) variance or residual (float) These methods should be identical if we're querying this with actual circles. Returning the second one for now. """ from circle_fit import hyper_fit, least_squares_circle data = [(item[0] * scale, item[1] * scale) for item in points_l] data = np.array(data) circle_1 = hyper_fit(data) circle_2 = least_squares_circle(data) xc_1, yc_1, r_1, _ = circle_1 xc_2, yc_2, r_2, _ = circle_2 if debug: print(f'(hyperfit) rad {r_1:0.4f}, center ({xc_1:0.4f},{yc_1:0.4f})') print(f'(least-sq) rad {r_2:0.4f}, center ({xc_2:0.4f},{yc_2:0.4f})') return circle_2
def get_xy_coords_for_circles(circles): for i in range(len(circles)): x_coor = circles[i]["lon"] * 111.320 * cos( np.radians(circles[i]["lat"])) * 1000 y_coor = circles[i]["lat"] * 110.54 * 1000 # converting from lat, lon to coordinates in metre from (0,0). c_xc = np.full(np.size(x_coor, 1), np.nan) c_yc = np.full(np.size(x_coor, 1), np.nan) c_r = np.full(np.size(x_coor, 1), np.nan) for j in range(np.size(x_coor, 1)): a = ~np.isnan(x_coor.values[:, j]) if a.sum() > 4: c_xc[j], c_yc[j], c_r[j], _ = cf.least_squares_circle([ (k, l) for k, l in zip(x_coor.values[:, j], y_coor.values[:, j]) if ~np.isnan(k) ]) circle_y = np.nanmean(c_yc) / (110.54 * 1000) circle_x = np.nanmean(c_xc) / (111.320 * cos(np.radians(circle_y)) * 1000) circle_diameter = np.nanmean(c_r) * 2 xc = [None] * len(x_coor.T) yc = [None] * len(y_coor.T) xc = np.mean(x_coor, axis=0) yc = np.mean(y_coor, axis=0) delta_x = x_coor - xc # *111*1000 # difference of sonde long from mean long delta_y = y_coor - yc # *111*1000 # difference of sonde lat from mean lat circles[i]["platform_id"] = circles[i].platform_id.values[0] circles[i]["flight_altitude"] = circles[i].flight_altitude.mean( ).values circles[i]["circle_time"] = ( circles[i].launch_time.mean().values.astype("datetime64")) # circles[i].encoding["circle_time"] = { # "units": "seconds since 2020-01-01", # "dtype": "datetime64[ns]", # } circles[i]["circle_lon"] = circle_x circles[i]["circle_lat"] = circle_y circles[i]["circle_diameter"] = circle_diameter circles[i]["dx"] = (["sounding", "alt"], delta_x) circles[i]["dy"] = (["sounding", "alt"], delta_y) return print("Circles ready for regression")
def get_valid_radii(self): # Creates circles from contours and accepts a certain interval for circles radius cont = EdgeDetection.total_contour_list valid_circles_list_total = list() valid_circles_list = list() for image_number, image in enumerate(cont): for contours in image: x_center, y_center, radius, _ = cf.least_squares_circle(contours[:, 0]) if 30 < radius < 200: valid_circles_list.append([image_number, x_center, y_center, radius]) valid_circles_list_total.append(valid_circles_list) valid_circles_list = list() CirclePosition.circle_features = valid_circles_list_total
def check_arc(points): # PULL X Y COORDS coords = [[s['X'], s['Y']] for s in points] # print(f"no.points: {len(coords)}") # FIT CIRCLE xc,yc,r,s = cf.least_squares_circle(coords) if DEBUG: print(f"CIRCLE FITTED:\n X: {xc},\n Y: {yc},\n R: {r},\n S: {s}") if s < Sthreshold: return True else: return False
def fit_circle(gcode): """ Takes a list of GCode commands in dict form and uses the least squares method to fit a cirlce. Returns xc, yx, r, s. """ # PULL X Y COORDS coords = [[s['X'], s['Y']] for s in gcode] # FIT CIRCLE xc,yc,r,s = cf.least_squares_circle(coords) if DEBUG: print(f"CIRCLE FITTED:\n X: {xc},\n Y: {yc},\n R: {r},\n S: {s}") return xc, yc, r, s
def compute_arc_move(points): # PULL X Y COORDS coords = [[s['X'], s['Y']] for s in points] # FIT CIRCLE xc,yc,r,s = cf.least_squares_circle(coords) if DEBUG: print(f"CIRCLE FITTED:\n X: {xc},\n Y: {yc},\n R: {r},\n S: {s}") # DETERMINE MOVE TYPE movetype = move_type(coords[0][:2], coords[1][:2], (xc, yc)) # SUM E TOTAL E_total = sum([i['E'] for i in points]) # FORMULATE G CODE COMMAND if s < Sthreshold: COMMAND = f"{movetype} X{coords[-1][0]} Y{coords[-1][1]} R{round(r, 5)} E{round(E_total, 5)}" if DEBUG: print(f'{round(s, 5)} : {COMMAND}') return COMMAND else: print(f"{round(s, 5)} : NOT AN ARC MOVE") # ------------- PLOTTING -------------- # ASK TO PLOT if PLOTTING: # CREATE FIGURE fig, ax = plt.subplots() ax.set_aspect(1) #ax.set_xlim([50,150]) #ax.set_ylim([50,150]) # PLOT SCATTER POINTS plt.scatter([i[0] for i in coords], [i[1] for i in coords]) # PLOT CIRCLE circle1 = plt.Circle((xc, yc), r, linestyle='--', fill=False) ax.add_artist(circle1) # SHOW PLOT plt.show()
def process_img(frame): # Convert BGR to HSV hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # define range of blue color in HSV lowbound = np.array([0, 0, 0]) uppbound = np.array([70, 255, 214]) # inrange only colours of hand, then remove gaps mask = cv2.inRange(hsv, lowbound, uppbound) kernel = np.ones((5, 5), np.uint8) # dilate mask = cv2.dilate(mask, kernel, iterations=1) mask = cv2.erode(mask, kernel, iterations=1) hand = cv2.bitwise_and(frame, frame, mask=mask) print(hand.shape) im = hand.copy() hand = cv2.cvtColor(hand, cv2.COLOR_BGR2GRAY) ret, thresh = cv2.threshold(hand, 100, 255, 0) contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) cnts = contours hand_cnt = [] for c in cnts: # if the contour is not sufficiently large, ignore it if cv2.contourArea(c) < 100: continue # compute the rotated bounding box of the contour. x, y, w, h = cv2.boundingRect(c) if (x, y) == (0, 0): continue cv2.rectangle(im, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.drawContours(hand, c, -1, (0, 255, 255)) hand_cnt.append(c) #keeping doing until find a hand if len(hand_cnt) > 1 or len(hand_cnt) == 0: cv2.imshow('hand', im) print("keep finding hand") else: c = hand_cnt[0] hull = cv2.convexHull(c, returnPoints=False) defects = cv2.convexityDefects(c, hull) # creat lists to store start points and far points start_p = [] far_p = [] points = [] for i in range(defects.shape[0]): s, e, f, d = defects[i, 0] start = tuple(c[s][0]) end = tuple(c[e][0]) far = tuple(c[f][0]) start_p.append((c[s][0])) far_p.append(c[f][0]) cv2.line(im, start, end, [0, 255, 0], 2) if i > 0: x1, y1 = far_p[i - 1] x2, y2 = far_p[i] if dist(x1, x2, y1, y2) > 50: rightmost = tuple(c[c[:, :, 0].argmax()][0]) if abs(x2 - rightmost[0]) > 30: points.append((x2, y2)) else: continue for i in range(len(points)): x, y = points[i] cv2.circle(im, (x, y), 5, [0, 0, 255], -1) font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(im, str(i), (x + 10, y + 10), font, 0.5, (255, 255, 255), 2, cv2.LINE_AA) # cv2.circle(im, start, 2, [0, 255, 255], -1) if len(points) != 10: cv2.imshow('hand', im) else: even = [0, 2, 4, 6, 8, 10] odd = [1, 3, 5, 7, 9] fingers = { 'pinky': 0, 'ring': 0, 'middle': 0, 'index': 0, 'thumb': 0 } finger_length = [] mid_points = [] # find middle points, noted the one for index is inaccurate for i in range(len(even) - 1): x1, y1 = points[even[i]] x2, y2 = points[even[i + 1]] mx, my = midpoint(x1, x2, y1, y2) mid_points.append((mx, my)) tx, ty = points[odd[i]] finger_length.append(dist(mx, tx, my, ty)) # fit middle points in a circle curve data = [] for i in range(4): data.append(points[even[i]]) xc, yc, r, _ = cf.least_squares_circle(data) xc, yc = int(xc), int(yc) cv2.circle(im, (xc, yc), 5, [0, 255, 255], -1) mid_middle = mid_points[2] angle_mid_middle = find_angle(xc, mid_middle[0], yc, mid_middle[1]) angle_6 = find_angle(xc, points[6][0], yc, points[6][1]) # for the case centre is above point 6 if yc >= mid_middle[1]: angle = (angle_6 - angle_mid_middle) + angle_6 elif points[6][1] <= yc < mid_middle[1]: angle = (angle_6 + angle_mid_middle) + angle_6 # correct the index finger length xi = xc - r * math.cos(angle) yi = yc - r * math.sin(angle) mid_index = (xi, yi) mid_points[3] = mid_index finger_length[3] = dist(points[7][0], xi, points[7][1], yi) for i in range(5): xm, ym = mid_points[i] xm, ym = int(xm), int(ym) cv2.circle(im, (xm, ym), 6, [175, 255, 255], -1) count = 0 for name in fingers: fingers[name] = finger_length[count] count += 1 print(name, ":", fingers[name]) font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText( im, str(fingers[name]), (points[odd[count]][0] + 10, points[odd[count]][1] + 10), font, 0.5, (255, 255, 175), 2, cv2.LINE_AA) cv2.imshow('frame', im)
def circle_fit(self): xCtr, yCtr, r, _ = cf.least_squares_circle(self.points_data.values) return hv.Ellipse(xCtr, yCtr, 2 * r).opts(color="red")
def process_img(frame, right_hand): if right_hand == False: frame = cv2.flip(frame, 0) rows, cols, c = frame.shape framearea = float(rows * cols) # Convert img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) img = cv2.GaussianBlur(img, (7, 7), 0) # Process ret, thresh = cv2.threshold(img, 70, 255, 0) img = cv2.bitwise_and(img, thresh) #apply black border to aid contours border = 10 bordmask = np.zeros((rows, cols), np.uint8) bordmask[border:rows - border, border:cols - border] = 1 img = cv2.bitwise_and(img, img, mask=bordmask) minval = 0 maxval = 255 # edge detection edg = cv2.Canny(img, minval, maxval, apertureSize=3, L2gradient=True) # countour detection # opening and closing kernel = np.ones((3, 3), np.uint8) opening = cv2.morphologyEx(edg, cv2.MORPH_OPEN, kernel) closing = cv2.morphologyEx(edg, cv2.MORPH_CLOSE, kernel) edg = closing contours, hierarchy = cv2.findContours(edg, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) hand = cv2.bitwise_and(frame, frame, mask=thresh) im = hand.copy() #find and draw contours cnts = contours hand_cnt = [] for ci, c in enumerate(cnts): # if the contour is not sufficiently large, or if it's too big, ignore it if not framearea / 400.0 < cv2.contourArea(c) < framearea / 1.06: continue # compute the rotated bounding box of the contour. x, y, w, h = cv2.boundingRect(c) ellipse = _, _, orient_angle = cv2.fitEllipse(c) print(ci, orient_angle) cv2.ellipse(im, ellipse, (0, 0, 255), 2) #im = rotate_image(im, orient_angle, rows, cols) if x == 0: continue cv2.rectangle(im, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.drawContours(im, c, -1, (0, ci * 255, 255)) hand_cnt.append(c) print(len(contours), len(hand_cnt)) #keeping doing until find a hand if len(hand_cnt) < 1: #cv2.imshow('hand',im) print("keep finding hand, contour not found") else: c = hand_cnt[1] if len(hand_cnt) > 1 else hand_cnt[0] hull = cv2.convexHull(c, returnPoints=False) defects = cv2.convexityDefects(c, hull) # creat lists to store start points and far points start_p = [] end_p = [] far_p = [] points = [] for i in range(defects.shape[0]): s, e, f, d = defects[i, 0] start = tuple(c[s][0]) end = tuple(c[e][0]) far = tuple(c[f][0]) start_p.append((c[s][0])) end_p.append((c[e][0])) far_p.append(c[f][0]) cv2.line(im, start, end, [0, 255, 0], 2) #set ratio of constriant distance ratio = 0.18 ratio_s = 0.09 ratio_d = 0.065 #ratio_d = 0.03 if i == 0: x2, y2 = far_p[i] cv2.circle(im, (x2, y2), 5, [0, 0, 255], -1) points.append((x2, y2)) else: #defect points x1, y1 = far_p[i - 1] x2, y2 = far_p[i] cv2.circle(im, (x2, y2), 5, [0, 0, 255], -1) #start and end points sx, sy = start_p[i] sx_1, sy_1 = start_p[i - 1] ex, ey = end_p[i] #take the only start point at finger tips if dist(sx, sx_1, sy, sy_1) > ratio_s * im.shape[1]: if dist(sx, ex, sy, ey) > ratio_s * im.shape[1]: points.append((sx, sy)) if dist(x1, x2, y1, y2) > ratio_d * im.shape[1]: bottommost = tuple(c[c[:, :, 1].argmax()][0]) rightmost = tuple(c[c[:, :, 0].argmax()][0]) topmost = tuple(c[c[:, :, 1].argmin()][0]) if abs(x2 - rightmost[0]) > ratio * im.shape[1]: points.append((x2, y2)) else: continue #plot start points for i in range(len(start_p)): sx, sy = start_p[i] cv2.circle(im, (sx, sy), 2, [0, 125, 255], -1) #get all the points far away enough from right edge only pc = [] ratio1 = 0.18 for i in range(len(points)): px, py = points[i] if abs(px - rightmost[0]) > ratio1 * im.shape[1]: pc.append((px, py)) points = pc if points[1][0] >= bottommost[0]: points[1] = bottommost if points[9][0] >= topmost[0]: points[9] = topmost if len(points) < 11: for i in range(1, 12 - len(points)): points.append(far_p[-i]) #cv2.setMouseCallback('image', click_to_add) for i in range(len(points)): x, y = points[i] #cv2.circle(im, (x, y), 5, [0, 0, 255], -1) font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(im, str(i), (x + 10, y + 10), font, 0.5, (255, 255, 255), 2, cv2.LINE_AA) # cv2.circle(im, start, 2, [0, 255, 255], -1) #cv2.imshow('hand',im) #cv2.waitKey(0) if len(points) < 10: print("not enough points") else: even = [0, 2, 4, 6, 8, 10] odd = [1, 3, 5, 7, 9] fingers = { 'pinky': 0, 'ring': 0, 'middle': 0, 'index': 0, 'thumb': 0 } finger_length = [] mid_points = [] # find middle points, noted the one for index is inaccurate for i in range(len(even) - 1): x1, y1 = points[even[i]] x2, y2 = points[even[i + 1]] mx, my = midpoint(x1, x2, y1, y2) mid_points.append((mx, my)) tx, ty = points[odd[i]] finger_length.append(round(dist(mx, tx, my, ty), 1)) # fit middle points in a circle curve data = [] for i in range(4): data.append(points[even[i]]) xc, yc, r, _ = cf.least_squares_circle(data) xc, yc = int(xc), int(yc) cv2.circle(im, (xc, yc), 5, [0, 255, 255], -1) mid_middle = mid_points[2] #get points for line construction for each finger finger_line = [] for i in range(5): a1, b1 = points[odd[i]] a1, b1 = int(a1), int(b1) a2, b2 = mid_points[i] a2, b2 = int(a2), int(b2) finger_line.append([(a2, b2), (a1, b1)]) angle_mid_middle = find_angle(xc, mid_middle[0], yc, mid_middle[1]) angle_6 = find_angle(xc, points[6][0], yc, points[6][1]) # for the case centre is below point 6 if yc >= mid_middle[1]: angle = (angle_6 - angle_mid_middle) + angle_6 xi = xc - r * cos(angle) yi = yc - r * sin(angle) # for the case yc is in between elif points[6][1] <= yc < mid_middle[1]: angle = (angle_6 + angle_mid_middle) + angle_6 xi = xc - r * cos(angle) yi = yc - r * sin(angle) else: # for the case points 6 and mid_middle both below yc if (angle_mid_middle - angle_6) <= angle_6: angle = angle_6 - (angle_mid_middle - angle_6) xi = xc - r * cos(angle) yi = yc + r * sin(angle) # for the case index_mid will be above yc else: angle = (angle_mid_middle - angle_6) - angle_6 xi = xc - r * cos(angle) yi = yc - r * sin(angle) # correct the index finger length mid_index = (xi, yi) mid_points[3] = mid_index finger_line[3][0] = tuple([int(i) for i in mid_index]) finger_length[3] = round(dist(points[7][0], xi, points[7][1], yi), 1) for i in range(5): xm, ym = mid_points[i] xm, ym = int(xm), int(ym) cv2.circle(im, (xm, ym), 6, [175, 255, 255], -1) count = 0 for name in fingers: fingers[name] = finger_length[count] font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText( im, str(int(fingers[name])), (points[odd[count]][0] - 10, points[odd[count]][1] - 10), font, 0.5, (255, 255, 175), 2, cv2.LINE_AA) count += 1 return im
for nf in range (0,Nframes): time.time() rx = signal[nf*N:(nf+1)*N] s = sine1.gen2() g = rx*np.conj(s) d = sigs.decimate(g, D, 20, ftype='fir', zero_phase=True) d.flatten() # buffer buff.put(d) df = buff.get() #print(df) # Circle Fitting auxA = np.real(df) auxB = np.imag(df) print(auxA) P = circle_fit.least_squares_circle([auxA, auxB]) print(P) # low pass memory filter x = axy*P[0] + (1-axy)*x y = axy*P[1] + (1-axy)*y r = ar*P[3] + (1-ar)*r # Signal Filtering dfit = (np.real(d)-x) + 1j*(np.imag(d)-y) # Angle conditioning phi = np.angle(dfit) phi = np.unwrap(phi) phi,z = sigs.lfilter(B, A, phi, zi = z) win.put(phi)
# axes(handles.axes5); # set(handles.axes5,'visible', 'on'); # set(handles.panel_ft_input_tag,'visible', 'on'); # set(handles.ft_panel_tag,'visible', 'on'); # set(handles.auto_ft_panel_tag,'visible', 'on'); axialc = axial - axial_median lateralc = lateral - lateral_median plt.scatter(lateralc, axialc) plt.xlabel('Lateral (nm)') plt.ylabel('Axial (nm)') plt.title('Combined structures') xy = np.vstack((lateralc, axialc)).T circle = circle_fit.least_squares_circle(xy) xc = circle[0] yc = circle[1] Rc = circle[2] dc = 2 * Rc plotcircle = circle_fit.plot_data_circle(lateralc, axialc, xc, yc, Rc) # box on # daspect([1 1 1]) # zlimits = [min((axial-axial_median))-0.1*(max(axial-axial_median)-... # min(axial-axial_median)) max((axial-axial_median))+0.1*(max(axial... # -axial_median)-min(axial-axial_median))]; %'zlimits' establishes an axial # % range centered at the axial # % 'median' position, and spanning # % over an axial length 20% greater
def singleCircleAnalysis(sc_img, settings, prev_result=None, showplot=True, iterations=2): """ Analyzes an image with only one circle in it. Having more is possible but will most likely fail. A result by means of hough transform or earlier investigation can be passed (cx, cy, r). If not, cx, cy is set to centre of image. :param sc_img: circle image :param nphi: number of angles at which lines will be used to evaluate intensity from centre point towards image border :param prev_result: list or numpy array ordered like [cx, cy, r] whith center points cx, cy and radius r :param showplot: results will be plotted. default is True :return: image with circle where center of image is center of found circle. Therefore image may be smaller in size """ nphi = settings['nphi'] ny, nx = np.shape(sc_img) phi_ls = np.linspace(0, 2 * math.pi * (1 - 1 / nphi), nphi) # do it once to get length of line: # print("prev_result", prev_result) _, _, tmp = interp_along_radius(sc_img, 0, centre=(prev_result[0], prev_result[1])) intensity_lines = np.zeros(shape=(len(tmp), len(phi_ls))) pts_of_max_int = np.zeros(shape=(nphi, 2)) xcentre = nx / 2 ycentre = ny / 2 if showplot: fig, (axs1, axs2, axs3) = plt.subplots(1, 3, figsize=(10, 5)) axs2.imshow(sc_img) intensity_lines = np.zeros(shape=(len(tmp), len(phi_ls))) pts_of_max_int = np.zeros(shape=(nphi, 2)) for (i, p) in enumerate(phi_ls): x, y, tmp = interp_along_radius(sc_img, p, centre=(prev_result[0], prev_result[1])) # put line into array: intensity_lines[:, i] = tmp pts_of_max_int[i, 0] = np.mean(x[np.where(tmp == np.amax(tmp))[0]]) pts_of_max_int[i, 1] = np.mean(y[np.where(tmp == np.amax(tmp))[0]]) if showplot: axs2.plot(x, y, 'k--') xmax = pts_of_max_int[:, 0] ymax = pts_of_max_int[:, 1] # fit circle through pts: xc, yc, r, _ = cf.least_squares_circle(np.array([ymax, xmax]).transpose()) if r < settings['minRad'] or r > settings['maxRad']: # if found radius outside of defined range, set to zero r = np.nan if showplot: axs2.scatter(ymax, xmax, c='r') # circle from hough: if prev_result is not None: c = plt.Circle((prev_result[0], prev_result[1]), prev_result[2], fill=False, color='red', linestyle='--', linewidth=3) axs2.add_artist(c) # circle newly found: if r is not np.nan: c = plt.Circle((xc, yc), r, fill=False, color='black', linewidth=3) axs2.add_artist(c) axs2.scatter(xc, yc, c='g', marker='+', s=20000) lx = np.shape(sc_img)[0] ly = np.shape(sc_img)[1] dx = min(abs(lx - xc), lx) - 1 dy = min(abs(ly - yc), ly) - 1 cropnew = False if cropnew: return_img = sc_img[int(yc - dy):int(yc + dy), int(xc - dx):int(xc + dx)] # translate coordinates of new circle to new image: xc = xc - (xc - dx) yc = yc - (yc - dy) else: return_img = sc_img if showplot: ny, nx = np.shape(intensity_lines) XX, YY = np.meshgrid(np.arange(nx), np.arange(ny)) axs1.contourf(XX, YY, intensity_lines) axs1.scatter( np.arange(nx), np.sqrt(np.square(xmax - xcentre) + np.square(ymax - ycentre)), c='r') axs1.set_xlim([0, nx - 1]) every = 2 axs1.set_xticks(np.arange(nphi)[::every]) axs1.set_xticklabels( ["%4.1f" % (p * 180 / math.pi) for p in phi_ls[::every]], rotation=0) axs1.set_xlabel('angle [°]') axs1.set_ylim([0, np.shape(XX)[0] - 1]) axs1.set_ylabel('Radius [px]') axs2.set_xlabel('x [px]') axs2.set_ylabel('y [px]') # print preview of new image and plot newly found circle in there (Note the displacement) if r is not np.nan: axs3.imshow(return_img) c = plt.Circle((xc, yc), r, fill=False, color='black', linewidth=3) axs3.add_artist(c) plt.show() return return_img, [xc, yc, r]
def test_circle_fit(self): circle = least_squares_circle(self.data) circle = least_squares_circle(self.numpy_data)
def process_img(frame): img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # blur it img = cv2.GaussianBlur(img, (7, 7), 0) ret, thresh = cv2.threshold(img, 70, 255, 0) img = cv2.bitwise_and(img, thresh) minval = 0 maxval = 255 # ret,edg = cv2.threshold(img,12,255,cv2.THRESH_BINARY) # cv2.imshow('i', edg) # edge detection edg = cv2.Canny(img, minval, maxval, apertureSize=3, L2gradient=True) # countour detection # minval,maxval = 84,84 # opening and closing kernel = np.ones((3, 3), np.uint8) opening = cv2.morphologyEx(edg, cv2.MORPH_OPEN, kernel) closing = cv2.morphologyEx(edg, cv2.MORPH_CLOSE, kernel) edg = closing contours, hierarchy = cv2.findContours(edg, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) hand = cv2.bitwise_and(frame,frame, mask=thresh) #print(hand.shape) im = hand.copy() cnts = contours hand_cnt = [] for c in cnts: # if the contour is not sufficiently large, ignore it if cv2.contourArea(c) < 400: continue # compute the rotated bounding box of the contour. x, y, w, h = cv2.boundingRect(c) if (x, y) == (0, 0): continue cv2.rectangle(im, (x, y), (x + w, y + h), (0, 255, 0), 2) cv2.drawContours(im, c, -1, (0, 255, 255)) hand_cnt.append(c) #keeping doing until find a hand if len(hand_cnt)!=1: cv2.imshow('hand',im) else: c = hand_cnt[0] hull = cv2.convexHull(c, returnPoints=False) defects = cv2.convexityDefects(c, hull) # creat lists to store start points and far points start_p = [] end_p =[] far_p = [] points = [] for i in range(defects.shape[0]): s, e, f, d = defects[i, 0] start = tuple(c[s][0]) end = tuple(c[e][0]) far = tuple(c[f][0]) start_p.append((c[s][0])) end_p.append((c[e][0])) far_p.append(c[f][0]) cv2.line(im, start, end, [0, 255, 0], 2) if i > 0: #defect points x1, y1 = far_p[i - 1] x2, y2 = far_p[i] #start and end points sx, sy = start_p[i] sx_1, sy_1 = start_p[i - 1] ex, ey = end_p[i] #take the only start point at finger tips if dist(sx, sx_1, sy, sy_1) > 40: if dist(sx, ex, sy, ey) > 40: points.append((sx, sy)) if dist(x1, x2, y1, y2) > 35: rightmost = tuple(c[c[:, :, 0].argmax()][0]) if abs(x2 - rightmost[0]) > 80: points.append((x2, y2)) else: continue pc = [] for i in range(len(points)): px,py = points[i] if abs(px - rightmost[0]) >70: pc.append((px, py)) points =pc for i in range(len(points)): x, y = points[i] cv2.circle(im, (x, y), 5, [0, 0, 255], -1) #plot start points sx,sy =start_p[i] #cv2.circle(im, (sx, sy), 3, [0, 125, 255], -1) font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(im, str(i), (x + 10, y + 10), font, 0.5, (255, 255, 255), 2, cv2.LINE_AA) # cv2.circle(im, start, 2, [0, 255, 255], -1) if len(points)<10: print("not enough contour points") cv2.imshow('hand',im) else: even = [0, 2, 4, 6, 8, 10] odd = [1, 3, 5, 7, 9] fingers = {'pinky': 0, 'ring': 0, 'middle': 0, 'index': 0, 'thumb': 0} finger_length = [] mid_points = [] # find middle points, noted the one for index is inaccurate for i in range(len(even) - 1): x1, y1 = points[even[i]] x2, y2 = points[even[i + 1]] mx, my = midpoint(x1, x2, y1, y2) mid_points.append((mx, my)) tx, ty = points[odd[i]] finger_length.append(dist(mx, tx, my, ty)) # fit middle points in a circle curve data = [] for i in range(4): data.append(points[even[i]]) xc, yc, r, _ = cf.least_squares_circle(data) xc, yc = int(xc), int(yc) cv2.circle(im, (xc, yc), 5, [0, 255, 255], -1) mid_middle = mid_points[2] #get points for line construction for each finger finger_line = [] for i in range(4): a1, b1 = points[odd[i]] a1,b1 = int(a1), int(b1) a2, b2 = mid_points[i] a2,b2 = int(a2), int(b2) finger_line.append([(a2,b2),(a1,b1)]) angle_mid_middle = find_angle(xc, mid_middle[0], yc, mid_middle[1]) angle_6 = find_angle(xc, points[6][0], yc, points[6][1]) # for the case centre is below point 6 if yc >= mid_middle[1]: angle = (angle_6 - angle_mid_middle) + angle_6 xi = xc - r * math.cos(angle) yi = yc - r * math.sin(angle) #for the case yc is in between elif points[6][1] <= yc < mid_middle[1]: angle = (angle_6 + angle_mid_middle) + angle_6 xi = xc - r * math.cos(angle) yi = yc - r * math.sin(angle) else: #for the case points 6 and mid_middle both below yc if (angle_mid_middle - angle_6) <= angle_6: angle = angle_6 - (angle_mid_middle - angle_6) xi = xc - r * math.cos(angle) yi = yc + r * math.sin(angle) #for the case index_mid will be above yc else: angle = (angle_mid_middle - angle_6) - angle_6 xi = xc - r * math.cos(angle) yi = yc - r * math.sin(angle) # correct the index finger length mid_index = (xi, yi) mid_points[3] = mid_index finger_length[3] = dist(points[7][0], xi, points[7][1], yi) for i in range(5): xm, ym = mid_points[i] xm, ym = int(xm), int(ym) cv2.circle(im, (xm, ym), 6, [175, 255, 255], -1) count = 0 for name in fingers: fingers[name] = finger_length[count] font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(im, str(int(fingers[name])), (points[odd[count]][0] - 10, points[odd[count]][1] - 10), font, 0.5,(255, 255, 175), 2, cv2.LINE_AA) count += 1 return finger_line
def find_intensity_max_arround_circles2(self): kernel = np.ones((3, 3), np.uint8) #self.picture = cv2.erode(self.picture, kernel, iterations=1) #self.picture = cv2.dilate(self.picture, kernel, iterations=1) xcentre = np.shape(self.picture)[0]/2 ycentre = np.shape(self.picture)[1]/2 nphi = 9 phi_ls = np.linspace(0, 2*math.pi*(1-1/nphi), nphi) # do it once to get length of line: _, _, tmp = interp_along_radius(self.picture, 0) fig, (axs1, axs2, axs3) = plt.subplots(1, 3, figsize=(10, 5)) axs2.imshow(self.picture) # plot center of image: axs2.scatter(self.picture.shape[0]/2, self.picture.shape[1]/2, c='r', marker='+', s=1000) intensity_lines = np.zeros(shape=(len(tmp), len(phi_ls))) pts_of_max_int = np.zeros(shape=(nphi, 2)) for (i, p) in enumerate(phi_ls): x, y, tmp = interp_along_radius(self.picture, p) # put line into array: intensity_lines[:, i] = tmp pts_of_max_int[i, 0] = np.mean(x[np.where(tmp == np.amax(tmp))[0]]) pts_of_max_int[i, 1] = np.mean(y[np.where(tmp == np.amax(tmp))[0]]) axs2.plot(y, x, 'k--') xmax = pts_of_max_int[:, 0] ymax = pts_of_max_int[:, 1] axs2.scatter(ymax, xmax, c='r') # fit circle through pts: xc, yc, r, _ = cf.least_squares_circle(np.array([ymax, xmax]).transpose()) # circle from hough: c = plt.Circle((xcentre, ycentre), self.radius, fill=False, color='red', linestyle='--', linewidth=3) axs2.add_artist(c) # circle newly found: c = plt.Circle((xc, yc), r, fill=False, color='black', linewidth=3) axs2.add_artist(c) axs2.scatter(xc, yc, c='g', marker='+', s=20000) ny, nx = np.shape(intensity_lines) XX, YY = np.meshgrid(np.arange(nx), np.arange(ny)) axs1.contourf(XX, YY, intensity_lines) axs1.scatter(np.arange(nx), np.sqrt(np.square(xmax-xcentre)+np.square(ymax-ycentre)), c='r') axs1.set_xlim([0, nx-1]) every = 2 axs1.set_xticks(np.arange(nphi)[::every]) axs1.set_xticklabels(["%4.1f" % (p*180/math.pi) for p in phi_ls[::every]], rotation=0) axs1.set_xlabel('angle [°]') axs1.set_ylim([0, np.shape(XX)[0]-1]) axs1.set_ylabel('Radius [px]') axs2.set_xlabel('x [px]') axs2.set_ylabel('y [px]') print(nx) lx = np.shape(self.picture)[0] ly = np.shape(self.picture)[1] dx = min(abs(lx-xc), lx)-1 dy = min(abs(ly-yc), ly)-1 print(int(xc-dx), int(xc+dx)) print(int(yc-dy), int(yc+dy)) #self.picture = self.picture[xc-dx:xc+dx, yc-dy:yc+dy] axs3.imshow(self.picture[int(xc-dx):int(xc+dx), int(yc-dy):int(yc+dy)]) plt.show()
def find_intensity_max_arround_circles(self): #since evaluating in polar coordinates is terrible, lets just rotate the picture by the angle we want, and crop the interesting part of the picture from there masksizewidth = 5 length = self.radius searchsize = 0.1*self.radius phi = 0 lines_to_evaluate = [] cv2.line(self.picture, (0, self.y_midpoint), (self.picture.shape[0], self.y_midpoint), color=0, thickness=2) for phi in range(0, 180, 30): #first create the rotation matrix for the angle to evaluate: phi = phi*2*math.pi/360 rot = cv2.getRotationMatrix2D((self.picture.shape[0]/2, self.picture.shape[1]/2), phi, 1.0) #trans = np.concatenate([rot, np.array([[1],[1]]).dot(np.array([0]))], axis=1) print(rot) rotatetPicture = cv2.warpAffine(self.picture, rot, self.picture.shape) """ x_min = self.x_midpoint+length-searchsize x_max = self.x_midpoint+length+searchsize y_min = self.y_midpoint-masksizewidth y_max = self.y_midpoint-masksizewidth """ intensity_line = rotatetPicture[int(rotatetPicture.shape[0]/2-3):int(rotatetPicture.shape[0]/2+3),0:self.picture.shape[-1]] intensity_line = np.mean(intensity_line, axis=0) lines_to_evaluate.append([phi, intensity_line]) #fining maximums in these lines: x_max = [] y_max = [] for line in lines_to_evaluate: #line[1] equals the points to evaluate, line[0] equals phi line_ev = line[1][0:int(len(line[1])/2)] x_max.append(-(-np.argmax(line_ev) + len(line_ev))*math.cos(line[0])+self.picture.shape[0]/2) y_max.append(-(-np.argmax(line_ev) + len(line_ev))*math.sin(line[0])+self.picture.shape[1]/2) line_ev=line[1][int(len(line[1])/2):-1] x_max.append(np.argmax(line_ev)*math.cos(line[0])+self.picture.shape[0]/2) y_max.append(np.argmax(line_ev)*math.sin(line[0])+self.picture.shape[1]/2) x=[] y=[] z=[] for line in lines_to_evaluate: x.append([(i-len(line[1])/2)*math.cos(line[0])+self.picture.shape[0]/2 for i in range(len(line[1]))]) y.append([(i-len(line[1])/2)*math.sin(line[0])+self.picture.shape[1]/2 for i in range(len(line[1]))]) z.append(line [1]) x=np.asarray(x).flatten() y=np.asarray(y).flatten() z=np.asarray(z).flatten() fig, (axs1, axs2) = plt.subplots(1,2, sharex=True, sharey=True) axs1.scatter(x,y,c=z) #axs1.scatter(range(len(lines_to_evaluate[0][1])),12*np.ones(22,1), lines_to_evaluate[0][1]) axs2.imshow(self.picture) axs2.scatter(x_max, y_max, c='b') # fit circle through pts: xc, yc, r, _ = cf.least_squares_circle(np.array([x_max, y_max]).transpose()) c = plt.Circle((xc, yc), r, fill=False, color='red') axs2.add_artist(c) axs2.scatter(self.picture.shape[0]/2, self.picture.shape[1]/2, c='g', marker='o', s=200) axs2.scatter(xc, yc, c='r', marker='+', s=200) print(xc,yc) plt.show()
data = [(float(x), float(y), float(z), float(expTime), str(filt_slot), float(flux), float(counts), float(fwhm), float(bkgnd), float(chiSq)) for x, y, z, expTime, filt_slot, flux, counts, fwhm, bkgnd, chiSq in csv.reader(csvfile, delimiter=',')] return data if __name__ == "__main__": fileName = sys.argv[1] if fileName[0] == '~': fileName = os.path.expanduser('~') + fileName[1:] data = get_data(fileName) xyData = [] #scrub everything but x & y from data for target in data: xyData.append(target[:2]) xc, yc, r, mse = cf.least_squares_circle(xyData) xc = xc + CENTER_OFFSET[0] yc = yc + CENTER_OFFSET[1] print("XCenter = " + repr(xc)) print("YCenter = " + repr(yc)) print("Radius = " + repr(r)) print("MSE = " + repr(mse))
cv2.CHAIN_APPROX_SIMPLE) backtorgb = cv2.cvtColor(gray, cv2.COLOR_GRAY2RGB) for i in range(np.array(contours).shape[0]): if (np.array(contours[i]).shape[0] > 1000): cv2.drawContours(backtorgb, contours[i], -1, (0, 0, 255), 3) print(i) plt.figure(figsize=(20, 20)) plt.imshow(backtorgb) #cv2.imshow("img", gray) #cv2.waitKey(0) for i in range(np.array(contours).shape[0]): if (np.array(contours[i]).shape[0] > 1000): print(np.array(contours[i]).shape) import circle_fit as cf cor = [] #for i in range(20): # cor.append(contours[35][i]) cor = np.array(contours[1]) cor = cor.reshape(cor.shape[0], cor.shape[2]) print(cor.shape) xc, yc, r, _ = cf.least_squares_circle(cor) print(xc, yc, r)
gdf.plot(column="cluster", categorical=True, markersize=1) # Subsetting the dataset sel = gdf # Keep only clusters with more than x building min_buildings = 3 count = gdf.groupby("cluster").count().iloc[:, 0] sel = sel.loc[gdf["cluster"].isin(count[count > min_buildings].index), :] # Keep only close buildings fitting in a circle sel["radius"] = 0 sel2 = sel.copy() for i, c in enumerate(sel.cluster.unique()): x, y, radius, e = circle_fit.least_squares_circle( sel.loc[sel.cluster == c, ["E.Gebäudekoordinate", "N.Gebäudekoordinate"]].values) sel2.loc[sel2.cluster == c, "radius"] = radius max_radius = 500 sel = sel2.loc[sel2.radius < max_radius, :] print( sel[["PV_ERTRAG", "DACHART", "Bauperiode", "cluster", "radius", "sqdist"]].sort_values(by="cluster")) fig, ax = plt.subplots() gdf.plot(ax=ax, color="grey", markersize=0.5) sel.plot(column="cluster", ax=ax, markersize=3, categorical=True) ax.set_xticks([]) ax.set_yticks([])
print("The as-designed center point is: (" + str(givenC_tuple[0]) + "," + str(givenC_tuple[1]) + ")") print("The distance between them is: " + str(round(math.dist(givenC_tuple, FCP), 7))) print("The fitted radius is: " + str(radius) + " and the actual radius is: " + str(givenR)) print("The difference between them is: " + str(round(abs(givenR - radius), 7))) pipe_point = [] sec_count = 0 for n in range(50): a = PassesSecondNoiseTestBySection[2 * n:2 * n + 2] if len(a[0]) > 0: xc, yc, r, CI = least_squares_circle(a[0], 8) plot_data_circle((list(zip(*a[0]))[0]), (list(zip(*a[0]))[1]), xc, yc, r) plt.title("Section " + str(sec_count) + " Pipe " + str(sec_count * 2)) plt.show() printInfo(r, xc, yc, sec_count, 0) pipe_point.append({xc, yc}) else: pass if len(a[1]) > 0: xc, yc, r, CI = least_squares_circle(a[1], 4.375) plot_data_circle((list(zip(*a[1]))[0]), (list(zip(*a[1]))[1]), xc, yc, r) plt.title("Section " + str(sec_count) + " Pipe " + str(sec_count * 2 + 1)) plt.show()