image = cv.imread('id_card.png')
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
_, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY + cv.THRESH_OTSU)
contours, _ = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
biggest_rect = None
for contour in contours:
epsilon = 0.02 * cv.arcLength(contour, True)
approx = cv.approxPolyDP(contour, epsilon, True)
if len(approx) == 4:
if biggest_rect is None or cv.contourArea(approx) > cv.contourArea(biggest_rect):
biggest_rect = approx
def order_points(points):
points = points.reshape(4, 2).astype(np.float32)
sums = points.sum(axis=1)
diffs = np.diff(points, axis=1).ravel()
return np.float32([
points[np.argmin(sums)],
points[np.argmin(diffs)],
points[np.argmax(sums)],
points[np.argmax(diffs)],
])
pts1 = order_points(biggest_rect)
pts2 = np.float32([[0, 0], [400, 0], [400, 200], [0, 200]])
matrix = cv.getPerspectiveTransform(pts1, pts2)
result = cv.warpPerspective(image, matrix, (400, 200))