1

I have a white contour, with black inside and around. I need to find the biggest circle that have only white areea inside, without holes, and does not contain black area from outside of the contour. For now, I can not find good way to do so. I am using openCv and Numpy in Python. of course if any other library is necessary I would like to hear.

##Update##

At first, I was trying with this code, but it gave me the biggest circle without consider the holes in it:

def get_biggest_area_inside_contour(self,image,index):

image_bin=cv2.cvtColor(image,cv2.COLOR_RGB2GRAY) 
retval,image_bin=cv2.threshold(image_bin,biggest_circle_thresh,255,cv2.THRESH_BINARY) 
contours, hierarchy = cv2.findContours(image_bin.copy(),cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE) 
image_with_contour=np.zeros(image.shape, np.uint8) 
dist=np.zeros((image.shape[0],image.shape[1])) 
for ind_y in range(image.shape[0]): 
    for ind_x in range(image.shape[1]): 
        dist[ind_y,ind_x] = cv2.pointPolygonTest(max_contour,(ind_x,ind_y),True)

As answered to me, there is a solution for that problem. The thing is I didn't managed to pass the code from MATLAB to python. The code is:

def get_biggest_area_inside_contour(self,image,index):

    image_bin=cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)
    _,image_bin=cv2.threshold(image_bin,biggest_circle_thresh,255,cv2.THRESH_BINARY)
    contours, _ = cv2.findContours(image_bin.copy(),cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)
    max_contour=contours[0]
    max_area=cv2.contourArea(contours[0])
    #Find the biggest white contour, some times can be little white surrond by black area
    for _cnt in contours:
        _area = cv2.contourArea(_cnt)
        if _area>max_area:
            max_area=_area
            max_contour=_cnt 
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    _blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    _threshold = cv2.threshold(_blurred, biggest_circle_thresh, 255, cv2.THRESH_BINARY)[1]
    result_img=cv2.drawContours(_threshold,max_contour,-1,(255,255,255),1)
    contours, _ = cv2.findContours(result_img.copy(),cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)
    #cv2.namedWindow('img {}'.format(index), cv2.WINDOW_NORMAL)
    #cv2.imshow('img {}'.format(index), result_img)

    apdp = cv2.approxPolyDP(max_contour,1,True)
    ap = [(a[0][0],a[0][1]) for a in apdp]
    vor_ap = Voronoi(ap,incremental=True)
    spined = []
    for ridge in contours:
        x, y, w, h = cv2.boundingRect(ridge)
        if cv2.pointPolygonTest(max_contour,(x,y),True) < 0.0 or cv2.pointPolygonTest(max_contour,(x+w,y+h),True) < 0.0:
            continue
        else:
            if tuple((x,y)) not in spined:
                spined.append([tuple((x,y))])
            if tuple((x+w,y)) not in spined:
                spined.append([tuple((x+w,y))])
            if tuple((x,y+h)) not in spined:
                spined.append([tuple((x,y+h))])  
            if tuple((x+w,y+h)) not in spined:
                spined.append([tuple((x+w,y+h))])                                 
    if len(spined)>0:
        for index in range(0,len(spined)):
            vor_ap.add_points(spined[index])
    fig=plt.figure(index)
    ax = fig.add_subplot(111)        
    voronoi_plot_2d(vor_ap, point_size=5, ax=ax)
    plt.scatter([s[0][0] for s in spined],[s[0][1] for s in spined])
    plt.plot([a[1] for a in ap],[a[0] for a in ap])
    if len(spined)>0:
        borders_and_holes=ap
        for i in range (0,len(spined)):
            borders_and_holes.append(spined[i])
        points=np.vstack(borders_and_holes)
        dt = Delaunay(points)
        ##cc = compute_triangle_circumcenters(dt.points, dt.simplices) Not sure how to do this
        #plt.plot(cc[:, 0], cc[:, 1], ".k")
    plt.show()

enter image description here

Alon H
  • 33
  • 9

1 Answers1

0

you can do a distance transform (in OpenCV).

invert picture so the fringes are white (true) and center is black (false). you may have to threshold your image, maybe remove the smudge in the middle.

apply distance transform with L2 distance (euclidean).

find highest peak (minMaxLoc).

highest peak is your circle center, and its value is the radius.

Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
  • image_bin=cv2.cvtColor(image,cv2.COLOR_RGB2GRAY) retval,image_bin=cv2.threshold(image_bin,biggest_circle_thresh,255,cv2.THRESH_BINARY) contours, hierarchy = cv2.findContours(image_bin.copy(),cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE) image_with_contour=np.zeros(image.shape, np.uint8) dist=np.zeros((image.shape[0],image.shape[1])) for ind_y in range(image.shape[0]): for ind_x in range(image.shape[1]): dist[ind_y,ind_x] = cv2.pointPolygonTest(max_contour,(ind_x,ind_y),True) This is what I have done, and it gave me inner holes. – Alon H Dec 07 '20 at 06:48
  • @AlonH Please post updates and clarifications in your question itself for everyone to see. Especially code, so that you can format it correctly. – beaker Dec 07 '20 at 16:16