连接角落的线在手拉的图象在Python与cv2

时间:2017-06-14 14:04:51

标签: python opencv image-processing corner-detection

我希望检测连接手绘图像like this上的角落的线条。我正在使用哈里斯角点检测找到图像的角落。接下来,我用线条连接所有角落并迭代这些点以查看它们是否与原始图像中的像素匹配,并为每个线条像素覆盖设置一个阈值,说明可以接受的是说它是连接角落的正确线条。{ {3}}。它有效...但它很慢。有没有更好的方法来做这个或我应该使用的不同方法? (由于弯曲线的可能性,霍夫线不起作用,我只想连接角线。

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])

任何帮助都表示赞赏,谢谢!

1 个答案:

答案 0 :(得分:0)

我最初的方法是创建一个空白图像并在其上绘制每一行,然后使用cv2.bitwise_and()和二进制(扩张)图像来计算一致的像素数,如果它们达到阈值,然后在原始图像上绘制这些线条。然而,设置像素数量的阈值会对小线条造成不利影响。一个更好的指标是正确匹配数与错误匹配数的比率(我现在意识到你正在做的事情)。此外,这对于扩张和您选择绘制线条的线条厚度来说更加稳健。

然而,您使用的一般方法对于绘图中的问题并不是非常强大,在这种情况下,合成线可能很容易适合它们不属于的线,因为许多绘制的曲线可能会触及线段。您可以在我的代码输出中看到此问题:

Marked lines between edges

我只是硬编码了一些角落估计并从那里开始。请注意使用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)

我尝试了很多不同的设置(玩厚度,扩张,不同的比例等)并且无法让出现的虚假更长的线条。虽然它很适合原始的黑色像素,所以如果你使用这种方法,我不确定如何能够摆脱它。从它的右上方线开始的曲线,以及它穿过的中间线,右下方的曲线,这个方向趋向于一点。无论如何,这只需要两秒钟的时间来运行,所以至少它比你当前的代码更快。