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

Python 使用OpenCV查找具有特定纵横比的旋转矩形?,python,opencv,python-3.6,Python,Opencv,Python 3.6,我没有困难转换一个找到的盒子,事实上,当盒子处于某个角度时,我首先无法检测到它 这是一个示例图像,我想要图像中最大的~1230:123矩形,问题是矩形可以旋转 这是我无法检测到的旋转条形码的图片: 我用来处理轮廓区域的函数只是寻找最大的矩形 我应该使用什么方法来查找旋转的矩形,以便即使在旋转时也能检测到它 #PYTHON 3.6 Snippet for Image Processing gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) #

我没有困难转换一个找到的盒子,事实上,当盒子处于某个角度时,我首先无法检测到它

这是一个示例图像,我想要图像中最大的~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
保留到最后,并得到您要查找的结果

您可以使用以下阶段:

  • 使用大津阈值法应用二值阈值(以防图像不是二值图像)
  • 执行
    cv2.findContours
    ,找到面积最大的轮廓
  • 使用
    cv2.minareact
    查找最小面积边界矩形
下面是一个代码示例:

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

结果:


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

你能发布原始图像吗?谢谢你的帮助,我将把我所有的东西都转换为使用大津。我遇到的问题是,它将左上角的渐变识别为矩形。四开始解决这个问题,首先得到一个透视图的完整卡删除背景。将其无角度转换为1920x1080,然后执行条形码查找功能。上面这张图片的问题是,即使整张卡片上有一点点角被切掉,它也无法识别出它是一个矩形。非常感谢