【问题标题】:Using OpenCV to find a rotated rectangle of a certain aspect ratio?使用 OpenCV 查找具有一定纵横比的旋转矩形?
【发布时间】:2021-03-23 06:59:03
【问题描述】:

我在转换找到的盒子时没有遇到困难,事实上,当盒子倾斜时,我一开始就无法检测到它。

这是一个示例图像,我想要图像中最大的 ~1230:123 矩形,问题是矩形可以旋转。

这是一张我无法检测到的旋转条形码图片:

我一直用来处理的函数使用轮廓区域只是寻找最大的矩形。

我应该使用什么方法来寻找一个旋转的矩形,这样即使在旋转时我也能检测到它?

    #PYTHON 3.6 Snippet for Image Processing

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# compute the Scharr gradient magnitude representation of the images
# in both the x and y direction using OpenCV 2.4
ddepth = cv2.cv.CV_32F if imutils.is_cv2() else cv2.CV_32F
gradX = cv2.Sobel(gray, ddepth=ddepth, dx=1, dy=0, ksize=-1)
gradY = cv2.Sobel(gray, ddepth=ddepth, dx=0, dy=1, ksize=-1)
# subtract the y-gradient from the x-gradient
gradient = cv2.subtract(gradX, gradY)
gradient = cv2.convertScaleAbs(gradient)
# blur and threshold the image
blurred = cv2.blur(gradient, (8, 8))
(_, thresh) = cv2.threshold(blurred, 225, 255, cv2.THRESH_BINARY)
# construct a closing kernel and apply it to the thresholded image
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7))
closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)
# perform a series of erosions and dilations
closed = cv2.erode(closed, None, iterations = 4)
closed = cv2.dilate(closed, None, iterations = 4)
# find the contours in the thresholded image, then sort the contours
# by their area, keeping only the largest one
cnts = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
c = sorted(cnts, key = cv2.contourArea, reverse = True)[0]
# compute the rotated bounding box of the largest contour

rect = cv2.minAreaRect(c)

【问题讨论】:

标签: python opencv python-3.6


【解决方案1】:

在执行 findContours 之前,您不需要所有的预处理(如 Sobel、erode、dilate)来查找。

findContours 在轮廓完整(用白色填充)而不是只有边缘时效果更好。
我想您可以将代码从cv2.findContours 保留到最后,并得到您正在寻找的结果。

您可以使用以下阶段:

  • 使用 Otsu 的阈值处理应用二进制阈值(以防图像不是二进制图像)。
  • 执行cv2.findContours,找到面积最大的轮廓。
  • 使用cv2.minAreaRect 查找最小面积边界矩形。

这是一个代码示例:

import numpy as np
import cv2

img = cv2.imread('img.png', cv2.IMREAD_GRAYSCALE)  # Read input image as gray-scale

ret, img = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)  # Apply threshold using Otsu's thresholding (just in case image is not a binary image).

# Find contours in img.
cnts = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2]  # [-2] indexing takes return value before last (due to OpenCV compatibility issues).

# Find the contour with the maximum area.
c = max(cnts, key=cv2.contourArea)

# Find the minimum area bounding rectangle
# https://stackoverflow.com/questions/18207181/opencv-python-draw-minarearect-rotatedrect-not-implemented
rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
box = np.int0(box)

# Convert image to BGR (just for drawing a green rectangle on it).
bgr_img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

cv2.drawContours(bgr_img, [box], 0, (0, 255, 0), 2)

# Show images for debugging
cv2.imshow('bgr_img', bgr_img)
cv2.waitKey()
cv2.destroyAllWindows()

结果:

注意:最大的轮廓似乎是一个平行四边形,而不是一个完美的矩形。

【讨论】:

  • 将把我所有的东西都转换成使用 OTSU 感谢您的帮助。我也遇到的问题是将左上角的渐变识别为矩形。 Iv 首先通过去除背景的完整卡片的透视图来解决这个问题。将其转换为 1920x1080 不带角度,然后执行条码查找功能。上图的问题是,即使从完整的卡片上切掉一点角,它也不会将其识别为矩形。非常感谢
猜你喜欢
  • 2016-05-07
  • 1970-01-01
  • 2020-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-16
  • 2021-10-20
  • 2013-06-12
相关资源
最近更新 更多