【问题标题】:Detect middle vertical line of a double side scanned image检测双面扫描图像的中间垂直线
【发布时间】:2021-09-08 01:23:03
【问题描述】:

我正在尝试检测图像中的长中间分隔垂直线,以便我可以根据该线将图像裁剪成两个单独的图像,尝试使用 HoughLinesP 但我如何确保它只选择中间垂直线,我可以清楚地看到那条线很容易区分。

我对它应用了opencv HoughLinesP,得到了以下结果

使用以下代码:

img = cv2.imread('./image.jpeg', 1)
img_gray = gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)


cannied = cv2.Canny(img_gray, threshold1=50, threshold2=200, apertureSize=3)
lines = cv2.HoughLinesP(cannied, rho=1, theta=np.pi / 180, threshold=80, minLineLength=30, maxLineGap=10)

for line in get_lines(lines):
    leftx, boty, rightx, topy = line
    cv2.line(img, (leftx, boty), (rightx,topy), (255, 255, 0), 2)

cv2.imwrite('./lines.png', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

我申请的更多资源

PyImageSearch

还有其他几个

【问题讨论】:

标签: python-3.x opencv image-processing opencv-contour


【解决方案1】:

根据此输入图像,您希望找到位于图像中间的最长垂直线。因此,您有多种选择:

  1. 裁剪图像的左右两侧,只保留中间的 1/3 或 1/4,这大致是实际中间线所在的位置。
  2. 调整cv2.HoughLinesP 中的参数minLineLength,以消除较短的行。
  3. 如果还剩下多行,那么最长的可能就是您想要的。要仔细检查,请计算线条的斜率,最垂直 + 最长的应该是最终答案。

【讨论】:

    【解决方案2】:

    这是一个可能的解决方案。它涉及从输入图像的几行中选择一个样本,然后使用cv2.reduce 函数将样本减少为一个行图像。循环通过减少的行并查找从0255 的像素强度跳跃,因为该转换表示您用于指导裁剪的页面区域。最后,将跳转的位置存储在列表中,以进一步裁剪图像中的页面。这些是步骤:

    1. 从图像中获取样本 ROI
    2. 减少样本 ROI 为大小为1 x width 的行图像,在MAX 模式下使用cv2.reduce 函数得到每列的最大强度值
    3. 遍历图像并寻找从0255强度转换 - 这个点是垂直线所在的位置
    4. list存储每个“转换位置”
    5. 使用“过渡位置”列表中的信息裁剪图像

    让我们看看代码:

    # Imports:
    import numpy as np
    import cv2
    
    # Set the image path
    path = "D://opencvImages//"
    fileName = "mx8lW.jpg"
    
    # Read the image in default mode:
    inputImage = cv2.imread(path + fileName)
    
    # Convert RGB to grayscale:
    grayscaleImage = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY)
    
    # Set the sample ROI and crop it:
    (imageHeight, imageWidth) = grayscaleImage.shape[:2]
    roiX = 0
    roiY = int(0.05 * imageHeight)
    roiWidth = imageWidth
    roiHeight = int(0.05 * imageHeight)
    
    # Crop the image:
    imageRoi = grayscaleImage[roiY:roiY+roiHeight, roiX:roiWidth]
    

    第一位读取图像,将其从BGR 转换为grayscale 并定义样本ROI。此 ROI 用于定位垂直线。由于图像中的垂直线是恒定的,因此只需选择和裁剪一个样本就可以了,而不是处理整个图像。我定义的 ROI 选择了图像顶部正下方的区域,因为有一些暗部可能会影响 ROI 减少为一行。

    此图像显示了选定的 ROI,用绿色矩形绘制:

    请注意,两条(最左侧和最右侧)垂直线在 ROI 内清晰显示。如果我们裁剪它,我们将得到这个示例图像:

    我们需要裁剪页面的所有信息都在那里。让我们threshold 图像来获得二进制掩码:

    # Thresholding:
    _, binaryImage = cv2.threshold(imageRoi, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    

    这是二进制掩码:

    注意从0255 的跳转以及它们的含义。每个过渡都表示我们可以用来裁剪两个页面的起点和终点。好的,让我们将reduce 二进制掩码设置为一行。我们将使用MAX模式,其中行中的每个像素值都定义为该图像列对应的最大强度值:

    # Reduce the ROI to a 1 x imageWidth row:
    reducedImg = cv2.reduce(binaryImage, 0, cv2.REDUCE_MAX)
    

    这是生成的图像,只是一行:

    让我们遍历这张图片(实际上只是一个普通的numpy 数组)并寻找那些转换。此外,让我们准备一个列表并在我们找到它们时存储跳转位置:

    # Store the transition positions here:
    linePositions = []
    
    # Find transitions from 0 to 255:
    pastPixel = 255
    for x in range(reducedImg.shape[1]):
        # Get current pixel:
        currentPixel = reducedImg[0,x]
        # Check for the "jumps":
        if currentPixel == 255 and pastPixel == 0:
            # Store the jump locations in list:
            print("Got Jump at:"+str(x))
            linePositions.append(x)
        # Set current pixel to past pixel:
        pastPixel = currentPixel
    

    酷,我们在linePositions 中准备好了跳跃位置。让我们最后裁剪图像。我已经通过位置列表实现了这种循环并设置了裁剪参数:

    # Crop pages:
    for i in range(len(linePositions)):
        # Get top left:
        cropX = linePositions[i]
        
        # Get top left:
        if i != len(linePositions)-1:
            # Get point from the list:
            cropWidth = linePositions[i+1]
        else:
            # Set point from the image's original width:
            cropWidth = reducedImg.shape[1]
    
        # Crop page:
        cropY = 0
        cropHeight = imageHeight
        currentCrop = inputImage[cropY:cropHeight,cropX:cropWidth]
    
        # Show current crop:
        cv2.imshow("CurrentCrop", currentCrop)
        cv2.waitKey(0)
    

    生产两种作物:

    【讨论】:

      猜你喜欢
      • 2023-01-16
      • 1970-01-01
      • 2013-02-10
      • 2020-09-27
      • 1970-01-01
      • 2011-01-29
      • 2014-11-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多