How to find accurate corner positions of a distorted rectangle from blurry image in python?

丶灬走出姿态 提交于 2020-01-04 05:33:13

问题


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

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?

This is my initial image:

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.


回答1:


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

corners = cv2.goodFeaturesToTrack(image, maxCorners, qualityLevel, 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:


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

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

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

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

Corner points

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

Code

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


来源:https://stackoverflow.com/questions/58736927/how-to-find-accurate-corner-positions-of-a-distorted-rectangle-from-blurry-image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!