Spaces:
Runtime error
Runtime error
| import cv2 | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| from deskew import determine_skew | |
| import math | |
| from typing import Tuple, Union | |
| def rotate(image: np.ndarray, angle: float, background: Union[int, Tuple[int, int, int]]) -> np.ndarray: | |
| old_width, old_height = image.shape[:2] | |
| angle_radian = math.radians(angle) | |
| width = abs(np.sin(angle_radian) * old_height) + abs(np.cos(angle_radian) * old_width) | |
| height = abs(np.sin(angle_radian) * old_width) + abs(np.cos(angle_radian) * old_height) | |
| image_center = tuple(np.array(image.shape[1::-1]) / 2) | |
| rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0) | |
| rot_mat[1, 2] += (width - old_width) / 2 | |
| rot_mat[0, 2] += (height - old_height) / 2 | |
| return cv2.warpAffine(image, rot_mat, (int(round(height)), int(round(width))), borderValue=background) | |
| def check(my_list): | |
| unique_elements = [] | |
| # Sử dụng vòng lặp để kiểm tra từng phần tử trong danh sách | |
| for item in my_list: | |
| # Nếu phần tử không xuất hiện trong danh sách các phần tử duy nhất, thêm nó vào danh sách đó | |
| if item not in unique_elements: | |
| unique_elements.append(item) | |
| return len(unique_elements) | |
| def order_points(pts): | |
| rect = np.zeros((4, 2), dtype="float32") | |
| pts = np.array(pts) | |
| s = pts.sum(axis=1) | |
| rect[0] = pts[np.argmin(s)] | |
| rect[2] = pts[np.argmax(s)] | |
| diff = np.diff(pts, axis=1) | |
| rect[1] = pts[np.argmin(diff)] | |
| rect[3] = pts[np.argmax(diff)] | |
| return rect.astype("int").tolist() | |
| def find_dest(pts): | |
| (tl, tr, br, bl) = pts | |
| 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)) | |
| maxWidth = max(int(widthA), int(widthB)) | |
| 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)) | |
| maxHeight = max(int(heightA), int(heightB)) | |
| destination_corners = [[0, 0], [maxWidth, 0], [maxWidth, maxHeight], [0, maxHeight]] | |
| return order_points(destination_corners) | |
| def extract(ori_img, img, image_size=384, BUFFER=100): | |
| img=img.astype(np.uint8) | |
| gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) | |
| angle = determine_skew(gray_image) | |
| img = rotate(img, angle, (0, 0, 0)) | |
| ori_img = rotate(ori_img, angle, (0, 0, 0)) | |
| #get size of image | |
| size = img.shape | |
| top_pad = 10 # Số pixel padding ở phía trên | |
| bottom_pad = 10 # Số pixel padding ở phía dưới | |
| left_pad = 10 # Số pixel padding ở phía trái | |
| right_pad = 10 # Số pixel padding ở phía phải | |
| # Tạo hình ảnh mới với kích thước lớn hơn, bằng cách thêm pixel màu đen (0) vào xung quanh | |
| height, width, channels = img.shape | |
| new_height = height + top_pad + bottom_pad | |
| new_width = width + left_pad + right_pad | |
| # Tạo một hình ảnh mới với màu đen (0) là màu nền | |
| padded_img = np.zeros((new_height, new_width, channels), dtype=np.uint8) | |
| # Copy nội dung của hình ảnh gốc vào vị trí tương ứng trong hình ảnh mới | |
| padded_img[top_pad:top_pad + height, left_pad:left_pad + width] = img | |
| img = padded_img | |
| height, width, channels = ori_img.shape | |
| new_height = height + top_pad + bottom_pad | |
| new_width = width + left_pad + right_pad | |
| # Tạo một hình ảnh mới với màu đen (0) là màu nền | |
| padded_ori_img = np.full((new_height, new_width, channels), 255, dtype=np.uint8) | |
| # Copy nội dung của hình ảnh gốc vào vị trí tương ứng trong hình ảnh mới | |
| padded_ori_img[top_pad:top_pad + height, left_pad:left_pad + width] = ori_img | |
| ori_img = padded_ori_img | |
| imH, imW, C = img.shape | |
| IMAGE_SIZE = image_size | |
| img_rs = cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE), interpolation=cv2.INTER_NEAREST) | |
| # imH, imW, C = img.shape | |
| # IMAGE_SIZE=image_size | |
| scale_x = imW / IMAGE_SIZE | |
| scale_y = imH / IMAGE_SIZE | |
| # img=cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE), interpolation=cv2.INTER_NEAREST) | |
| canny = cv2.Canny(img_rs.astype(np.uint8), 225, 255) | |
| canny = cv2.dilate(canny, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))) | |
| contours, _ = cv2.findContours(canny, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) | |
| page = sorted(contours, key=cv2.contourArea, reverse=True)[0] | |
| epsilon = (0.02* cv2.arcLength(page, True)) | |
| corners = cv2.approxPolyDP(page, epsilon, True) | |
| corners = np.concatenate(corners).astype(np.float32) | |
| corners[:, 0] *= scale_x | |
| corners[:, 1] *= scale_y | |
| # corners[:, 0] -= half | |
| # corners[:, 1] -= half | |
| for corner in corners: | |
| x, y = corner.astype(int) | |
| cv2.circle(img, (int(x), int(y)), 20, (0, 255, 0), -1) # Vẽ một hình tròn màu xanh lên ảnh | |
| if len(corners) > 4: | |
| left_pad, top_pad, right_pad, bottom_pad = 0, 0, 0, 0 | |
| rect = cv2.minAreaRect(corners.reshape((-1, 1, 2))) | |
| box = cv2.boxPoints(rect) | |
| box_corners = np.int32(box) | |
| # box_corners = minimum_bounding_rectangle(corners) | |
| box_x_min = np.min(box_corners[:, 0]) | |
| box_x_max = np.max(box_corners[:, 0]) | |
| box_y_min = np.min(box_corners[:, 1]) | |
| box_y_max = np.max(box_corners[:, 1]) | |
| # Find corner point which doesn't satify the image constraint | |
| # and record the amount of shift required to make the box | |
| # corner satisfy the constraint | |
| if box_x_min <= 0: | |
| left_pad = abs(box_x_min) + BUFFER | |
| if box_x_max >= imW: | |
| right_pad = (box_x_max - imW) + BUFFER | |
| if box_y_min <= 0: | |
| top_pad = abs(box_y_min) + BUFFER | |
| if box_y_max >= imH: | |
| bottom_pad = (box_y_max - imH) + BUFFER | |
| box_corners[:, 0] += left_pad | |
| box_corners[:, 1] += top_pad | |
| corners = box_corners | |
| if check(order_points(corners)) >= 4: | |
| corners = order_points(corners) | |
| else: | |
| pass | |
| # Define the amount to increase the rectangle size | |
| # (tl, tr, br, bl) = corners | |
| # 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)) | |
| # maxWidth = max(int(widthA), int(widthB)) | |
| # 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)) | |
| # maxHeight = max(int(heightA), int(heightB)) | |
| # # Increase the x-coordinate of the top-right and bottom-right points | |
| # corners[1][0] += maxWidth/30 | |
| # corners[2][0] += maxWidth/30 | |
| # # Decrease the x-coordinate of the top-left and bottom-left points | |
| # corners[0][0] -= maxWidth/30 | |
| # corners[3][0] -= maxWidth/30 | |
| # # Increase the y-coordinate of the bottom-right and bottom-left points | |
| # corners[2][1] += maxHeight/30 | |
| # corners[3][1] += maxHeight/30 | |
| # # Decrease the y-coordinate of the top-left and top-right points | |
| # corners[0][1] -= maxHeight/30 | |
| # corners[1][1] -= maxHeight/30 | |
| # print(corners) | |
| destination_corners = find_dest(corners) | |
| M = cv2.getPerspectiveTransform(np.float32(corners), np.float32(destination_corners)) | |
| final = cv2.warpPerspective(ori_img, M, (destination_corners[2][0], destination_corners[2][1]), | |
| flags=cv2.INTER_LANCZOS4) | |
| return final | |
| # ori=cv2.imread("runs\segment\predict\image0.jpg") | |
| # img=cv2.imread("mask/2.png") | |
| # final=extract(ori,img) | |
| # plt.imshow(final) | |
| # plt.show() | |
| # # print(img.shape) |