【问题标题】:Detecting near-horizontal lines using Image processing使用图像处理检测近水平线
【发布时间】:2022-01-25 07:32:30
【问题描述】:

有什么方法可以使用 opencv 来检测几乎水平的线条吗?我对How to detect lines in OpenCV? 中提到的一些概念感到困惑——我可以用canny 进行边缘检测,但我对如何使用霍夫变换并将它们限制为水平线有点迷茫。

我这里有一堆示例图片:https://gist.github.com/jason-s/df90e41e29f3ba46e6ccabad4516e916

包括:

具体来说,每个图像都有一对大约 1200 像素长且与水平方向成 3 度角的水平边缘。 (这些是由我扫描的照片的角落组成的。)

对使用什么算法有什么建议吗?

【问题讨论】:

  • 迭代旋转图像。然后得到每一行的平均值,找到最大值的行。找到所有旋转角度中值最大的行。
  • 你的最终目标是什么?为什么需要找到这些行?您是否尝试提取图像?
  • 看看这个方法,它可能有用:stackoverflow.com/questions/67644977/…
  • @Jason S 我并不是说它们是相关的。我只是给你一个找到差距的方法。至于提取图片,我会通过阈值或更好的洪水填充来接近它。然后使用轮廓在二值图像中找到图片区域。然后从轮廓中,使用 minAreaRect() 获取旋转的矩形。

标签: python opencv image-processing


【解决方案1】:

根据线的方向度检测过滤器

import cv2
import numpy as np
import math

path='images/lines.png'
image = cv2.imread(path)

dst = cv2.Canny(image, 50, 200, None, 3)
linesP = cv2.HoughLinesP(dst, 1, np.pi / 180, 50, None, 50, 10)

if linesP is not None:
    for i in range(0, len(linesP)):
        l = linesP[i][0]

        #here l contains x1,y1,x2,y2  of your line
        #so you can compute the orientation of the line 
        p1 = np.array([l[0],l[1]])
        p2 = np.array([l[2],l[3]])

        p0 = np.subtract( p1,p1 ) #not used
        p3 = np.subtract( p2,p1 ) #translate p2 by p1

        angle_radiants = math.atan2(p3[1],p3[0])
        angle_degree = angle_radiants * 180 / math.pi

        print("line degree", angle_degree)

        if 0 < angle_degree < 15 or 0 > angle_degree > -15 :
            cv2.line(image,  (l[0], l[1]), (l[2], l[3]), (0,0,255), 1, cv2.LINE_AA)


cv2.imshow("Source", image)

print("Press any key to close")
cv2.waitKey(0)
cv2.destroyAllWindows()

【讨论】:

    【解决方案2】:

    您可以使用 tan inverse 找到直线与地面平行的角度。

    for x1,y1,x2,y2 in lines[0]:
       angle = math.degrees(math.atan((abs(y2-y1))/abs(x2-x1)))
       cv2.line(img2,(x1,y1),(x2,y2),(255,0,0),1)
       print(angle)
    

    然后您可以按照@Mario 的说明过滤这些行。由于上面使用 abs() 来查找差异,因此您必须仅使用正范围过滤角度。

    【讨论】:

    • 谢谢,不过我不需要使用 atan;可以通过预计算 tan 3 ~ 0.0524 来检查斜率是否在 3 度以内。
    • 太好了,你也可以使用 tan 3 本身的值。
    【解决方案3】:

    我尝试使用 Fred (@fmw42) 建议的变体。我首先尝试通过转换为 HSV 颜色空间然后找到既不饱和又明亮的像素来定位图像边框上的所有白色像素。

    然后,我将生成的图像以 0.1 度的增量旋转 -5 到 +5 度。在每个旋转角度,我运行一个 SobelY 过滤器来寻找水平边缘。然后我计算了每一行中的白色像素。每当我找到导致较长水平线的方向时,我都会更新我的最佳估计并记住旋转。

    可能有很多变体,但这应该可以帮助您入门:

    #!/usr/bin/env python3
    
    import cv2
    import numpy as np
    
    # Load image
    im = cv2.imread('a4e.jpg')
    
    # Find white pixels, i.e. unsaturated and bright
    HSV = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)
    
    unsat = HSV[:,:,1] < 50
    bright= HSV[:,:,2] > 240
    
    white = ((unsat & bright)*255).astype(np.uint8)
    cv2.imwrite('DEBUG-white.png', white)
    

    看起来像这样:

    # Pad with border so it isn't cropped when rotated, get new dimensions
    bw = 100
    white = cv2.copyMakeBorder(white, bw, bw, bw, bw, borderType= cv2.BORDER_CONSTANT)
    w, h = white.shape[:2]
    
    # Find rotation that results in horizontal row with largest number of white pixels
    maxOverall = 0
    
    # SobelY horizontal edge kernel
    kernel = np.array((
        [-1, -2, -1],
        [0, 0, 0],
        [1, 2, 1]), dtype="int")
    
    # Rotate image -5 to +5 degrees in 0.1 degree increments
    for angle in [x * 0.1 for x in range(-50, 50)]:
       M = cv2.getRotationMatrix2D((h/2,w/2),angle,1)
       rotated = cv2.warpAffine(white,M,(h,w))
       # Output image for debug purposes
       cv2.imwrite(f'DEBUG rotated {angle}.jpg',rotated)
    
       # Filter for horizontal edges
       filtered = cv2.filter2D(rotated, -1, kernel)
       cv2.imwrite(f'DEBUG rotated {angle} filtered.jpg',filtered)
    
       # Check for maximum white pixels in any row
       maxThis = np.amax(np.sum(rotated, axis=1))
       if maxThis > maxOverall:
          print(f'Angle:{angle}: New longest horizontal row has {maxThis} white pixels')
          maxOverall = maxThis
    

    整个流程是这样的:

    输出是这样的,表示检测到的角度是0.6度:

    Angle:-5.0: New longest horizontal row has 34287 white pixels
    Angle:-4.9: New longest horizontal row has 34517 white pixels
    Angle:-4.800000000000001: New longest horizontal row has 34809 white pixels
    Angle:-4.7: New longest horizontal row has 35191 white pixels
    Angle:-4.6000000000000005: New longest horizontal row has 35625 white pixels
    Angle:-4.5: New longest horizontal row has 36108 white pixels
    Angle:-4.4: New longest horizontal row has 36755 white pixels
    Angle:-4.3: New longest horizontal row has 37436 white pixels
    Angle:-4.2: New longest horizontal row has 38151 white pixels
    Angle:-4.1000000000000005: New longest horizontal row has 38876 white pixels
    Angle:-4.0: New longest horizontal row has 39634 white pixels
    Angle:-3.9000000000000004: New longest horizontal row has 40414 white pixels
    Angle:-3.8000000000000003: New longest horizontal row has 41240 white pixels
    Angle:-3.7: New longest horizontal row has 42074 white pixels
    Angle:-3.6: New longest horizontal row has 42889 white pixels
    Angle:-3.5: New longest horizontal row has 43570 white pixels
    Angle:-3.4000000000000004: New longest horizontal row has 44252 white pixels
    Angle:-3.3000000000000003: New longest horizontal row has 44902 white pixels
    Angle:-3.2: New longest horizontal row has 45776 white pixels
    Angle:-3.1: New longest horizontal row has 46620 white pixels
    Angle:-3.0: New longest horizontal row has 47414 white pixels
    Angle:-2.9000000000000004: New longest horizontal row has 48178 white pixels
    Angle:-2.8000000000000003: New longest horizontal row has 48705 white pixels
    Angle:-2.7: New longest horizontal row has 49225 white pixels
    Angle:-2.6: New longest horizontal row has 49962 white pixels
    Angle:-2.5: New longest horizontal row has 51501 white pixels
    Angle:-2.4000000000000004: New longest horizontal row has 53217 white pixels
    Angle:-2.3000000000000003: New longest horizontal row has 54997 white pixels
    Angle:-2.2: New longest horizontal row has 56926 white pixels
    Angle:-2.1: New longest horizontal row has 59033 white pixels
    Angle:-2.0: New longest horizontal row has 61017 white pixels
    Angle:-1.9000000000000001: New longest horizontal row has 62538 white pixels
    Angle:-1.8: New longest horizontal row has 63370 white pixels
    Angle:-1.7000000000000002: New longest horizontal row has 64144 white pixels
    Angle:-1.6: New longest horizontal row has 65685 white pixels
    Angle:-1.5: New longest horizontal row has 68510 white pixels
    Angle:-1.4000000000000001: New longest horizontal row has 72377 white pixels
    Angle:-1.3: New longest horizontal row has 76693 white pixels
    Angle:-1.2000000000000002: New longest horizontal row has 80932 white pixels
    Angle:-1.1: New longest horizontal row has 84101 white pixels
    Angle:-1.0: New longest horizontal row has 86557 white pixels
    Angle:-0.9: New longest horizontal row has 90499 white pixels
    Angle:-0.8: New longest horizontal row has 97179 white pixels
    Angle:-0.7000000000000001: New longest horizontal row has 101430 white pixels
    Angle:-0.6000000000000001: New longest horizontal row has 105001 white pixels
    Angle:-0.5: New longest horizontal row has 112976 white pixels
    Angle:-0.4: New longest horizontal row has 117256 white pixels
    Angle:-0.30000000000000004: New longest horizontal row has 131478 white pixels
    Angle:-0.2: New longest horizontal row has 141468 white pixels
    Angle:-0.1: New longest horizontal row has 164588 white pixels
    Angle:0.0: New longest horizontal row has 186150 white pixels
    Angle:0.1: New longest horizontal row has 206695 white pixels
    Angle:0.2: New longest horizontal row has 230821 white pixels
    Angle:0.30000000000000004: New longest horizontal row has 249003 white pixels
    Angle:0.4: New longest horizontal row has 258888 white pixels
    Angle:0.6000000000000001: New longest horizontal row has 264409 white pixels
    

    【讨论】:

      猜你喜欢
      • 2020-09-05
      • 2020-08-10
      • 1970-01-01
      • 1970-01-01
      • 2020-09-27
      • 2011-11-05
      • 2017-02-06
      • 2019-09-06
      • 1970-01-01
      相关资源
      最近更新 更多