Spaces:
Runtime error
Runtime error
code
Browse files- Segmentation.py +58 -0
- perpestive_transform.py +188 -0
Segmentation.py
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from ultralytics import YOLO
|
2 |
+
import cv2
|
3 |
+
import os
|
4 |
+
import shutil
|
5 |
+
import numpy as np
|
6 |
+
def black_mask(results):
|
7 |
+
# Đường dẫn đến thư mục "runs"
|
8 |
+
runs_folder = "mask"
|
9 |
+
# Kiểm tra xem thư mục "mask" đã tồn tại chưa
|
10 |
+
if not os.path.exists(runs_folder):
|
11 |
+
# Nếu chưa tồn tại, tạo thư mục "mask"
|
12 |
+
os.makedirs(runs_folder)
|
13 |
+
for mask_index in range(len(results[0].masks)):
|
14 |
+
# Lấy mặt nạ
|
15 |
+
mask_raw = results[0].masks[mask_index].cpu().data.numpy().transpose(1, 2, 0)
|
16 |
+
# Chuyển đổi mặt nạ thành 3 kênh màu
|
17 |
+
mask_3channel = cv2.merge((mask_raw, mask_raw, mask_raw))
|
18 |
+
# Lấy kích thước của ảnh gốc (chiều cao, chiều rộng, số kênh)
|
19 |
+
h2, w2, c2 = results[0].orig_img.shape
|
20 |
+
# Thay đổi kích thước mặt nạ thành cùng kích thước với ảnh gốc
|
21 |
+
mask = cv2.resize(mask_3channel, (w2, h2))
|
22 |
+
# Chuyển đổi ảnh mặt nạ thành không gian màu HSV
|
23 |
+
hsv = cv2.cvtColor(mask, cv2.COLOR_BGR2HSV)
|
24 |
+
# Xác định phạm vi độ sáng trong không gian màu HSV
|
25 |
+
lower_black = np.array([0, 0, 0])
|
26 |
+
upper_black = np.array([0, 0, 1])
|
27 |
+
# Tạo mặt nạ dựa trên phạm vi độ sáng
|
28 |
+
mask = cv2.inRange(mask, lower_black, upper_black)
|
29 |
+
# Đảo ngược mặt nạ để lấy mọi thứ trừ màu đen
|
30 |
+
mask = cv2.bitwise_not(mask)
|
31 |
+
# Áp dụng mặt nạ vào ảnh gốc
|
32 |
+
masked = cv2.bitwise_and(results[0].orig_img, results[0].orig_img, mask=mask)
|
33 |
+
# Chuyển mọi pixel màu đen thành màu trắng
|
34 |
+
black_color = [0, 0, 0]
|
35 |
+
white_color = [255, 255, 255]
|
36 |
+
result_image = np.where(np.all(masked == black_color, axis=-1, keepdims=True), masked, white_color)
|
37 |
+
name = "mask/"+str(mask_index) + '.png'
|
38 |
+
# Show the masked part of the image
|
39 |
+
cv2.imwrite(name,result_image)
|
40 |
+
def segmentation_doc(image):
|
41 |
+
model = YOLO('Model/Seg65ep.pt')
|
42 |
+
runs_folder = "runs"
|
43 |
+
folder="mask"
|
44 |
+
# Xóa thư mục runs
|
45 |
+
if os.path.exists(runs_folder) and os.path.isdir(runs_folder):
|
46 |
+
# Xóa thư mục runs
|
47 |
+
shutil.rmtree(runs_folder)
|
48 |
+
if os.path.exists(folder) and os.path.isdir(folder):
|
49 |
+
# Xóa thư mục runs
|
50 |
+
shutil.rmtree(folder)
|
51 |
+
color = [255, 255, 255] # Màu trắng
|
52 |
+
padding_size = 50
|
53 |
+
image = cv2.copyMakeBorder(image, padding_size, padding_size, padding_size, padding_size, cv2.BORDER_CONSTANT, value=color)
|
54 |
+
results = model(image,save=True,retina_masks = True, conf=0.7)
|
55 |
+
black_mask(results)
|
56 |
+
return image
|
57 |
+
# image=cv2.imread("test1.jpg")
|
58 |
+
# segmentation_doc(image)
|
perpestive_transform.py
ADDED
@@ -0,0 +1,188 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import cv2
|
2 |
+
import numpy as np
|
3 |
+
import matplotlib.pyplot as plt
|
4 |
+
from deskew import determine_skew
|
5 |
+
import math
|
6 |
+
from typing import Tuple, Union
|
7 |
+
def rotate(image: np.ndarray, angle: float, background: Union[int, Tuple[int, int, int]]) -> np.ndarray:
|
8 |
+
old_width, old_height = image.shape[:2]
|
9 |
+
angle_radian = math.radians(angle)
|
10 |
+
width = abs(np.sin(angle_radian) * old_height) + abs(np.cos(angle_radian) * old_width)
|
11 |
+
height = abs(np.sin(angle_radian) * old_width) + abs(np.cos(angle_radian) * old_height)
|
12 |
+
|
13 |
+
image_center = tuple(np.array(image.shape[1::-1]) / 2)
|
14 |
+
rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0)
|
15 |
+
rot_mat[1, 2] += (width - old_width) / 2
|
16 |
+
rot_mat[0, 2] += (height - old_height) / 2
|
17 |
+
|
18 |
+
return cv2.warpAffine(image, rot_mat, (int(round(height)), int(round(width))), borderValue=background)
|
19 |
+
|
20 |
+
|
21 |
+
def check(my_list):
|
22 |
+
unique_elements = []
|
23 |
+
|
24 |
+
# Sử dụng vòng lặp để kiểm tra từng phần tử trong danh sách
|
25 |
+
for item in my_list:
|
26 |
+
# 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 đó
|
27 |
+
if item not in unique_elements:
|
28 |
+
unique_elements.append(item)
|
29 |
+
return len(unique_elements)
|
30 |
+
|
31 |
+
|
32 |
+
def order_points(pts):
|
33 |
+
rect = np.zeros((4, 2), dtype="float32")
|
34 |
+
pts = np.array(pts)
|
35 |
+
s = pts.sum(axis=1)
|
36 |
+
rect[0] = pts[np.argmin(s)]
|
37 |
+
rect[2] = pts[np.argmax(s)]
|
38 |
+
|
39 |
+
diff = np.diff(pts, axis=1)
|
40 |
+
rect[1] = pts[np.argmin(diff)]
|
41 |
+
rect[3] = pts[np.argmax(diff)]
|
42 |
+
return rect.astype("int").tolist()
|
43 |
+
|
44 |
+
|
45 |
+
def find_dest(pts):
|
46 |
+
(tl, tr, br, bl) = pts
|
47 |
+
widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
|
48 |
+
widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
|
49 |
+
maxWidth = max(int(widthA), int(widthB))
|
50 |
+
heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
|
51 |
+
heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
|
52 |
+
maxHeight = max(int(heightA), int(heightB))
|
53 |
+
destination_corners = [[0, 0], [maxWidth, 0], [maxWidth, maxHeight], [0, maxHeight]]
|
54 |
+
return order_points(destination_corners)
|
55 |
+
def extract(ori_img, img, image_size=384, BUFFER=100):
|
56 |
+
img=img.astype(np.uint8)
|
57 |
+
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
58 |
+
angle = determine_skew(gray_image)
|
59 |
+
img = rotate(img, angle, (0, 0, 0))
|
60 |
+
ori_img = rotate(ori_img, angle, (0, 0, 0))
|
61 |
+
#get size of image
|
62 |
+
size = img.shape
|
63 |
+
top_pad = 10 # Số pixel padding ở phía trên
|
64 |
+
bottom_pad = 10 # Số pixel padding ở phía dưới
|
65 |
+
left_pad = 10 # Số pixel padding ở phía trái
|
66 |
+
right_pad = 10 # Số pixel padding ở phía phải
|
67 |
+
|
68 |
+
# 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
|
69 |
+
height, width, channels = img.shape
|
70 |
+
new_height = height + top_pad + bottom_pad
|
71 |
+
new_width = width + left_pad + right_pad
|
72 |
+
|
73 |
+
# Tạo một hình ảnh mới với màu đen (0) là màu nền
|
74 |
+
padded_img = np.zeros((new_height, new_width, channels), dtype=np.uint8)
|
75 |
+
|
76 |
+
# Copy nội dung của hình ảnh gốc vào vị trí tương ứng trong hình ảnh mới
|
77 |
+
padded_img[top_pad:top_pad + height, left_pad:left_pad + width] = img
|
78 |
+
img = padded_img
|
79 |
+
|
80 |
+
height, width, channels = ori_img.shape
|
81 |
+
new_height = height + top_pad + bottom_pad
|
82 |
+
new_width = width + left_pad + right_pad
|
83 |
+
|
84 |
+
# Tạo một hình ảnh mới với màu đen (0) là màu nền
|
85 |
+
padded_ori_img = np.full((new_height, new_width, channels), 255, dtype=np.uint8)
|
86 |
+
|
87 |
+
# Copy nội dung của hình ảnh gốc vào vị trí tương ứng trong hình ảnh mới
|
88 |
+
padded_ori_img[top_pad:top_pad + height, left_pad:left_pad + width] = ori_img
|
89 |
+
ori_img = padded_ori_img
|
90 |
+
|
91 |
+
imH, imW, C = img.shape
|
92 |
+
IMAGE_SIZE = image_size
|
93 |
+
img_rs = cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE), interpolation=cv2.INTER_NEAREST)
|
94 |
+
|
95 |
+
# imH, imW, C = img.shape
|
96 |
+
# IMAGE_SIZE=image_size
|
97 |
+
scale_x = imW / IMAGE_SIZE
|
98 |
+
scale_y = imH / IMAGE_SIZE
|
99 |
+
# img=cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE), interpolation=cv2.INTER_NEAREST)
|
100 |
+
|
101 |
+
canny = cv2.Canny(img_rs.astype(np.uint8), 225, 255)
|
102 |
+
canny = cv2.dilate(canny, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)))
|
103 |
+
contours, _ = cv2.findContours(canny, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE)
|
104 |
+
page = sorted(contours, key=cv2.contourArea, reverse=True)[0]
|
105 |
+
epsilon = (0.02* cv2.arcLength(page, True))
|
106 |
+
corners = cv2.approxPolyDP(page, epsilon, True)
|
107 |
+
corners = np.concatenate(corners).astype(np.float32)
|
108 |
+
corners[:, 0] *= scale_x
|
109 |
+
corners[:, 1] *= scale_y
|
110 |
+
|
111 |
+
# corners[:, 0] -= half
|
112 |
+
# corners[:, 1] -= half
|
113 |
+
for corner in corners:
|
114 |
+
x, y = corner.astype(int)
|
115 |
+
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
|
116 |
+
|
117 |
+
if len(corners) > 4:
|
118 |
+
left_pad, top_pad, right_pad, bottom_pad = 0, 0, 0, 0
|
119 |
+
rect = cv2.minAreaRect(corners.reshape((-1, 1, 2)))
|
120 |
+
box = cv2.boxPoints(rect)
|
121 |
+
box_corners = np.int32(box)
|
122 |
+
# box_corners = minimum_bounding_rectangle(corners)
|
123 |
+
|
124 |
+
box_x_min = np.min(box_corners[:, 0])
|
125 |
+
box_x_max = np.max(box_corners[:, 0])
|
126 |
+
box_y_min = np.min(box_corners[:, 1])
|
127 |
+
box_y_max = np.max(box_corners[:, 1])
|
128 |
+
|
129 |
+
# Find corner point which doesn't satify the image constraint
|
130 |
+
# and record the amount of shift required to make the box
|
131 |
+
# corner satisfy the constraint
|
132 |
+
if box_x_min <= 0:
|
133 |
+
left_pad = abs(box_x_min) + BUFFER
|
134 |
+
|
135 |
+
if box_x_max >= imW:
|
136 |
+
right_pad = (box_x_max - imW) + BUFFER
|
137 |
+
|
138 |
+
if box_y_min <= 0:
|
139 |
+
top_pad = abs(box_y_min) + BUFFER
|
140 |
+
|
141 |
+
if box_y_max >= imH:
|
142 |
+
bottom_pad = (box_y_max - imH) + BUFFER
|
143 |
+
box_corners[:, 0] += left_pad
|
144 |
+
box_corners[:, 1] += top_pad
|
145 |
+
corners = box_corners
|
146 |
+
|
147 |
+
if check(order_points(corners)) >= 4:
|
148 |
+
corners = order_points(corners)
|
149 |
+
else:
|
150 |
+
pass
|
151 |
+
|
152 |
+
# Define the amount to increase the rectangle size
|
153 |
+
# (tl, tr, br, bl) = corners
|
154 |
+
# widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
|
155 |
+
# widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
|
156 |
+
# maxWidth = max(int(widthA), int(widthB))
|
157 |
+
# heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
|
158 |
+
# heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
|
159 |
+
# maxHeight = max(int(heightA), int(heightB))
|
160 |
+
|
161 |
+
# # Increase the x-coordinate of the top-right and bottom-right points
|
162 |
+
# corners[1][0] += maxWidth/30
|
163 |
+
# corners[2][0] += maxWidth/30
|
164 |
+
|
165 |
+
# # Decrease the x-coordinate of the top-left and bottom-left points
|
166 |
+
# corners[0][0] -= maxWidth/30
|
167 |
+
# corners[3][0] -= maxWidth/30
|
168 |
+
# # Increase the y-coordinate of the bottom-right and bottom-left points
|
169 |
+
# corners[2][1] += maxHeight/30
|
170 |
+
# corners[3][1] += maxHeight/30
|
171 |
+
|
172 |
+
# # Decrease the y-coordinate of the top-left and top-right points
|
173 |
+
# corners[0][1] -= maxHeight/30
|
174 |
+
# corners[1][1] -= maxHeight/30
|
175 |
+
|
176 |
+
# print(corners)
|
177 |
+
|
178 |
+
destination_corners = find_dest(corners)
|
179 |
+
M = cv2.getPerspectiveTransform(np.float32(corners), np.float32(destination_corners))
|
180 |
+
final = cv2.warpPerspective(ori_img, M, (destination_corners[2][0], destination_corners[2][1]),
|
181 |
+
flags=cv2.INTER_LANCZOS4)
|
182 |
+
return final
|
183 |
+
# ori=cv2.imread("runs\segment\predict\image0.jpg")
|
184 |
+
# img=cv2.imread("mask/2.png")
|
185 |
+
# final=extract(ori,img)
|
186 |
+
# plt.imshow(final)
|
187 |
+
# plt.show()
|
188 |
+
# # print(img.shape)
|