找到对象边缘之间的中心线
Find the center line between object's edges
今天我想识别物体的边缘。
我通过这样做得到了很好的结果。
import cv2
img = cv2.imread("0.png")
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img2 = cv2.equalizeHist(img2)
img2 = cv2.GaussianBlur(img2, (7, 7), 0)
edges = cv2.Canny(img2, 180, 300)
im2, contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (0, 255, 0), 1)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
图像看起来像:(这是焊接的 X 射线)
我的最终目标是找到边缘之间的中心线,
(每个 X 上 (MaxY+MinY)/2 的集合)
理想的结果应该是这样的:(抱歉手绘不好)
谁能告诉我应该怎么做?
非常感谢。
首先你应该准备你的图像,这样你就可以找到你的一个轮廓(阈值,直方图均衡等)。轮廓 returns 是一组代表轮廓的 (x,y) 坐标,因此对于第一步,您应该将上边缘与底部分开(将其分成两半)。在我的示例中,我将它作为轮廓的补充,但请注意,这不适用于曲线!你将不得不制定一个算法来划分上侧和下侧。完成此操作后,您可以制作两个列表,每个 x 坐标包含一个元素。然后简单的计算中间,在图像上打一个点。
示例代码:
import cv2
import numpy as np
img = cv2.imread('centerline.png')
mask = np.zeros((img.shape[:2]), np.uint8)
h2, w2 = img.shape[:2]
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
equ = cv2.equalizeHist(gray)
_, thresh = cv2.threshold(equ,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
_, contours, hierarchy = cv2.findContours(opening,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
for cnt in contours:
x,y,w,h = cv2.boundingRect(cnt)
print(h, w)
if h < 30 and w > 270:
cv2.drawContours(mask, [cnt], 0, (255,255,255), -1)
res = cv2.bitwise_and(img, img, mask=mask)
gray = cv2.cvtColor(res,cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
blur = cv2.GaussianBlur(thresh,(5,5),0)
_, contours, hierarchy = cv2.findContours(blur,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)
M = cv2.moments(cnt)
cy = int(M['m01']/M['m00'])
mask = np.zeros((img.shape[:2]), np.uint8)
cv2.drawContours(mask, [cnt], 0, (255,255,255), -1)
up = []
down = []
for i in cnt:
x = i[0][0]
y = i[0][1]
if x == 0:
pass
elif x == w2:
pass
else:
if y > cy:
down.append(tuple([x,y]))
elif y < cy:
up.append(tuple([x,y]))
else:
pass
up.sort(key = lambda x: x[0])
down.sort(key = lambda x: x[0])
up_1 = []
down_1 = []
for i in range(0, len(up)-1):
if up[i][0] != up[i+1][0]:
up_1.append(up[i])
else:
pass
for i in range(0, len(down)-1):
if down[i][0] != down[i+1][0]:
down_1.append(down[i])
else:
pass
lines = zip(up_1, down_1)
for i in lines:
x1 = i[0][0]
y1 = i[0][1]
x2 = i[1][0]
y2 = i[1][1]
middle = np.sqrt(((x2-x1)**2)+((y2-y1)**2))
cv2.circle(img, (x1, y1+int(middle/2)), 1, (0,0,255), -1)
cv2.imshow('img', img)
结果:
今天我想识别物体的边缘。
我通过这样做得到了很好的结果。
import cv2
img = cv2.imread("0.png")
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img2 = cv2.equalizeHist(img2)
img2 = cv2.GaussianBlur(img2, (7, 7), 0)
edges = cv2.Canny(img2, 180, 300)
im2, contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (0, 255, 0), 1)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
图像看起来像:(这是焊接的 X 射线)
我的最终目标是找到边缘之间的中心线, (每个 X 上 (MaxY+MinY)/2 的集合) 理想的结果应该是这样的:(抱歉手绘不好)
谁能告诉我应该怎么做? 非常感谢。
首先你应该准备你的图像,这样你就可以找到你的一个轮廓(阈值,直方图均衡等)。轮廓 returns 是一组代表轮廓的 (x,y) 坐标,因此对于第一步,您应该将上边缘与底部分开(将其分成两半)。在我的示例中,我将它作为轮廓的补充,但请注意,这不适用于曲线!你将不得不制定一个算法来划分上侧和下侧。完成此操作后,您可以制作两个列表,每个 x 坐标包含一个元素。然后简单的计算中间,在图像上打一个点。
示例代码:
import cv2
import numpy as np
img = cv2.imread('centerline.png')
mask = np.zeros((img.shape[:2]), np.uint8)
h2, w2 = img.shape[:2]
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
equ = cv2.equalizeHist(gray)
_, thresh = cv2.threshold(equ,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
_, contours, hierarchy = cv2.findContours(opening,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
for cnt in contours:
x,y,w,h = cv2.boundingRect(cnt)
print(h, w)
if h < 30 and w > 270:
cv2.drawContours(mask, [cnt], 0, (255,255,255), -1)
res = cv2.bitwise_and(img, img, mask=mask)
gray = cv2.cvtColor(res,cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
blur = cv2.GaussianBlur(thresh,(5,5),0)
_, contours, hierarchy = cv2.findContours(blur,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
cnt = max(contours, key=cv2.contourArea)
M = cv2.moments(cnt)
cy = int(M['m01']/M['m00'])
mask = np.zeros((img.shape[:2]), np.uint8)
cv2.drawContours(mask, [cnt], 0, (255,255,255), -1)
up = []
down = []
for i in cnt:
x = i[0][0]
y = i[0][1]
if x == 0:
pass
elif x == w2:
pass
else:
if y > cy:
down.append(tuple([x,y]))
elif y < cy:
up.append(tuple([x,y]))
else:
pass
up.sort(key = lambda x: x[0])
down.sort(key = lambda x: x[0])
up_1 = []
down_1 = []
for i in range(0, len(up)-1):
if up[i][0] != up[i+1][0]:
up_1.append(up[i])
else:
pass
for i in range(0, len(down)-1):
if down[i][0] != down[i+1][0]:
down_1.append(down[i])
else:
pass
lines = zip(up_1, down_1)
for i in lines:
x1 = i[0][0]
y1 = i[0][1]
x2 = i[1][0]
y2 = i[1][1]
middle = np.sqrt(((x2-x1)**2)+((y2-y1)**2))
cv2.circle(img, (x1, y1+int(middle/2)), 1, (0,0,255), -1)
cv2.imshow('img', img)
结果: