Find edge points of this shape using opencv python

Question:

Everyone I have used contours to find out the endpoints as shown in the image but I’m not getting my expected output what these points (p1,p2,p3,p4). Can you please help me to find it out? I have also attached my input image below.
Thank you.

import cv2
cropped_image=cv2.imread('croped_img.png')
# cropped_image=cv2.resize(cropped_image,(512,615))
original_ccropped_image=cropped_image.copy()
cnt= contours(cropped_image)

#####take points bbox for stright line
x_new,y_new,w_new,h_new = cv2.boundingRect(cnt)

#####take points bbox for rotated
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
print(box)
cropped_image=cv2.drawContours(cropped_image,[box],0,(0,0,255),2)

My input image

enter image description here

Asked By: Ali Ahmad

||

Answers:

As mentioned in the comments you need to use convexity defects. OpenCV tutorial on this can be found here.

I tried the following code on your sample image and it works on your test image.

import cv2
import matplotlib.pyplot as plt

# Read the image, ignore conversions that I did here.
img= cv2.imread('img.png')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
_, img_gray = cv2.threshold(img_gray,150,255,cv2.THRESH_BINARY)

# Find contours
contours, hierarchy = cv2.findContours(img_gray, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)

# Find the convex hulls and defects, assuming there might exist more than one contour.
hull_list= []
defect_list= []
for i in range(len(contours)):
    hull = cv2.convexHull(contours[i], returnPoints= False)
    defects = cv2.convexityDefects(contours[i],hull)
    hull = cv2.convexHull(contours[i])
    hull_list.append(hull)
    defect_list.append(defects)

# Draw.
for idx, defects in enumerate(defect_list):
    cv2.drawContours(img, hull_list, idx, (255,0,0),2) # remove if you do not want the contour.
    for i in range(defects.shape[0]):
        s,e,_,d = defects[i,0]
        if d>512: # This filters places that are very close to be convex. Change it to zero and see what happens !!!!
            start = tuple(contours[idx][s][0])
            end = tuple(contours[idx][e][0])
            cv2.line(img,start,end,[0,255,0],2)

plt.imshow(img)
plt.show()

enter image description here

Answered By: Farshid