在对象中查找矩形的轮廓

时间:2019-02-03 21:58:52

标签: python opencv

我想找到对象内部矩形照片的轮廓。我曾尝试使用OpenCV的拐角检测功能,但无济于事。我还尝试使用findContours查找所有轮廓,并过滤出(多于或少于)4个边缘的轮廓,但这也没有导致任何问题。

我在这里有一个sample scan

1 个答案:

答案 0 :(得分:0)

我为您提供了解决方案,但这涉及很多步骤。同样,它可能不能很好地概括这一点。但是,它确实对您的图像效果很好。

首先创建灰度和阈值,然后使用findContours创建纸区域的蒙版。将该遮罩反转并与原始图像合并,使黑色边缘变白。在生成的图像上创建新的灰度和阈值,然后将其反转,以便findContours可以找到照片的暗像素。选择一个围绕最大轮廓的旋转框,这就是您要寻找的区域。

我添加了一些多余的东西,虽然您可能不需要,但是可能很方便:将透视扭曲应用于框,因此将所需区域制作为直角矩形。

发生了很多事情,所以我建议您花一些时间看一下中间步骤,以了解发生了什么。

结果:

enter image description here

代码:

import numpy as np 
import cv2
# load image
image = cv2.imread('photo.jpg')
# resize to easily view on screen, remove for final processing
image = cv2.resize(image,None,fx=0.2, fy=0.2, interpolation = cv2.INTER_CUBIC)

### remove outer black edge
# create grayscale
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# perform threshold
retr , mask = cv2.threshold(gray_image, 190, 255, cv2.THRESH_BINARY)
# remove noise
kernel =  np.ones((5,5),np.uint8)
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
# create emtpy mask
mask_2 = np.zeros(image.shape[:3], dtype=image.dtype)
# find contours
ret, contours, hier = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# draw the found shapes (white, filled in ) on the empty mask
for cnt in contours:
    cv2.drawContours(mask_2, [cnt], 0, (255,255,255), -1)

# invert mask and combine with original image - this makes the black outer edge white
mask_inv_2 = cv2.bitwise_not(mask_2)
tmp = cv2.bitwise_or(image, mask_inv_2)

### Select photo - not inner edge
# create grayscale
gray_image2 = cv2.cvtColor(tmp, cv2.COLOR_BGR2GRAY)
# perform threshold
retr, mask3 = cv2.threshold(gray_image2, 190, 255, cv2.THRESH_BINARY)
# remove noise
maskX = cv2.morphologyEx(mask3, cv2.MORPH_CLOSE, kernel)
# invert mask, so photo area can be found with findcontours
maskX = cv2.bitwise_not(maskX)
# findcontours
ret, contours2, hier = cv2.findContours(maskX, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# select the largest contour
largest_area = 0
for cnt in contours2:
    if cv2.contourArea(cnt) > largest_area:
        cont = cnt
        largest_area = cv2.contourArea(cnt)

# find the rectangle (and the cornerpoints of that rectangle) that surrounds the contours / photo
rect = cv2.minAreaRect(cont)
box = cv2.boxPoints(rect)
box = np.int0(box)
print(rect)

#### Warp image to square
# assign cornerpoints of the region of interest
pts1 = np.float32([box[1],box[0],box[2],box[3]])
# provide new coordinates of cornerpoints
pts2 = np.float32([[0,0],[0,450],[630,0],[630,450]])

# determine and apply transformationmatrix
M = cv2.getPerspectiveTransform(pts1,pts2)
result = cv2.warpPerspective(image,M,(630,450))

#draw rectangle on original image
cv2.drawContours(image, [box], 0, (255,0,0), 2)

#show image
cv2.imshow("Result", result)
cv2.imshow("Image", image)

cv2.waitKey(0)
cv2.destroyAllWindows()