首页 > 解决方案 > OpenCV:找不到大矩形轮廓

问题描述

Opencv版本:4.5

我试图通过将对象设置在网格上并尽可能接近自上而下的照片来重新创建对象的尺寸,然后我将获得最大边界矩形的轮廓,然后进行透视扭曲。

我目前无法获得大边界正方形的轮廓,但是,它不断地只找到较小的矩形/正方形,我认为这些矩形/正方形不够大,无法正确修复视角。

第一张图:原图

在此处输入图像描述

第二张图片:我使用 openCV 的代码得到了什么 在此处输入图像描述

第三张图片:接近我理想的结果 在此处输入图像描述

我的代码:

import imutils
import numpy as np
import cv2 as cv

# load the query image
image = cv.imread("path/to/image")

# make image greyscale, blur, find edges
grayscale_image = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
thresh = cv.adaptiveThreshold(grayscale_image, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C,
                              cv.THRESH_BINARY, 11, 2)

# find contours in the threshed image, keep only the largest
# ones
cnts = cv.findContours(
    thresh.copy(), cv.RETR_LIST, cv.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
cnts = sorted(cnts, key=cv.contourArea, reverse=True)[:5]

# draw contours for reference
cv.drawContours(image, cnts, -1, (0, 255, 0), 3)

我尝试使用双边滤波器或高斯模糊进行预处理,而不是自适应阈值处理,但结果仍然找不到大矩形。

任何帮助将不胜感激,因为我不知道为什么它无法检测到更大的正方形。另外,如果人们认为有更好的方法来固定透视图以便我可以准确地重新创建电路板尺寸,请告诉我。

标签: pythonopencvimage-processingopencv-contour

解决方案


您可以申请以下阶段:

  • 使用cv2.threshold(而不是cv2.adaptiveThreshold)应用阈值。
  • 使用长列向量应用开口以仅保留垂直线。
  • 在 中查找轮廓vert_lines
  • 从左到右对轮廓进行排序。
  • 在草图(黑色)图像上绘制最左边和最右边的轮廓。
  • 应用带有长行矢量的开口以仅保留水平线,查找轮廓,从上到下排序,并绘制顶部和底部轮廓。
  • 在草图图像中找到内部轮廓(左、右、顶和底线)。
    内轮廓是最小的。

这是一个代码示例:

import imutils
import numpy as np
import cv2

# load the query image
image = cv2.imread("image.png")

# make image greyscale, blur, find edges
grayscale_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

#thresh = cv2.adaptiveThreshold(grayscale_image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
thresh = cv2.threshold(grayscale_image, 0, 255, cv2.THRESH_OTSU)[1]  # Apply automatic threshold (use THRESH_OTSU).

rect_im = np.zeros_like(thresh)  # Sketch image

# Apply opening with long column vector for keeping only the vertical lines.
vert_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, np.ones(50))

# Apply opening with long row vector for keeping only the horizontal lines.
horz_lines = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, np.ones((1,50)))

# Find contours in vert_lines
cnts = imutils.grab_contours(cv2.findContours(vert_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE))

# Sort contours left to right.
cnts = sorted(cnts, key=lambda c: cv2.boundingRect(c)[0])  # cv2.boundingRect(c)[0] is the left side x coordinate.

cv2.drawContours(rect_im, [cnts[0], cnts[-1]], -1, 255, -1) # Draw left and right contours

# Find contours in horz_lines
cnts = imutils.grab_contours(cv2.findContours(horz_lines, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE))

# Sort contours top to bottom.
cnts = sorted(cnts, key=lambda c: cv2.boundingRect(c)[1])  # cv2.boundingRect(c)[1] is the top y coordinate.

cv2.drawContours(rect_im, [cnts[0], cnts[-1]], -1, 255, -1)  # Draw top and bottom contours

# Find contours in rect_im
cnts = imutils.grab_contours(cv2.findContours(rect_im, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE))  # Note: use RETR_TREE for getting inner contour.

c = min(cnts, key=cv2.contourArea)  # Get the smallest contour

# Draw contour for reference
cv2.drawContours(image, [c], -1, (0, 255, 0), 3)

结果:

thresh
在此处输入图像描述

vert_lines
在此处输入图像描述

horz_lines
在此处输入图像描述

左右线:
在此处输入图像描述

rect_im
在此处输入图像描述

image(输出):
在此处输入图像描述


推荐阅读