python 中用 cv2 连接手绘图像角的线
Lines connecting corners over hand drawn image in python with cv2
我想检测手绘图像上连接角的线 like this. I am using Harris Corner Detection to find the corners of the image. Next I am connecting all of the corners with lines and iterating though the points to see if they match the pixels from original image and setting a threshold for each line pixel cover to say what is acceptable to say it is a correct line connecting corners.Image of connected lines。它有效......但它非常慢。有没有更好的方法或我应该使用的不同方法? (霍夫线将无法工作,因为可能有曲线,我只想要连接角的线。
for i in c_corners: #corners thru harris and coorected with subpix
x1,y1 = i.ravel()
for k in c_corners:
x2,y2 = k.ravel()
if x1 != x2 and y1 != y2: #ignore vertical lines
linePoints = line_points(x1,y1, x2,y2) # function to get line pnts
totalLinePoints = len(linePoints)
coverPoints = 0
########## This is where I think the slow down is happening and could be optimized
for m in originalImage: #image is dialated to help detection
for n in linePoints:
match = np.all(m == n)
if match == True:
coverPoints += 1
print("Line Cover = ", (coverPoints/totalLinePoints))
if (coverPoints/totalLinePoints) > .65:
good_lines.append([x1,y1,x2,y2])
感谢任何帮助,谢谢!
我最初的方法是创建一个空白图像并在其上绘制每条线,然后使用 cv2.bitwise_and()
和二值(膨胀)图像来计算有多少像素一致,如果它们满足阈值,然后在原始图像上绘制这些线条。但是,为像素数设置阈值会惩罚细线。一个更好的指标是正确匹配与不正确匹配的数量之比(我现在意识到这就是你实际在做的事情)。此外,这对膨胀和您选择绘制线条的线条粗细更加稳健。
但是,您使用的一般方法对于绘图中的问题不是很稳健,在绘图中,像这一个一样,合成线可能能够轻松地适应它们不属于的线,因为许多绘制的曲线可能打一个线段。您可以在我的代码输出中看到这个问题:
我只是硬编码了一些角落估计,然后从那里开始。请注意使用 itertools
来帮助创建所有可能的点对来定义线段。
import cv2
import numpy as np
import itertools
img = cv2.imread('drawing.png')
bin_inv = cv2.bitwise_not(img) # flip image colors
bin_inv = cv2.cvtColor(bin_inv, cv2.COLOR_BGR2GRAY) # make one channel
bin_inv = cv2.dilate(bin_inv, np.ones((5,5)))
corners = ((517, 170),
(438, 316),
(574, 315),
(444, 436),
(586, 436))
lines = itertools.combinations(corners,2) # create all possible lines
line_img = np.ones_like(img)*255 # white image to draw line markings on
for line in lines: # loop through each line
bin_line = np.zeros_like(bin_inv) # create a matrix to draw the line in
start, end = line # grab endpoints
cv2.line(bin_line, start, end, color=255, thickness=5) # draw line
conj = (bin_inv/255 + bin_line/255) # create agreement image
n_agree = np.sum(conj==2)
n_wrong = np.sum(conj==1)
if n_agree/n_wrong > .05: # high agreements vs disagreements
cv2.line(line_img, start, end, color=[0,200,0], thickness=5) # draw onto original img
# combine the identified lines with the image
marked_img = cv2.addWeighted(img, .5, line_img, .5, 1)
cv2.imwrite('marked.png', marked_img)
我尝试了很多不同的设置(使用粗细、膨胀、不同的比率等),但无法让那条虚假的更长的线出现。它非常适合原始的黑色像素,所以我不确定如果你使用这种方法你将如何摆脱它。它有从右上角的线开始的曲线,以及它穿过的中间线, 和 右下角的曲线向该方向倾斜了一点。无论如何,运行 只需要两秒钟,所以至少它比您当前的代码快。
我想检测手绘图像上连接角的线 like this. I am using Harris Corner Detection to find the corners of the image. Next I am connecting all of the corners with lines and iterating though the points to see if they match the pixels from original image and setting a threshold for each line pixel cover to say what is acceptable to say it is a correct line connecting corners.Image of connected lines。它有效......但它非常慢。有没有更好的方法或我应该使用的不同方法? (霍夫线将无法工作,因为可能有曲线,我只想要连接角的线。
for i in c_corners: #corners thru harris and coorected with subpix
x1,y1 = i.ravel()
for k in c_corners:
x2,y2 = k.ravel()
if x1 != x2 and y1 != y2: #ignore vertical lines
linePoints = line_points(x1,y1, x2,y2) # function to get line pnts
totalLinePoints = len(linePoints)
coverPoints = 0
########## This is where I think the slow down is happening and could be optimized
for m in originalImage: #image is dialated to help detection
for n in linePoints:
match = np.all(m == n)
if match == True:
coverPoints += 1
print("Line Cover = ", (coverPoints/totalLinePoints))
if (coverPoints/totalLinePoints) > .65:
good_lines.append([x1,y1,x2,y2])
感谢任何帮助,谢谢!
我最初的方法是创建一个空白图像并在其上绘制每条线,然后使用 cv2.bitwise_and()
和二值(膨胀)图像来计算有多少像素一致,如果它们满足阈值,然后在原始图像上绘制这些线条。但是,为像素数设置阈值会惩罚细线。一个更好的指标是正确匹配与不正确匹配的数量之比(我现在意识到这就是你实际在做的事情)。此外,这对膨胀和您选择绘制线条的线条粗细更加稳健。
但是,您使用的一般方法对于绘图中的问题不是很稳健,在绘图中,像这一个一样,合成线可能能够轻松地适应它们不属于的线,因为许多绘制的曲线可能打一个线段。您可以在我的代码输出中看到这个问题:
我只是硬编码了一些角落估计,然后从那里开始。请注意使用 itertools
来帮助创建所有可能的点对来定义线段。
import cv2
import numpy as np
import itertools
img = cv2.imread('drawing.png')
bin_inv = cv2.bitwise_not(img) # flip image colors
bin_inv = cv2.cvtColor(bin_inv, cv2.COLOR_BGR2GRAY) # make one channel
bin_inv = cv2.dilate(bin_inv, np.ones((5,5)))
corners = ((517, 170),
(438, 316),
(574, 315),
(444, 436),
(586, 436))
lines = itertools.combinations(corners,2) # create all possible lines
line_img = np.ones_like(img)*255 # white image to draw line markings on
for line in lines: # loop through each line
bin_line = np.zeros_like(bin_inv) # create a matrix to draw the line in
start, end = line # grab endpoints
cv2.line(bin_line, start, end, color=255, thickness=5) # draw line
conj = (bin_inv/255 + bin_line/255) # create agreement image
n_agree = np.sum(conj==2)
n_wrong = np.sum(conj==1)
if n_agree/n_wrong > .05: # high agreements vs disagreements
cv2.line(line_img, start, end, color=[0,200,0], thickness=5) # draw onto original img
# combine the identified lines with the image
marked_img = cv2.addWeighted(img, .5, line_img, .5, 1)
cv2.imwrite('marked.png', marked_img)
我尝试了很多不同的设置(使用粗细、膨胀、不同的比率等),但无法让那条虚假的更长的线出现。它非常适合原始的黑色像素,所以我不确定如果你使用这种方法你将如何摆脱它。它有从右上角的线开始的曲线,以及它穿过的中间线, 和 右下角的曲线向该方向倾斜了一点。无论如何,运行 只需要两秒钟,所以至少它比您当前的代码快。