Minimum bounding box or convex body for any quad shape?

Note. ... I am trying to create a process that can work with a general range of images, orientations and qualities, not just this image.

I understand that you can use a convex hull to enclose many points with a polygon, and you can use one of several algorithms to create a minimum bounding rectangle for those points. However, I want to do what looks like a minimum bounding box, but without bounding it to a rectangle.

Let's say I have this receipt:

enter image description here

Convex hull:

enter image description here

Minimum bounding rectangle (rotating caliper):

enter image description here

My target: (ms-paint):

enter image description here

As you can see, the minimum bounding box doesn't quite fit, since the receipt is a trapezoid from the point of view. It only gets worse, the lower the perspective. I want to have 4 points and sharp corners, so I cannot use a convex hull.

Is there an algorithm I can use to get something similar to a convex hull or minimum bounding box, but limited to four points and any four-sided shape?

+3


source to share


1 answer


With some confusion with color filtering and morphological operations, I was able to use the Harris detector with success. You can also expand on this using intersection points like here from Hough Lines, which can be helpful, albeit a little verbose. This works well for this particular image, but it requires a lot of parameters for the pipeline (open and close kernel sizes, iterations).

My implementation is in Python, but this of course could work in C ++ or Java too:

import numpy as np
import cv2

# read image
img = cv2.imread('receipt.png')

# thresholding
blur = cv2.GaussianBlur(img, (5,5), 1)
hls = cv2.cvtColor(blur, cv2.COLOR_BGR2HLS)
low = np.array([0, 70, 0])
high = np.array([255, 255, 85])
thresh = cv2.inRange(hls, low, high)

# morphological operations to get the paper
kclose = np.ones((3,3), dtype=np.uint8)
kopen = np.ones((5,5), dtype=np.uint8)
closing = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kclose, iterations=2)
opening = cv2.morphologyEx(closing, cv2.MORPH_OPEN, kopen, iterations=6)

# corner detection
opening = cv2.GaussianBlur(opening, (3,3), 1)
opening = np.float32(opening)
dst = cv2.cornerHarris(opening, 2, 3, 0.04)

# drawing corners
dst = cv2.dilate(dst, None)
img[dst>0.01*dst.max()]=[0,0,255]

cv2.imshow('Corners', img)
cv2.waitKey(0)

      

And here are the corners:

Corners

Note that you are getting a few pixels from Harris, so you will have to do clustering to get special corner points if you want to use them to deform later.

I applied masks from filtering colors, closing and opening on the image so that you can see the masks after these operations.



Filtration:

Filtration

Closing:

Closing

Opening:

Opening

+1


source







All Articles