Given this image:
I'd like to make it such that it will rotate and stretch to fully fit in the bounding box with no whitespace on the outside of the largest rectangular box. It should also account for worse perspective case, like in the links I list later on.
Basically, while it is not noticeable, the rectangle is rotated a little bit, and I'd like to fix that distortion.
However, I got an error when attempting to retrieve the four points of the contour. I have made sure and utilized contour approximation to isolate and get only relevant looking contours and as you can see in the image it's successful, though I can't use perspective warp on it.
I've already tried the links here:
- How to straighten a rotated rectangle area of an image using opencv in python?
- https://www.pyimagesearch.com/2014/05/05/building-pokedex-python-opencv-perspective-warping-step-5-6/
- https://www.pyimagesearch.com/2014/09/01/build-kick-ass-mobile-document-scanner-just-5-minutes/
And followed them, with only minor modifications (like not downscaling the image and then upscaling it) and different input image.
There is a similar error encountered by a reader there in the comments, but the author just said to use contour approximation. I did that but I still receive the same error.
I have already retrieved the contour (which along with its bounding box, is the image illustrated earlier), and used this code to attempt persective warp:
def warp_perspective(cnt):
# reshape cnt to get tl, tr, br, bl points
pts = cnt.reshape(4, 2)
rect = np.zeros((4, 2), dtype="float32")
s = pts.sum(axis=1)
rect[0] = pts[np.argmin(s)]
rect[2] = pts[np.argmin(s)]
diff = np.diff(pts, axis=1)
rect[1] = pts[np.argmin(diff)]
rect[2] = pts[np.argmax(diff)]
# solve for the width of the image
(tl, tr, br, bl) = rect
widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
# solve for the height of the image
heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
# get the final dimensions
maxWidth = max(int(widthA), int(widthB))
maxHeight = max(int(heightA), int(heightB))
# construct the dst image
dst = np.array([
[0, 0],
[maxWidth - 1, 0],
[maxWidth - 1, maxHeight - 1],
[0, maxHeight - 1]], dtype="float32")
# calculate perspective transform matrix
# warp the perspective
M = cv2.getPerspectiveTransform(rect, dst)
warp = cv2.warpPerspective(orig, M, (maxWidth, maxHeight))
cv2.imshow("warped", warp)
return warp
The function accepts cnt
as a single contour.
Upon running I ran into this error I mentioned earlier:
in warp_perspective
pts = cnt.reshape(4, 2)
ValueError: cannot reshape array of size 2090 into shape (4,2)
Which I do not understand at all. I have successfully isolated and retrieved the correct contour and bounding box, and the only thing I did differently was to skip downscaling..