如何从python中的模糊图像中找到变形矩形的准确角位置?

问题描述:

我正在寻找一种使用Python中的OpenCV准确检测扭曲矩形的角的过程.

I am looking for a procedure to detect the corners of an distorted rectangle accurately with OpenCV in Python.

我已经通过谷歌搜索尝试了不同建议的解决方案,但是通过直线的正弦叠加(请参见阈值图像),我可能无法检测到拐角.到目前为止,我尝试过findContours和HoughLines,但效果不佳. 不幸的是,在如何用opencv查找模糊角位置?

I've tried the solution of different suggestions by googling, but through a sinusoidal superposition of a straight line (see the thresholded image) I probably can't detect the corners. I tried findContours and HoughLines so far without good results. Unfortunately I don't understand the C-Code from Xu Bin in how to find blur corner position with opencv?

这是我的初始图片:

调整大小和阈值后,我应用canny边缘检测来获取以下图像:

After resizing and thresholding I apply canny edge detection to get following image:

contours, hierarchy = cv2.findContours(g_mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
box = cv2.minAreaRect(contour)
box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)
box = np.array(box, dtype="float")
box = perspective.order_points(box)

我只能通过一些额外的绘图获得以下结果:

I only get the following result with some extra drawing:

我认为线路拟合将是解决问题的一种好方法,但是不幸的是,在查看

I thought line fitting would be a good way to solve the problem, but unfortunately I couldn't get HoughLines working and after looking in OpenCV Python - How to implement RANSAC to detect straight lines? RANSAC seems also difficult to apply for my problem.

我们非常感谢您的帮助.

Any help is highly appreciated.

要检测拐角,可以使用

To detect corners, you can use cv2.goodFeaturesToTrack(). The function takes four parameters

corners = cv2.goodFeaturesToTrack(image, maxCorners, qualityLevel, minDistance)

  • image-输入8位或浮点32位灰度单通道图像
  • maxCorners-要返回的最大拐角数
  • qualityLevel-0-1之间的最小可接受角点质量等级.低于质量级别的所有角落都被拒绝
  • minDistance-角之间的最小欧几里得距离
    • image - Input 8-bit or floating-point 32-bit grayscale single-channel image
    • maxCorners - Maximum number of corners to return
    • qualityLevel - Minimum accepted quality level of corners between 0-1. All corners below quality level are rejected
    • minDistance - Minimum possible Euclidean distance between corners
    • 现在我们知道如何找到角,我们必须找到旋转的矩形并应用该函数.这是一种方法:

      Now that we know how to find corners, we have to find the rotated rectangle and apply the function. Here's an approach:

      我们首先放大图像,转换为灰度,应用双边滤镜,然后使用Otsu的阈值获得二进制图像

      We first enlarge the image, convert to grayscale, apply a bilateral filter, then Otsu's threshold to get a binary image

      接下来,我们通过使用cv2.findContours()查找轮廓来找到变形的矩形,然后获得以绿色突出显示的旋转边界框.我们将此边界框绘制到蒙版上

      Next we find the distorted rectangle by finding contours with cv2.findContours() then obtain the rotated bounding box highlighted in green. We draw this bounding box onto a mask

      现在有了遮罩,我们只需使用cv2.goodFeaturesToTrack()在遮罩上找到角点

      Now that we have the mask, we simply use cv2.goodFeaturesToTrack() to find the corners on the mask

      这是原始输入图像上的结果以及每个角的(x, y)坐标

      Here's the result on the original input image and the (x, y) coordinates for each corner

      角点

(377.0, 375.0)
(81.0, 344.0)
(400.0, 158.0)
(104.0, 127.0)

代码

import cv2
import numpy as np
import imutils

# Resize image, blur, and Otsu's threshold
image = cv2.imread('1.png')
resize = imutils.resize(image, width=500)
mask = np.zeros(resize.shape, dtype=np.uint8)
gray = cv2.cvtColor(resize, cv2.COLOR_BGR2GRAY)
blur = cv2.bilateralFilter(gray,9,75,75)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# Find distorted rectangle contour and draw onto a mask
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
rect = cv2.minAreaRect(cnts[0])
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(resize,[box],0,(36,255,12),2)
cv2.fillPoly(mask, [box], (255,255,255))

# Find corners on the mask
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
corners = cv2.goodFeaturesToTrack(mask, maxCorners=4, qualityLevel=0.5, minDistance=150)

for corner in corners:
    x,y = corner.ravel()
    cv2.circle(resize,(x,y),8,(155,20,255),-1)
    print("({}, {})".format(x,y))

cv2.imshow('resize', resize)
cv2.imshow('thresh', thresh)
cv2.imshow('mask', mask)
cv2.waitKey()