Python – Find the boundary point of the outline in opencv numpy

Find the boundary point of the outline in opencv numpy… here is a solution to the problem.

Find the boundary point of the outline in opencv numpy

Enter image description here rookie who finishes open cv and numpy here. Here is the picture: here is my code:

import numpy as np
import cv2

im = cv2.imread('test.jpg')
imgray = cv2.cvtColor(im, cv2. COLOR_BGR2GRAY)
imgray = cv2.medianBlur(imgray, ksize=7)

ret, thresh = cv2.threshold(imgray, 0, 255, cv2. THRESH_BINARY+cv2. THRESH_OTSU)
_, contours, _ = cv2.findContours(thresh, cv2. RETR_EXTERNAL, cv2. CHAIN_APPROX_NONE)

print ("number of countours detected before filtering %d -> "%len(contours))
new = np.zeros(imgray.shape)

new = cv2.drawContours(im,contours,len(contours)-1,(0,0,255),18)

cv2.namedWindow('Display',cv2. WINDOW_NORMAL)
cv2.imshow('Display',new)
cv2.waitKey()

mask = np.zeros(imgray.shape,np.uint8)
cv2.drawContours(mask,[contours[len(contours)-1]],0,255,-1)
pixelpoints = cv2.findNonZero(mask)
cv2.imwrite("masked_image.jpg",mask)

print(len(pixelpoints))
print("type of pixelpoints is %s" %type(pixelpoints))

The length of the pixel is close to 2 million because it contains all the points covered by the outline. But I just need the border point of that profile. What should I do? I tried several approaches in the opencv docs, but tuple and sort operations always go wrong. Please… Help?

I just need the boundary point of the outline 🙁

Solution

Is this what contour boundary points mean?
(I used your image above to try)

The white line you see is the dot I marked in white on the blue outline I draw. There’s a little dot in the lower right corner because I think it’s most likely your black background isn’t really black, so when
I do the threshold processing and padding to get this
enter image description here

In the same place there is a small white blob. However, if you try to use parameters and do more appropriate threshold handling and padding, that shouldn’t be a problem.
In openCV’s drawContours function, cnts will contain a list of contours, and each contour will contain an array of points. Each dot is also of type numpy.ndarray. If you want to keep all the points of each outline in one place so that it returns a set of boundary points, such as the white point outline in the image above, you may want to append them all to a list. You can try this :

#rgb is brg instead
contoured=cv2.drawContours(black, cnts, -1, (255,0,0), 3)

#list of ALL points of ALL contours
all_pixels=[]

for i in range(0, len(cnts)):
    for j in range(0,len(cnts[i])):
        all_pixels.append(cnts[i][j])

When I try

print(len(all_pixels))

It returned me 2139 points.

If you want to mark points for visualization purposes (for example, like my white point), do this:

#contouredC is a copy of the contoured image above
contouredC[x_val, y_val]=[255,255,255]

If you want fewer dots, just use the ladder function to draw the white dots while iterating. Something like this:
enter image description here

In python, for loops

are slow, so I think there is a better way to replace nested for loops with the np.where() function or something. Will update this if/when I figure it out. In addition, this requires better thresholding and binarization techniques. Floodfill technique quoted from: Python 2.7: Area opening and closing binary image in Python not so accurate .

Hope this helps.

Related Problems and Solutions