使用 OpenCV 查找特定纵横比的旋转矩形?

Using OpenCV to find a rotated rectangle of a certain aspect ratio?

我在转换找到的盒子时没有困难,事实是当盒子倾斜时我无法首先检测到盒子。

这是一个示例图像我想要图像中最大的 ~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)

在执行 findContours.

之前,您不需要所有的预处理(如 Sobel、腐蚀、扩张)来查找

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
# 
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()

结果:

注意:最大的轮廓好像是平行四边形,不是正方形。