def get_rings(gray_img, origin):
    components_list = util.get_connected_components(gray_img)
    polar_components_list = util.get_polar_components(components_list, origin)
    rings = util.get_merged_components(polar_components_list)

    temp = np.zeros((gray_img.shape))
    mean_radius = []
    for points in rings:
        mean_radius.append(np.mean(points[:, 0]))
    rings = [x for _, x in sorted(zip(mean_radius, rings))]

    ring_number = 1
    for points in rings:
        for radius, theta in points:
            x, y = util.polar2cart(radius, theta)
            x += origin[0]
            y += origin[1]
            temp[int(y), int(x)] = ring_number
        ring_number += 1

    plt.figure()
    plt.imshow(temp)
    plt.show()

    return rings
def scatter_plot(rings, C, origin):
    cart_rings = []
    for points in rings:
        cart_ring = []
        for radius, theta in points:
            x, y = util.polar2cart(radius, theta)
            x += origin[0]
            y += origin[1]
            cart_ring.append((x, y))
        cart_rings.append(np.array(cart_ring).astype('float'))

    fig = plt.figure()
    ax = plt.axes(projection='3d')
    for i in range(len(C)):
        ax.scatter3D(cart_rings[i][:, 0], cart_rings[i][:, 1], C[i], 'gray')
    plt.show()
def findPeakpt(img, pt1, pt2, verbose=False):
    peakIdx, zi_diff, zi_int = findPeakIdx(img, pt1, pt2, verbose)
    theta_rad = math.atan2(abs(pt2[1]-pt1[1]), abs(pt2[0]-pt1[0])) 
    x, y = util.polar2cart(peakIdx, theta_rad, pt1)
    return x, y
def estimateCircleDiameter3(img, centerXY, diag_len, verbose, debug_img, show_plots=False):
    (rows, cols) = img.shape[:2]

    if False:
        #patch_angles=[ (np.pi/4), (3*np.pi/4) ]  # these only work if cols == rows
        patch_angles=[ (np.pi/4), -(np.pi/4) ]  # these only work if cols == rows
    else:
        theta_rad = math.atan2(rows, cols)
        #patch_angles=[ theta_rad, (np.pi-theta_rad) ]
        #patch_angles=[ np.pi/2-theta_rad, -(np.pi/2-theta_rad) ]
        patch_angles=[ theta_rad, -(theta_rad) ]

    #patch_width=100
    patch_width=int(diag_len * 0.10)
    if patch_width > 100: patch_width = 100
    if patch_width < 25:  patch_width = 25

    dia = []
    pt_sets = []

    for idx, patch_angle in enumerate(patch_angles):
        print(">>> Patch idx: %d, angle: %.2f, diag_len: %d, patch_width: %d" % (idx, np.rad2deg(patch_angle), diag_len, patch_width))

        patch = subimage2(img, centerXY, (np.pi/2-patch_angle), patch_width, diag_len + patch_width)
        #patch_blur = cv2.GaussianBlur(patch, (15, 15), 0)
        patch_blur=patch
        patch_mean = np.abs(np.mean(patch_blur, axis=1))
        patch_diff = np.abs(np.diff(patch_mean))
        patch_values = patch_mean

        n = patch_values.size
        print(" patch length = %d" % (n))
        left_range  = patch_values[n/2::-1]
        right_range = patch_values[n/2:]

        left_peakIdx  = findFirstPeakAboveThresh(left_range,  (np.max(left_range) * 0.5) )
        right_peakIdx = findFirstPeakAboveThresh(right_range, (np.max(right_range) * 0.5) )

        left_edge  = n/2 - left_peakIdx
        right_edge = n/2 + right_peakIdx

        print(" left_peakIdx = %d,  left_edge = %d" % (left_peakIdx, left_edge))
        print(" right_peakIdx = %d, right_edge = %d" % (right_peakIdx, right_edge))
        #~ print "  >>>>> right_edge, left_edge: ", peak_sets[1][0], peak_sets[0][0]
        #~ print "  >>>>> patch_angle, patch_angle2: ", patch_angle, patch_angle + np.pi

        if left_peakIdx == -99 or right_peakIdx == -99:
            print(" Could not find peak...")
            #return -99, pt_sets

        if left_peakIdx == 0 or right_peakIdx == 0:
            print(" Could only find one peak...")
            #return -99, pt_sets

        pt1 = util.polar2cart(left_peakIdx, patch_angle, (centerXY[0], rows-centerXY[1]))
        pt1 = ( int(np.round(pt1[0])), int(rows-np.round(pt1[1])) )
        pt2 = util.polar2cart(right_peakIdx, patch_angle + np.pi, (centerXY[0], rows-centerXY[1]))
        pt2 = ( int(np.round(pt2[0])), int(rows-np.round(pt2[1])) )
        pt_sets.append( (pt1, pt2) )

        #print(">>> left_edge: %d, right_edge: %d" % (left_edge,right_edge))
        if verbose: print(" nominal dia: %d" % (right_edge-left_edge))
        dia.append(right_edge-left_edge)

        if show_plots:
            #
            # Rotate patch 90, then plot
            #
            pt1 = util.polar2cart(centerXY[0], patch_angles[1], (0,0))
            pt1 = ( int(pt1[0]), int(pt1[1]) )
            patch_rot = np.rot90(patch_blur, k=1).copy()
            cv2.line(patch_rot, (pt1[0], 0), (pt1[0], 70), 128, 3)
            plt.figure(figsize=(20,8))
            plt.subplot(111)
            plt.imshow(patch_rot, cmap='gray',vmin=0,vmax=255)
            plt.title(('patch %d' % (idx)))
            plt.xticks([t for t in range(50, patch_rot.shape[:2][1], 50)] )

            #
            # Calculate pts for patch width and add lines
            #
            pt1 = util.polar2cart(int(diag_len/2.0), patch_angle, centerXY)
            pt1 = ( int(pt1[0]), int(pt1[1]) )
            pt2 = util.polar2cart(int(diag_len/2.0), patch_angle + (4*np.pi/4), centerXY)
            pt2 = ( int(pt2[0]), int(pt2[1]) )
            #cv2.line(debug_img, pt1, pt2, (200, 255, 180), 2)
            angle_offsets = [np.pi/2, 6*np.pi/4]
            for angle_offset in angle_offsets:
                pt1_1 = util.polar2cart(int(patch_width/2.0), patch_angle+angle_offset, pt1)
                pt1_1 = ( int(pt1_1[0]), int(pt1_1[1]) )
                pt2_1 = util.polar2cart(int(patch_width/2.0), patch_angle + (4*np.pi/4)-angle_offset, pt2)
                pt2_1 = ( int(pt2_1[0]), int(pt2_1[1]) )
                cv2.line(debug_img, pt1_1, pt2_1, (100, 155, 180), 2)

            #
            # plot the left and right patch mean values separately
            #
            if False:
                plt.figure(figsize=(30,8))
                plt.subplot(221)
                plt.plot(left_range[::-1])
                plt.xticks([t for t in range(0, left_range.size, 50)] )
                plt.text(left_range.size-50, np.max(left_range)-50, ("%s" % (left_peakIdx)), fontsize=18)
                plt.title("patch %d, left range (left half of patch_mean)" % (idx))
                plt.subplot(222)
                plt.plot(right_range)
                plt.xticks([t for t in range(0, right_range.size, 50)] )
                plt.text(20, np.max(right_range)-50, ("%s" % (right_peakIdx)), fontsize=18)
                plt.title("patch %d, right range (right half of patch_mean)" % (idx))

            #
            # plot the patch_values
            #
            mid_pt = patch_values.size/2
            max_pt = np.max(patch_values)/2
            plt.figure(figsize=(50,6))
            plt.subplot(220 + idx + 1)
            plt.plot(patch_values)
            plt.vlines(left_edge, 0, max_pt + 25, color='r', linewidth=4)
            plt.text(left_edge-20, 20, ("%s" % left_edge), fontsize=12)
            plt.vlines(right_edge, 0, max_pt + 25, color='r', linewidth=4)
            plt.vlines(mid_pt, 0, max_pt, color='y', linewidth=2)
            plt.text(right_edge-20, 20, ("%s" % right_edge), fontsize=12)
            plt.text(left_edge+((right_edge-left_edge)/2), np.max(patch_values)-50, ("%s" % (right_edge-left_edge)), fontsize=18)
            plt.text(left_edge+((mid_pt-left_edge)/2), max_pt-50, ("%s" % (left_peakIdx)), fontsize=18)
            plt.text(mid_pt+((right_edge-mid_pt)/2), max_pt-50, ("%s" % (right_peakIdx)), fontsize=18)
            plt.title("patch %d, mean" % (idx))
            plt.xticks([t for t in range(50, patch_values.size, 50)] )
        
    dia_np=np.array(dia)
    delta = np.abs(dia_np.mean() - diag_len)
    #percent_diff =  np.abs(diag_len - dia_np.mean()) / ((dia_np.mean() + diag_len)/2.0)
    
    if dia_np.std() > (dia_np.max() * 0.2):
        found = False
        print("  estimation failed : %.2f > %2f" % (dia_np.std(), (dia_np.max() * 0.2)))
    else:
        found = True
        
    if not found:
        return -99, pt_sets 
    else:
        return dia_np.mean(), pt_sets
def estimateCircleDiameter2(img, centerXY, diag_len, verbose, debug_img, show_plots=False):
    #(rows, cols) = img.shape[:2]
    # pt = (center[1]+(376/2), center[0]-(488/2))
#     end_pt=(cols-1, 1)
#     offset=(0, 0)

#     x_len = abs(cols)
#     y_len = abs(rows)
#     hypot = int(np.hypot(x_len, y_len))
#     theta_rad = math.atan2(abs(y_len), abs(x_len))
#     #theta_rad = math.atan2((end_pt[1]-center_pt[1]), (end_pt[0]-center_pt[0]))
#     print("angle: %f" % np.rad2deg(theta_rad))
#     x,y = util.polar2cart(hypot/2, theta_rad, center_pt)
#     print "rot pt (center): ", (x,y)
#     x,y = abs(x+offset[0]), abs(y+offset[1])
#     print "rot pt (center) after offset: ", (x,y)

    if show_plots:
        plot_lst = []
        plot_lst.append( (img, 'img') )

    if True:
        patch_angles=[ (np.pi/4), (3*np.pi/4) ]  # these only work if cols == rows
    else:
        (rows, cols) = img.shape[:2]
        theta_rad = math.atan2(rows, cols)
        patch_angles=[ theta_rad, (np.pi-theta_rad) ]

    patch_width=70
    dia = []
    pt_sets = []
    for idx, patch_angle in enumerate(patch_angles):
        patch = subimage2(img, centerXY, patch_angle, patch_width, diag_len + (1*150))
        #patch_blur = cv2.GaussianBlur(patch, (15, 15), 0)
        patch_blur=patch
        patch_mean = np.abs(np.mean(patch_blur, axis=1))
        patch_diff = np.abs(np.diff(patch_mean))

        if show_plots:
            plot_lst.append( (patch_blur, ('patch %d' % (idx))) )
        
        pt1 = util.polar2cart(int(diag_len/2.0), patch_angle, centerXY)
        pt1 = ( int(pt1[0]), int(pt1[1]) )
        pt2 = util.polar2cart(int(diag_len/2.0), patch_angle + (4*np.pi/4), centerXY)
        pt2 = ( int(pt2[0]), int(pt2[1]) )
        #cv2.line(debug_img, pt1, pt2, (200, 255, 180), 2)
        angle_offsets = [np.pi/2, 6*np.pi/4]
        for angle_offset in angle_offsets:
            pt1_1 = util.polar2cart(int(patch_width/2.0), patch_angle+angle_offset, pt1)
            pt1_1 = ( int(pt1_1[0]), int(pt1_1[1]) )
            pt2_1 = util.polar2cart(int(patch_width/2.0), patch_angle + (4*np.pi/4)-angle_offset, pt2)
            pt2_1 = ( int(pt2_1[0]), int(pt2_1[1]) )
            cv2.line(debug_img, pt1_1, pt2_1, (100, 155, 180), 2)

        n = patch_diff.size
        ranges = []
        #~ lt_range = patch_diff[n/2::-1]
        #~ rt_range = patch_diff[n/2:]
        lt_range = patch_mean[n/2::-1]
        rt_range = patch_mean[n/2:]
        ranges.append(lt_range)
        ranges.append(rt_range)
        
        if show_plots:
            plt.figure(figsize=(10*2,10*2))
            plt.subplot(221)
            plt.plot(lt_range)
            plt.title("patch %d, left range (left half of patch_diff)" % (idx))
            plt.subplot(222)
            plt.plot(rt_range)
            plt.title("patch %d, right range (right half of patch_diff)" % (idx))

        # iter through each range, find the first peak past threshold
        peak_sets = []
        for r in ranges:
            delta_threshold = np.max(r) * 0.55
            if verbose: print("  (estimateCircleDiameter2) threshold: ", delta_threshold)
            idx_jumps = []
            for idx, delta in enumerate(r):
                if delta > delta_threshold:
                    idx_jumps.append( (idx, delta) )
                    #print("  idx_jump found: idx=%d, delta=%d" % (idx, delta))
            if len(idx_jumps) > 0:
                peak_set = idx_jumps[0]
                #print("  peakIdx, delta:", peak_set[0], peak_set[1])
            else:
                peak_set = (-99, 0)
            peak_sets.append(peak_set)
        #print("  peaks:", peak_sets)

        lt_peakIdx = n/2 - peak_sets[0][0]
        rt_peakIdx = n/2 + peak_sets[1][0]
        
        #~ print "  >>>>> rt_peakIdx, lt_peakIdx: ", peak_sets[1][0], peak_sets[0][0]
        #~ print "  >>>>> patch_angle, patch_angle2: ", patch_angle, patch_angle + (4*np.pi/4)
        pt1 = util.polar2cart(peak_sets[0][0], patch_angle, centerXY)
        pt1 = ( int(pt1[0]), int(pt1[1]) )
        pt2 = util.polar2cart(peak_sets[1][0], patch_angle + (4*np.pi/4), centerXY)
        pt2 = ( int(pt2[0]), int(pt2[1]) )
        pt_sets.append( (pt1, pt2) )
                
        #print(">>> lt_peakIdx: %d, rt_peakIdx: %d" % (lt_peakIdx,rt_peakIdx))
        if verbose: print("  (estimateCircleDiameter) nominal dia: %d" % (rt_peakIdx-lt_peakIdx))
        dia.append(rt_peakIdx-lt_peakIdx)

        if show_plots:
            util.plot_imgs(plot_lst)

#----- old:

    #~ patch1 = subimage2(img, centerXY, (np.pi/4), 60, diag_len + 150)
    #~ patch2 = subimage2(img, centerXY, (3*np.pi/4), 60, diag_len + 150)
    #~ #patch3 = subimage2(img, centerXY, (np.pi/2), 60, cols)
#~ 
    #~ patch1_blur = cv2.GaussianBlur(patch1, (15, 15), 0)
    #~ patch2_blur = cv2.GaussianBlur(patch2, (15, 15), 0)
    #~ #patch3_blur = cv2.GaussianBlur(patch3, (15, 15), 0)
#~ 
    #~ patch1_mean = np.abs(np.mean(patch1_blur, axis=1))
    #~ patch1_diff = np.abs(np.diff(patch1_mean))
    #~ patch2_mean = np.abs(np.mean(patch2_blur, axis=1))
    #~ patch2_diff = np.abs(np.diff(patch2_mean))
    #~ #patch3_mean = np.abs(np.mean(patch3_blur, axis=1))
    #~ #patch3_diff = np.abs(np.diff(patch3_mean))
#~ 
#~ 
    #~ patches = []
    #~ patches.append(patch1_diff)
    #~ patches.append(patch2_diff)
    #~ #patches.append(patch3_diff)
    #~ 
    #~ if show_plots:
        #~ util.plot_imgs([(img, 'img'), (patch1_blur, 'patch1'), (patch2_blur, 'patch2')], color=False)
#~ 
    #~ vector_sets=[  ]
    #~ dia=[]
    #~ for patch_diff in patches:
        #~ # split into two ranges: middle->left, middle->right
        #~ n = patch_diff.size
        #~ ranges = []
        #~ lt_range = patch_diff[n/2::-1]
        #~ rt_range = patch_diff[n/2:]
        #~ ranges.append(lt_range)
        #~ ranges.append(rt_range)
        #~ 
        #~ if show_plots:
            #~ plt.figure(figsize=(10*2,10*2))
            #~ plt.subplot(221)
            #~ plt.plot(lt_range)
            #~ plt.subplot(222)
            #~ plt.plot(rt_range)
#~ 
        #~ # iter through each range, find the first peak past threshold
        #~ peak_sets = []
        #~ for r in ranges:
            #~ delta_threshold = np.max(r) * 0.25
            #~ #if verbose: print "  (estimateCircleDiameter) threshold: ", delta_threshold
            #~ idx_jumps = []
            #~ for idx, delta in enumerate(r):
                #~ if delta > delta_threshold:
                    #~ idx_jumps.append( (idx, delta) )
                    #~ #print("  idx_jump found: idx=%d, delta=%d" % (idx, delta))
            #~ if len(idx_jumps) > 0:
                #~ peak_set = idx_jumps[0]
                #~ #print "  peakIdx, delta:", peak_set[0], peak_set[1]
            #~ else:
                #~ peak_set = (-99, 0)
            #~ peak_sets.append(peak_set)
        #~ #print "  peaks:", peak_sets
#~ 
        #~ lt_peakIdx = n/2 - peak_sets[0][0]
        #~ rt_peakIdx = n/2 + peak_sets[1][0]
        #~ 
        #~ vector_sets.append( (rt_peakIdx, lt_peakIdx) )
        #~ 
        #~ #print(">>> lt_peakIdx: %d, rt_peakIdx: %d" % (lt_peakIdx,rt_peakIdx))
        #~ if verbose: print("  (estimateCircleDiameter) nominal dia: %d" % (rt_peakIdx-lt_peakIdx))
        #~ dia.append(rt_peakIdx-lt_peakIdx)
    
    dia_np=np.array(dia)
    delta = np.abs(dia_np.mean() - diag_len)
    #percent_diff =  np.abs(diag_len - dia_np.mean()) / ((dia_np.mean() + diag_len)/2.0)
    
    if dia_np.std() > (dia_np.max() * 0.2):
        found = False
        print("  estimation failed1: %.2f > %2f" % (dia_np.std(), (dia_np.max() * 0.2)))
    #~ elif percent_diff > 0.1:
        #~ found = False
        #~ print("  estimation failed2: %.2f > 0.3" % (percent_diff))
        #~ print "   diag_len     : ", diag_len
        #~ print "   dia_np.mean(): ", dia_np.mean()
    else:
        found = True
        
    if not found:
        return -99, pt_sets 
    else:
        return dia_np.mean(), pt_sets
def findPeakpt(img, pt1, pt2, verbose=False):
    peakIdx, zi_diff, zi_int = findPeakIdx(img, pt1, pt2, verbose)
    theta_rad = math.atan2(abs(pt2[1]-pt1[1]), abs(pt2[0]-pt1[0])) 
    x, y = util.polar2cart(peakIdx, theta_rad, pt1)
    return x, y
def estimateCircleDiameter3(img, centerXY, diag_len, verbose, debug_img, show_plots=False):
    (rows, cols) = img.shape[:2]

    if False:
        #patch_angles=[ (np.pi/4), (3*np.pi/4) ]  # these only work if cols == rows
        patch_angles=[ (np.pi/4), -(np.pi/4) ]  # these only work if cols == rows
    else:
        theta_rad = math.atan2(rows, cols)
        #patch_angles=[ theta_rad, (np.pi-theta_rad) ]
        #patch_angles=[ np.pi/2-theta_rad, -(np.pi/2-theta_rad) ]
        patch_angles=[ theta_rad, -(theta_rad) ]

    #patch_width=100
    patch_width=int(diag_len * 0.10)
    if patch_width > 100: patch_width = 100
    if patch_width < 25:  patch_width = 25

    dia = []
    pt_sets = []

    for idx, patch_angle in enumerate(patch_angles):
        print(">>> Patch idx: %d, angle: %.2f, diag_len: %d, patch_width: %d" % (idx, np.rad2deg(patch_angle), diag_len, patch_width))

        patch = subimage2(img, centerXY, (np.pi/2-patch_angle), patch_width, diag_len + patch_width)
        #patch_blur = cv2.GaussianBlur(patch, (15, 15), 0)
        patch_blur=patch
        patch_mean = np.abs(np.mean(patch_blur, axis=1))
        patch_diff = np.abs(np.diff(patch_mean))
        patch_values = patch_mean

        n = patch_values.size
        print(" patch length = %d" % (n))
        left_range  = patch_values[n/2::-1]
        right_range = patch_values[n/2:]

        left_peakIdx  = findFirstPeakAboveThresh(left_range,  (np.max(left_range) * 0.5) )
        right_peakIdx = findFirstPeakAboveThresh(right_range, (np.max(right_range) * 0.5) )

        left_edge  = n/2 - left_peakIdx
        right_edge = n/2 + right_peakIdx

        print(" left_peakIdx = %d,  left_edge = %d" % (left_peakIdx, left_edge))
        print(" right_peakIdx = %d, right_edge = %d" % (right_peakIdx, right_edge))
        #~ print "  >>>>> right_edge, left_edge: ", peak_sets[1][0], peak_sets[0][0]
        #~ print "  >>>>> patch_angle, patch_angle2: ", patch_angle, patch_angle + np.pi

        if left_peakIdx == -99 or right_peakIdx == -99:
            print " Could not find peak..."
            #return -99, pt_sets

        if left_peakIdx == 0 or right_peakIdx == 0:
            print " Could only find one peak..."
            #return -99, pt_sets

        pt1 = util.polar2cart(left_peakIdx, patch_angle, (centerXY[0], rows-centerXY[1]))
        pt1 = ( int(np.round(pt1[0])), int(rows-np.round(pt1[1])) )
        pt2 = util.polar2cart(right_peakIdx, patch_angle + np.pi, (centerXY[0], rows-centerXY[1]))
        pt2 = ( int(np.round(pt2[0])), int(rows-np.round(pt2[1])) )
        pt_sets.append( (pt1, pt2) )

        #print(">>> left_edge: %d, right_edge: %d" % (left_edge,right_edge))
        if verbose: print(" nominal dia: %d" % (right_edge-left_edge))
        dia.append(right_edge-left_edge)

        if show_plots:
            #
            # Rotate patch 90, then plot
            #
            pt1 = util.polar2cart(centerXY[0], patch_angles[1], (0,0))
            pt1 = ( int(pt1[0]), int(pt1[1]) )
            patch_rot = np.rot90(patch_blur, k=1).copy()
            cv2.line(patch_rot, (pt1[0], 0), (pt1[0], 70), 128, 3)
            plt.figure(figsize=(20,8))
            plt.subplot(111)
            plt.imshow(patch_rot, cmap='gray',vmin=0,vmax=255)
            plt.title(('patch %d' % (idx)))
            plt.xticks([t for t in range(50, patch_rot.shape[:2][1], 50)] )

            #
            # Calculate pts for patch width and add lines
            #
            pt1 = util.polar2cart(int(diag_len/2.0), patch_angle, centerXY)
            pt1 = ( int(pt1[0]), int(pt1[1]) )
            pt2 = util.polar2cart(int(diag_len/2.0), patch_angle + (4*np.pi/4), centerXY)
            pt2 = ( int(pt2[0]), int(pt2[1]) )
            #cv2.line(debug_img, pt1, pt2, (200, 255, 180), 2)
            angle_offsets = [np.pi/2, 6*np.pi/4]
            for angle_offset in angle_offsets:
                pt1_1 = util.polar2cart(int(patch_width/2.0), patch_angle+angle_offset, pt1)
                pt1_1 = ( int(pt1_1[0]), int(pt1_1[1]) )
                pt2_1 = util.polar2cart(int(patch_width/2.0), patch_angle + (4*np.pi/4)-angle_offset, pt2)
                pt2_1 = ( int(pt2_1[0]), int(pt2_1[1]) )
                cv2.line(debug_img, pt1_1, pt2_1, (100, 155, 180), 2)

            #
            # plot the left and right patch mean values separately
            #
            if False:
                plt.figure(figsize=(30,8))
                plt.subplot(221)
                plt.plot(left_range[::-1])
                plt.xticks([t for t in range(0, left_range.size, 50)] )
                plt.text(left_range.size-50, np.max(left_range)-50, ("%s" % (left_peakIdx)), fontsize=18)
                plt.title("patch %d, left range (left half of patch_mean)" % (idx))
                plt.subplot(222)
                plt.plot(right_range)
                plt.xticks([t for t in range(0, right_range.size, 50)] )
                plt.text(20, np.max(right_range)-50, ("%s" % (right_peakIdx)), fontsize=18)
                plt.title("patch %d, right range (right half of patch_mean)" % (idx))

            #
            # plot the patch_values
            #
            mid_pt = patch_values.size/2
            max_pt = np.max(patch_values)/2
            plt.figure(figsize=(50,6))
            plt.subplot(220 + idx + 1)
            plt.plot(patch_values)
            plt.vlines(left_edge, 0, max_pt + 25, color='r', linewidth=4)
            plt.text(left_edge-20, 20, ("%s" % left_edge), fontsize=12)
            plt.vlines(right_edge, 0, max_pt + 25, color='r', linewidth=4)
            plt.vlines(mid_pt, 0, max_pt, color='y', linewidth=2)
            plt.text(right_edge-20, 20, ("%s" % right_edge), fontsize=12)
            plt.text(left_edge+((right_edge-left_edge)/2), np.max(patch_values)-50, ("%s" % (right_edge-left_edge)), fontsize=18)
            plt.text(left_edge+((mid_pt-left_edge)/2), max_pt-50, ("%s" % (left_peakIdx)), fontsize=18)
            plt.text(mid_pt+((right_edge-mid_pt)/2), max_pt-50, ("%s" % (right_peakIdx)), fontsize=18)
            plt.title("patch %d, mean" % (idx))
            plt.xticks([t for t in range(50, patch_values.size, 50)] )
        
    dia_np=np.array(dia)
    delta = np.abs(dia_np.mean() - diag_len)
    #percent_diff =  np.abs(diag_len - dia_np.mean()) / ((dia_np.mean() + diag_len)/2.0)
    
    if dia_np.std() > (dia_np.max() * 0.2):
        found = False
        print("  estimation failed : %.2f > %2f" % (dia_np.std(), (dia_np.max() * 0.2)))
    else:
        found = True
        
    if not found:
        return -99, pt_sets 
    else:
        return dia_np.mean(), pt_sets
def estimateCircleDiameter2(img, centerXY, diag_len, verbose, debug_img, show_plots=False):
    #(rows, cols) = img.shape[:2]
    # pt = (center[1]+(376/2), center[0]-(488/2))
#     end_pt=(cols-1, 1)
#     offset=(0, 0)

#     x_len = abs(cols)
#     y_len = abs(rows)
#     hypot = int(np.hypot(x_len, y_len))
#     theta_rad = math.atan2(abs(y_len), abs(x_len))
#     #theta_rad = math.atan2((end_pt[1]-center_pt[1]), (end_pt[0]-center_pt[0]))
#     print("angle: %f" % np.rad2deg(theta_rad))
#     x,y = util.polar2cart(hypot/2, theta_rad, center_pt)
#     print "rot pt (center): ", (x,y)
#     x,y = abs(x+offset[0]), abs(y+offset[1])
#     print "rot pt (center) after offset: ", (x,y)

    if show_plots:
        plot_lst = []
        plot_lst.append( (img, 'img') )

    if True:
        patch_angles=[ (np.pi/4), (3*np.pi/4) ]  # these only work if cols == rows
    else:
        (rows, cols) = img.shape[:2]
        theta_rad = math.atan2(rows, cols)
        patch_angles=[ theta_rad, (np.pi-theta_rad) ]

    patch_width=70
    dia = []
    pt_sets = []
    for idx, patch_angle in enumerate(patch_angles):
        patch = subimage2(img, centerXY, patch_angle, patch_width, diag_len + (1*150))
        #patch_blur = cv2.GaussianBlur(patch, (15, 15), 0)
        patch_blur=patch
        patch_mean = np.abs(np.mean(patch_blur, axis=1))
        patch_diff = np.abs(np.diff(patch_mean))

        if show_plots:
            plot_lst.append( (patch_blur, ('patch %d' % (idx))) )
        
        pt1 = util.polar2cart(int(diag_len/2.0), patch_angle, centerXY)
        pt1 = ( int(pt1[0]), int(pt1[1]) )
        pt2 = util.polar2cart(int(diag_len/2.0), patch_angle + (4*np.pi/4), centerXY)
        pt2 = ( int(pt2[0]), int(pt2[1]) )
        #cv2.line(debug_img, pt1, pt2, (200, 255, 180), 2)
        angle_offsets = [np.pi/2, 6*np.pi/4]
        for angle_offset in angle_offsets:
            pt1_1 = util.polar2cart(int(patch_width/2.0), patch_angle+angle_offset, pt1)
            pt1_1 = ( int(pt1_1[0]), int(pt1_1[1]) )
            pt2_1 = util.polar2cart(int(patch_width/2.0), patch_angle + (4*np.pi/4)-angle_offset, pt2)
            pt2_1 = ( int(pt2_1[0]), int(pt2_1[1]) )
            cv2.line(debug_img, pt1_1, pt2_1, (100, 155, 180), 2)

        n = patch_diff.size
        ranges = []
        #~ lt_range = patch_diff[n/2::-1]
        #~ rt_range = patch_diff[n/2:]
        lt_range = patch_mean[n/2::-1]
        rt_range = patch_mean[n/2:]
        ranges.append(lt_range)
        ranges.append(rt_range)
        
        if show_plots:
            plt.figure(figsize=(10*2,10*2))
            plt.subplot(221)
            plt.plot(lt_range)
            plt.title("patch %d, left range (left half of patch_diff)" % (idx))
            plt.subplot(222)
            plt.plot(rt_range)
            plt.title("patch %d, right range (right half of patch_diff)" % (idx))

        # iter through each range, find the first peak past threshold
        peak_sets = []
        for r in ranges:
            delta_threshold = np.max(r) * 0.55
            if verbose: print "  (estimateCircleDiameter2) threshold: ", delta_threshold
            idx_jumps = []
            for idx, delta in enumerate(r):
                if delta > delta_threshold:
                    idx_jumps.append( (idx, delta) )
                    #print("  idx_jump found: idx=%d, delta=%d" % (idx, delta))
            if len(idx_jumps) > 0:
                peak_set = idx_jumps[0]
                #print "  peakIdx, delta:", peak_set[0], peak_set[1]
            else:
                peak_set = (-99, 0)
            peak_sets.append(peak_set)
        #print "  peaks:", peak_sets

        lt_peakIdx = n/2 - peak_sets[0][0]
        rt_peakIdx = n/2 + peak_sets[1][0]
        
        #~ print "  >>>>> rt_peakIdx, lt_peakIdx: ", peak_sets[1][0], peak_sets[0][0]
        #~ print "  >>>>> patch_angle, patch_angle2: ", patch_angle, patch_angle + (4*np.pi/4)
        pt1 = util.polar2cart(peak_sets[0][0], patch_angle, centerXY)
        pt1 = ( int(pt1[0]), int(pt1[1]) )
        pt2 = util.polar2cart(peak_sets[1][0], patch_angle + (4*np.pi/4), centerXY)
        pt2 = ( int(pt2[0]), int(pt2[1]) )
        pt_sets.append( (pt1, pt2) )
                
        #print(">>> lt_peakIdx: %d, rt_peakIdx: %d" % (lt_peakIdx,rt_peakIdx))
        if verbose: print("  (estimateCircleDiameter) nominal dia: %d" % (rt_peakIdx-lt_peakIdx))
        dia.append(rt_peakIdx-lt_peakIdx)

        if show_plots:
            util.plot_imgs(plot_lst)

#----- old:

    #~ patch1 = subimage2(img, centerXY, (np.pi/4), 60, diag_len + 150)
    #~ patch2 = subimage2(img, centerXY, (3*np.pi/4), 60, diag_len + 150)
    #~ #patch3 = subimage2(img, centerXY, (np.pi/2), 60, cols)
#~ 
    #~ patch1_blur = cv2.GaussianBlur(patch1, (15, 15), 0)
    #~ patch2_blur = cv2.GaussianBlur(patch2, (15, 15), 0)
    #~ #patch3_blur = cv2.GaussianBlur(patch3, (15, 15), 0)
#~ 
    #~ patch1_mean = np.abs(np.mean(patch1_blur, axis=1))
    #~ patch1_diff = np.abs(np.diff(patch1_mean))
    #~ patch2_mean = np.abs(np.mean(patch2_blur, axis=1))
    #~ patch2_diff = np.abs(np.diff(patch2_mean))
    #~ #patch3_mean = np.abs(np.mean(patch3_blur, axis=1))
    #~ #patch3_diff = np.abs(np.diff(patch3_mean))
#~ 
#~ 
    #~ patches = []
    #~ patches.append(patch1_diff)
    #~ patches.append(patch2_diff)
    #~ #patches.append(patch3_diff)
    #~ 
    #~ if show_plots:
        #~ util.plot_imgs([(img, 'img'), (patch1_blur, 'patch1'), (patch2_blur, 'patch2')], color=False)
#~ 
    #~ vector_sets=[  ]
    #~ dia=[]
    #~ for patch_diff in patches:
        #~ # split into two ranges: middle->left, middle->right
        #~ n = patch_diff.size
        #~ ranges = []
        #~ lt_range = patch_diff[n/2::-1]
        #~ rt_range = patch_diff[n/2:]
        #~ ranges.append(lt_range)
        #~ ranges.append(rt_range)
        #~ 
        #~ if show_plots:
            #~ plt.figure(figsize=(10*2,10*2))
            #~ plt.subplot(221)
            #~ plt.plot(lt_range)
            #~ plt.subplot(222)
            #~ plt.plot(rt_range)
#~ 
        #~ # iter through each range, find the first peak past threshold
        #~ peak_sets = []
        #~ for r in ranges:
            #~ delta_threshold = np.max(r) * 0.25
            #~ #if verbose: print "  (estimateCircleDiameter) threshold: ", delta_threshold
            #~ idx_jumps = []
            #~ for idx, delta in enumerate(r):
                #~ if delta > delta_threshold:
                    #~ idx_jumps.append( (idx, delta) )
                    #~ #print("  idx_jump found: idx=%d, delta=%d" % (idx, delta))
            #~ if len(idx_jumps) > 0:
                #~ peak_set = idx_jumps[0]
                #~ #print "  peakIdx, delta:", peak_set[0], peak_set[1]
            #~ else:
                #~ peak_set = (-99, 0)
            #~ peak_sets.append(peak_set)
        #~ #print "  peaks:", peak_sets
#~ 
        #~ lt_peakIdx = n/2 - peak_sets[0][0]
        #~ rt_peakIdx = n/2 + peak_sets[1][0]
        #~ 
        #~ vector_sets.append( (rt_peakIdx, lt_peakIdx) )
        #~ 
        #~ #print(">>> lt_peakIdx: %d, rt_peakIdx: %d" % (lt_peakIdx,rt_peakIdx))
        #~ if verbose: print("  (estimateCircleDiameter) nominal dia: %d" % (rt_peakIdx-lt_peakIdx))
        #~ dia.append(rt_peakIdx-lt_peakIdx)
    
    dia_np=np.array(dia)
    delta = np.abs(dia_np.mean() - diag_len)
    #percent_diff =  np.abs(diag_len - dia_np.mean()) / ((dia_np.mean() + diag_len)/2.0)
    
    if dia_np.std() > (dia_np.max() * 0.2):
        found = False
        print("  estimation failed1: %.2f > %2f" % (dia_np.std(), (dia_np.max() * 0.2)))
    #~ elif percent_diff > 0.1:
        #~ found = False
        #~ print("  estimation failed2: %.2f > 0.3" % (percent_diff))
        #~ print "   diag_len     : ", diag_len
        #~ print "   dia_np.mean(): ", dia_np.mean()
    else:
        found = True
        
    if not found:
        return -99, pt_sets 
    else:
        return dia_np.mean(), pt_sets