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" (i.e. edge) and contour detection results in what you call "closed contour" (i.e. 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With