简体   繁体   中英

Get a contour (x,y) coordinates of a shape in an image with python

I need to get a matrix with the coordinates (x,y) of the contour of the following image with python.

在此输入图像描述

I try it with opencv canny detector and find contours but I get a lot of contours and I don't know how to get the one I want.

import numpy as np
from matplotlib import pyplot as plt
import cv2
#from skimage import measure, feature, io
#from skimage import img_as_ubyte

x1 = 330
xf = 690
y1 = 0
yf = 400

img = cv2.imread('test.tif')
img = img[y1:yf, x1:xf]
edge = cv2.Canny(img, 100, 200)

image, contours, hierarchy = cv2.findContours(edge, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

在此输入图像描述

I just need an array with the (x,y) coordinates of the contour. I think it is in the contours output of cv2.findContours() but I don't find the contour that I want…

I also tried with the matplotlib.pyplot.contour function :

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('test.tif', 0) # read image
img = cv2.threshold(img, 0, 255, cv2.THRESH_OTSU)[1] # threshold image
img = cv2.medianBlur(img, 15)  # remove noise

# skeletonize 
size = np.size(img)  # get number of pixels
skel = np.zeros(img.shape, np.uint8) # create an array of zeros with the same shape as the image and 256 gray levels

element = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)) # create a structurant element (cross)
done = False

while(not done):
    eroded = cv2.erode(img, element)
    temp = cv2.dilate(eroded, element)
    temp = cv2.subtract(img, temp)
    skel = cv2.bitwise_or(skel, temp)
    img = eroded.copy()
    zeros = size - cv2.countNonZero(img)
    if zeros == size:
        done = True

cs = plt.contour(skel, 1)
p = cs.collections[0].get_paths()[0]
v = p.vertices
x = v[:, 0]
y = v[:, 1]

在此输入图像描述

But I just have closed contours and not the open contour which is going from the left to the right of the image.

Thanks a lot for your answers.

You almost found the answer to your question. First of all, there is a difference between edge detection and contour detection . Fundamentally, edge detection results in what you call (improperly) "open contour" (ie edge) and contour detection results in what you call "closed contour" (ie contour).

The Canny edge detection is a popular edge detection algorithm. Since you want to detect the edge in the form of an array with the (x,y) coordinates going from the left to the right of the image, the Canny edge detection is a good idea.

The answer is edge which is not in the wanted format.

import numpy as np
import matplotlib.pyplot as plt
import cv2

img = cv2.imread('test.tif')
edge = cv2.Canny(img, 100, 200)

ans = []
for y in range(0, edge.shape[0]):
    for x in range(0, edge.shape[1]):
        if edge[y, x] != 0:
            ans = ans + [[x, y]]
ans = np.array(ans)

print(ans.shape)
print(ans[0:10, :])

The array ans (shape equal to (n, 2) ) stores the (x, y)-coordinate of the n pixels which compose the detected edge. This is the result you are looking for.

Here is an image where I have plotted in white these n pixels:

在此输入图像描述

I hope this will help you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM