2017-03-07 234 views
1

目前我工作的一个项目,我尝试使用OpenCV中找到矩形表面的照片的角落(的Python,Java或C++)OpenCV的:检测有缺陷的矩形

我选择所需表面通过过滤颜色,然后我有面具和它传递给cv2.findContours

cnts, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) 
cnt = sorted(cnts, key = cv2.contourArea, reverse = True)[0] 
peri = cv2.arcLength(cnt, True) 
approx = cv2.approxPolyDP(cnt, 0.02*peri, True) 
if len(approx) == 4: 
    cv2.drawContours(mask, [approx], -1, (255, 0, 0), 2) 

这给了我一个不准确的结果: findContours result

使用cv2.HoughLines我已经成功地得到4条直线准确地描述表面。它们的交叉点正是我需要的:

edged = cv2.Canny(mask, 10, 200) 
hLines = cv2.HoughLines(edged, 2, np.pi/180, 200) 
lines = [] 
for rho,theta in hLines[0]: 
    a = np.cos(theta) 
    b = np.sin(theta) 
    x0 = a*rho 
    y0 = b*rho 
    x1 = int(x0 + 1000*(-b)) 
    y1 = int(y0 + 1000*(a)) 
    x2 = int(x0 - 1000*(-b)) 
    y2 = int(y0 - 1000*(a)) 
    cv2.line(mask, (x1,y1), (x2,y2), (255, 0, 0), 2) 
    lines.append([[x1,y1],[x2,y2]]) 

HoughLines result

的问题是:是否有可能以某种方式调整findContours

另一种解决办法是找到交叉点的坐标。这种方法的任何线索,欢迎:)

任何人可以给我一个提示如何解决这个问题呢?

+0

“他们的交点正是我需要的” - - 在这种情况下计算它们的交点。 –

+0

你能给我一个线索我怎么能做到这一点? – Aray

+1

已经有很多线索可用,例如http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect或https://en.wikipedia.org/ wiki/Line%E2%80%93line_intersection或http://stackoverflow.com/a/7448287/3962537 –

回答

0

的发现,因为它似乎是路口也不是那么琐碎的问题,而是会被发现的交叉点之前,以下问题需要考虑:

  1. 最重要的是要选择对合适的参数HoughLines功能,因为它可以从0回到线的无限数字(我们需要4个平行)
  2. 由于我们没有在这些线路走,他们需要什么才能知道彼此
  3. 由于进行比较透视,平行线不再平行,因此每条线都会有一个相交点与其他人一起。一个简单的解决方案是过滤照片外的坐标。但可能会发生照片内出现不希望的交叉路口。
  4. 坐标应进行排序。根据任务的不同,可以通过不同的方式完成。

cv2.HoughLines将为每行返回值为rho and theta的数组。 现在的问题变成方程的所有行的成对系统:

system of equations

def intersections(edged): 
    # Height and width of a photo with a contour obtained by Canny 
    h, w = edged.shape 

    hl = cv2.HoughLines(edged,2,np.pi/180,190)[0] 
    # Number of lines. If n!=4, the parameters should be tuned 
    n = hl.shape[0]  

    # Matrix with the values of cos(theta) and sin(theta) for each line 
    T = np.zeros((n,2),dtype=np.float32) 
    # Vector with values of rho 
    R = np.zeros((n),dtype=np.float32) 

    T[:,0] = np.cos(hl[:,1]) 
    T[:,1] = np.sin(hl[:,1]) 
    R = hl[:,0] 

    # Number of combinations of all lines 
    c = n*(n-1)/2 
    # Matrix with the obtained intersections (x, y) 
    XY = np.zeros((c,2)) 
    # Finding intersections between all lines 
    for i in range(n): 
     for j in range(i+1, n): 
      XY[i+j-1, :] = np.linalg.inv(T[[i,j],:]).dot(R[[i,j]]) 

    # filtering out the coordinates outside the photo 
    XY = XY[(XY[:,0] > 0) & (XY[:,0] <= w) & (XY[:,1] > 0) & (XY[:,1] <= h)] 
    # XY = order_points(XY) # obtained points should be sorted 
    return XY 

这里是结果:

enter image description here

-1

是可能的:

  1. 选择最长的轮廓
  2. 断裂成片段,并将它们组由梯度
  3. 拟合线到最大的四组
  4. 查找交点

但随后,Hough变换做几乎同样的事情。有没有特别的理由不使用它?

线的交叉点是很容易计算。高中坐标几何课可以为您提供算法。

+0

其实我使用Hough变换来检测线条(第二个例子) – Aray

+0

在这种情况下,这种情况的最佳解决方案是找到交点,因为您已经在更新后的问题中完成了。在实际情况下,您需要一种方法来为线路选择最佳的四位候选人。 – Totoro

+1

我只是使用while循环,直到我只有4行。不是最好的解决方案,但工作 – Aray