简体   繁体   English

使用 OpenCV 找到一定纵横比的旋转矩形?

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

I am not having difficulty transforming a found box, it is the fact that I am not able to detect the box in the first place when it is at an angle.我在转换找到的盒子时没有困难,事实上,当盒子倾斜时,我首先无法检测到盒子。

Here is a sample image I want the largest ~1230:123 rectangle in the image the problem is the rectangle can be rotated.这是一个示例图像,我想要图像中最大的 ~1230:123 矩形,问题是矩形可以旋转。

Here is a picture of a rotated barcode that I am unable to detect:这是一张我无法检测到的旋转条形码图片:
在此处输入图像描述

The function I have been using to process uses contour area just looks for the largest rectangle.我一直用来处理使用轮廓区域的 function 只是寻找最大的矩形。

What methods should I use to look for a rotated rectangle so that even when rotated I can detect it?我应该使用什么方法来查找旋转的矩形,以便即使在旋转时我也可以检测到它?

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

You don't need all the preprocessing (like Sobel, erode, dilate) for finding before executing findContours .在执行findContours之前,您不需要所有的预处理(如 Sobel、erode、dilate)来进行查找。

findContours works better when contours are full (filled with white color) instead of having just the edges.当轮廓完整(填充白色)而不是只有边缘时, findContours效果更好。
I suppose you can keep the code from cv2.findContours to the end, and get the result you are looking for.我想您可以将cv2.findContours中的代码保留到最后,并获得您正在寻找的结果。

You may use the following stages:您可以使用以下阶段:

  • Apply binary threshold using Otsu's thresholding (just in case image is not a binary image).使用 Otsu 的阈值处理应用二进制阈值(以防图像不是二进制图像)。
  • Execute cv2.findContours , and Find the contour with the maximum area.执行cv2.findContours ,找到面积最大的轮廓。
  • Use cv2.minAreaRect for finding the minimum area bounding rectangle.使用cv2.minAreaRect查找最小面积边界矩形。

Here is a code sample:这是一个代码示例:

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

Result:结果:
在此处输入图像描述

Note: The largest contour seems to be a parallelogram and not a perfect rectangle.注意:最大的轮廓似乎是一个平行四边形,而不是一个完美的矩形。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM