rizkyputrapb
rizkyputrapb

Reputation: 95

Rotating QR code to the correct position using Python OpenCV

I'm a beginner in python and currently studying QR code detection and decoding. I'm having a hard time rotating the detected QR code to the right position. I already used minAreaRect() to rotate my QR code but it doesn't work. Is there any workaround or a right way to do this? thanks!

ROI2 = cv2.imread('ROI.png')
gray2 = cv2.cvtColor(ROI2, cv2.COLOR_BGR2GRAY)
blur2 = cv2.GaussianBlur(gray2, (9, 9), 0)
thresh2 = cv2.threshold(blur2, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Morph close
# kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# close2 = cv2.morphologyEx(thresh2, cv2.MORPH_CLOSE, kernel2, iterations=10)

# Find contours and filter for QR code
cnts2 = cv2.findContours(thresh2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts2 = cnts2[0] if len(cnts2) == 2 else cnts2[1]
c = sorted(cnts2, key=cv2.contourArea, reverse=True)[0]

draw = cv2.cvtColor(thresh2, cv2.COLOR_GRAY2BGR)
cv2.drawContours(draw, [c], 0, (0, 255, 0), 2)

rotrect = cv2.minAreaRect(c)
box = cv2.boxPoints(rotrect)
box = numpy.int0(box)
cv2.drawContours(draw, [box], 0, (0, 0, 255), 2)

cv2.imshow('thresh', thresh2)
cv2.imshow('ROI', ROI2)
cv2.imshow('minarearect', draw)

thresh ROI minAreaRect output

Upvotes: 5

Views: 4110

Answers (2)

Christoph Rackwitz
Christoph Rackwitz

Reputation: 15364

Detect the code using QRCodeDetector::detectAndDecode and redraw it from the straight_qrcode value. The QRCodeDetector might not be able to decode all codes that you can locate using simple thresholding and contours. Especially when pieces of it are missing (including the quiet zone), the QR code detector might have trouble.

This will always show the code in its canonical orientation, with the finder patterns to the NW, NE, and SW directions.

Simple minAreaRect will only align the code's edges to the image axes, but it would not be able to tell which way is "up" in the QR code.

import cv2 as cv

im = cv.imread("OnDlO.png")

det = cv.QRCodeDetector()
(rv, points, straight_qrcode) = det.detectAndDecode(im)
# rv == 'testing123456'
# points:
# array([[[304.     ,  36.     ],
#         [415.     , 321.     ],
#         [141.55959, 428.3963 ],
#         [ 32.     , 151.     ]]], dtype=float32)

# some white padding
with_quiet_zone = cv.copyMakeBorder(straight_qrcode, 1, 1, 1, 1, borderType=cv.BORDER_CONSTANT, value=255)

# scale it up for display
larger = cv.resize(with_quiet_zone, dsize=None, fx=16, fy=16, interpolation=cv.INTER_NEAREST)

# and show it
cv.imshow("larger", larger)
cv.waitKey()

input:

enter image description here

output:

enter image description here

Upvotes: 2

nathancy
nathancy

Reputation: 46600

From my understanding, you're trying to deskew an image. To do this, we need to first compute the rotated bounding box angle then perform a linear transformation. The idea is to use cv2.minAreaRect + cv2.warpAffine. According to the documentation, cv2.minAreaRect returns

(center(x, y), (width, height), angle of rotation) = cv2.minAreaRect(...)

The third parameter gives us the angle we need to deskew the image.


Input image -> Output result

Skew angle: -39.99416732788086

Code

import cv2
import numpy as np

# Load image, grayscale, Otsu's threshold
image = cv2.imread('2.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = 255 - gray
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# Compute rotated bounding box
coords = np.column_stack(np.where(thresh > 0))
angle = cv2.minAreaRect(coords)[-1]

if angle < -45:
    angle = -(90 + angle)
else:
    angle = -angle
print("Skew angle: ", angle)

# Rotate image to deskew
(h, w) = image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE)

cv2.imshow('rotated', rotated)
cv2.waitKey()

Note: See Python OpenCV skew correction for another approach using the Projection Profile Method to correct skew.

Upvotes: 6

Related Questions