基于 Python 的解决方案类似于 Yunus Temurlenk 的回答。首先应用 Otsu 阈值处理、canny 边缘检测和膨胀以获得良好的轮廓。接下来,按面积提取最大轮廓,基于最小面积矩形提取四个点。
此代码在此图像中没有dilation 步骤也可以工作。在这种情况下,轮廓将更紧密地适合矩形。
代码:
## Press ESC button to get next image
import cv2
import cv2 as cv
import numpy as np
#frame = cv2.imread('resources/pstr1.png')
frame = cv2.imread('resources/pstr2.png')
## keeping a copy of original
print(frame.shape)
original_frame = frame.copy()
## Show the original image
winName = 'Original'
cv.namedWindow(winName, cv.WINDOW_NORMAL)
cv.resizeWindow(winName, 800, 800)
cv.imshow(winName, original_frame)
cv.waitKey(0)
# Otsu's thresholding
grayimg = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
ret2,thresh_n = cv.threshold(grayimg,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
thresh_n = cv2.cvtColor(thresh_n, cv2.COLOR_GRAY2BGR)
frame = thresh_n
## edge detection
frame = cv2.Canny(frame,100,200)
## dilate the edges
kernel = np.ones((5,5),np.uint8)
frame = cv2.dilate(frame,kernel,iterations = 1)
## Get largest contour from contours
contours, hierarchy = cv2.findContours(frame, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
## Get minimum area rectangle and corner points
rect = cv2.minAreaRect(max(contours, key = cv2.contourArea))
box = cv2.boxPoints(rect)
print(box)
## draw anchor points on corner
z = 6
for b in box:
cv2.circle(original_frame, tuple(b), z, 255, -1)
## show original image with corners
box2 = np.int0(box)
cv2.drawContours(original_frame,[box2],0,(0,0,255), 2)
cv2.imshow('Detected Corners',original_frame)
cv2.waitKey(0)
cv2.destroyAllWindows()
输入图像:
输出图像: