Skip to content

Commit 6eeb3b2

Browse files
committed
Feat: 변경 겹친 마킹 탐지 및 인페인팅
1 parent c282680 commit 6eeb3b2

File tree

1 file changed

+57
-51
lines changed

1 file changed

+57
-51
lines changed

app/AIProcessor.py

Lines changed: 57 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -62,49 +62,32 @@ def object_detection(self, img):
6262
logging.info(f'객체 탐지 - {self.indices} 박스에 동그라미 존재')
6363
return bbox
6464

65-
def segment_from_boxes(self, image, bbox, save_path=None):
66-
'''
67-
input_boxes = torch.tensor(bbox, device=self.predictor.device)
68-
transformed_boxes = self.predictor.transform.apply_boxes_torch(input_boxes, image.shape[:2])
69-
masks, _, _ = self.predictor.predict_torch(
70-
point_coords=None,
71-
point_labels=None,
72-
boxes=transformed_boxes,
73-
multimask_output=False,
74-
)
75-
'''
65+
def segment_from_yolo(self, image, bbox, save_path=None):
7666
results = self.sam_model.predict(source=image, bboxes=bbox)
7767
mask_boxes = results[0].masks.data
7868

7969
masks_np = np.zeros(mask_boxes.shape[-2:], dtype=np.uint8)
8070
for i, mask in enumerate(mask_boxes):
8171
mask_np = mask.cpu().numpy().astype(np.uint8) * 255 # True는 255, False는 0으로 변환
8272
mask_np = mask_np.squeeze()
83-
if i in self.indices:
73+
'''if i in self.indices: # 원형 마킹이라면
74+
mask_np = cv2.dilate(mask_np, np.ones((3, 3), np.uint8), iterations=1)
8475
# kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15, 15)) # Adjust size as needed
85-
kernel = np.ones((15, 15), np.uint8)
86-
mask_np = cv2.morphologyEx(mask_np, cv2.MORPH_GRADIENT, kernel)
76+
# kernel = np.ones((15, 15), np.uint8)
77+
# mask_np = cv2.morphologyEx(mask_np, cv2.MORPH_GRADIENT, kernel)'''
8778
masks_np = cv2.bitwise_or(masks_np, mask_np)
8879
# cv2.imwrite(f'mask_box{i}.jpg', masks_np)
8980

9081
# cv2.imwrite(save_path, masks_np)
9182
logging.info(f'1차 마스킹 - 바운딩 박스 {len(mask_boxes)}개 세그먼트 완료.')
9283
return masks_np
9384

94-
def segment_from_points(self, image, user_points, user_labels, bbox, save_path=None):
95-
'''input_point = np.array(user_points)
96-
input_label = np.array(user_labels)
97-
98-
masks_points, scores, logits = self.predictor.predict(
99-
point_coords=input_point,
100-
point_labels=input_label,
101-
multimask_output=False,
102-
)'''
85+
def segment_from_user(self, image, user_inputs, bbox, save_path=None):
10386
# filtered_points, filtered_labels = self.remove_points_in_bboxes(user_points, user_labels, bbox)
10487
# logging.info(f'2차 마스킹 - 사용자 입력 필터링: from {len(user_points)}개 to {len(filtered_points)}개')
10588

10689
# results = self.sam_model.predict(source=image, points=filtered_points, labels=filtered_labels)
107-
results = self.sam_model.predict(source=image, bboxes=[user_points])
90+
results = self.sam_model.predict(source=image, bboxes=user_inputs)
10891
mask_points = results[0].masks.data
10992

11093
masks_np = np.zeros(mask_points.shape[-2:], dtype=np.uint8)
@@ -117,22 +100,38 @@ def segment_from_points(self, image, user_points, user_labels, bbox, save_path=
117100
logging.info(f'2차 마스킹 - 사용자 입력에 대해 {len(mask_points)}개 영역으로 세그먼트 완료.')
118101
return masks_np
119102

120-
def inpainting(self, image, mask_total):
121-
inpainted_image = cv2.inpaint(image.copy(), mask_total, 15, cv2.INPAINT_TELEA)
103+
def inpainting(self, image, mask_total, bbox=None):
104+
105+
mask_total = np.zeros(image.shape[:2], dtype=np.uint8)
106+
text_np = np.zeros(image.shape[:2], dtype=np.uint8) # 전체 roi_mask 저장
107+
for b in bbox:
108+
minx, miny, maxx, maxy = map(int, b)
109+
mask_total[miny:maxy, minx:maxx] = 255 # 박스 영역을 255로 채움
110+
roi = image[miny:maxy, minx:maxx] # 해당 이미지만 크롭
111+
roi_mask = cv2.inRange(roi, (0, 0, 0), (45, 45, 45)) # roi 내에서 인쇄된 글씨는 255값
112+
text_np[miny:maxy, minx:maxx] = roi_mask
113+
114+
text_np = cv2.dilate(text_np, np.ones((4, 4), np.uint8), iterations=1)
115+
text_np = cv2.erode(text_np, np.ones((2, 2), np.uint8), iterations=2)
116+
cv2.imwrite('text_np.jpg', text_np.astype(np.uint8))
117+
118+
inpainted_image = image.copy()
119+
inpainted_image[mask_total == 255] = [255, 255, 255]
120+
inpainted_image[text_np == 255] = [30, 30, 30]
121+
final_image = cv2.convertScaleAbs(inpainted_image, alpha=1.5, beta=15)
122+
122123

123-
'''inpainted_image = image.copy()
124-
inpainted_image[mask_total == 255] = [255, 255, 255]'''
125-
final_image = cv2.convertScaleAbs(inpainted_image, alpha=1.6, beta=10)
124+
# inpainted_image = cv2.inpaint(image.copy(), mask_total, 15, cv2.INPAINT_TELEA)
126125
# cv2.imwrite('test_images/inpainted_init.png', inpainted_image)
127126
# cv2.imwrite('test_images/inpainted_final.png', final_image)
128-
logging.info('인페인팅 및 후보정 완료.')
127+
logging.info('Yolo 결과 인페인팅 및 후보정 완료.')
129128

130129
return final_image
131130

132-
def inpaint_from_points(self, image, user_boxes, save_path=None):
131+
def inpaint_from_user(self, image, user_boxes, save_path=None):
133132
masks_np = np.zeros(image.shape[:2], dtype=np.uint8)
134133
for b in user_boxes: # 박스 내부 다 채우기(마스킹)
135-
minx, miny, maxx, maxy = b
134+
minx, miny, maxx, maxy = map(int, b)
136135
masks_np[miny:maxy, minx:maxx] = 255 # 박스 영역을 255로 채움
137136

138137
# cv2.imwrite(save_path, mask_points_uint8)
@@ -167,45 +166,52 @@ def process(self, img_bytes, user_inputs, extension='jpg'):
167166
#self.predictor.set_image(image)
168167
masks_total = np.zeros(image.shape[:2], dtype=np.uint8)
169168

170-
### 1차: Object Detection & Segment by Box
169+
### 1차: Segment by Object Detection
171170
bbox = self.object_detection(image)
172171
if len(bbox) > 0:
173-
logging.info("***** 객체 탐지 세그멘테이션 시작 ******")
174-
masks_by_yolo = self.segment_from_boxes(image, bbox, save_path=None) # 'test_images/seg_box.png'
172+
logging.info("***** 1차: 객체 탐지 세그멘테이션 시작 ******")
173+
masks_by_yolo = self.segment_from_yolo(image, bbox, save_path=None) # 'test_images/seg_box.png'
175174
masks_total = cv2.bitwise_or(masks_total, masks_by_yolo)
176-
#logging.info( f"1차 마스킹 후 shape 점검: YOLOv11 감지된 영역 shape: {masks_by_box.shape}, 이미지 영역 shape: {image.shape}") # (1893, 1577, 3) (1893, 1577)
177175
else:
178-
logging.info("***** 객체 탐지 세그멘테이션 스킵 ******")
176+
logging.info("***** 1차: 객체 탐지 세그멘테이션 스킵 ******")
179177
masks_by_yolo = None
180-
### 2차: points arguments by User & Segment by Points
178+
179+
180+
### 2차: Segment by User Prompt
181181
if len(user_inputs) > 0:
182-
logging.info("***** 사용자 입력 세그멘테이션 시작 ******")
183-
# masks_by_user = self.segment_from_points(image, user_inputs, user_labels, bbox, save_path=None) # save_path='test_images/seg_points.png'
184-
# masks_total = cv2.bitwise_or(masks_total, masks_by_user)
185-
masks_by_user, image_output = self.inpaint_from_points(image, user_inputs, save_path=None)
182+
logging.info("***** 2차: 사용자 입력 세그멘테이션 시작 ******")
183+
masks_by_user = self.segment_from_user(image, user_inputs, bbox, save_path=None) # save_path='test_images/seg_points.png'
184+
masks_total = cv2.bitwise_or(masks_total, masks_by_user)
185+
masks_by_user, image_output = self.inpaint_from_user(image, user_inputs, save_path=None)
186186
_, mask_bytes = cv2.imencode("." + extension, image_output)
187187
else:
188-
logging.info("***** 사용자 입력 세그멘테이션 스킵 ******")
188+
logging.info("***** 2차: 사용자 입력 세그멘테이션 스킵 ******")
189189
masks_by_user = None
190190
mask_bytes = None
191-
# cv2.imwrite('test_images/mask_total.png', masks_total)
192-
if isinstance(masks_total, np.ndarray):
193-
image_output = self.inpainting(image_output, masks_total)
191+
192+
if isinstance(masks_total, np.ndarray) and len(bbox) > 0:
193+
image_output = self.inpainting(image_output, masks_total, bbox)
194194
logging.info('***** 인페인팅 수행 완료 ******')
195-
else:
196-
logging.info('입력과 동일한 결과 이미지입니다.')
197195

198196
_, input_bytes = cv2.imencode("." + extension, image)
199-
# _, mask_bytes = cv2.imencode("." + extension, masks_total.astype(np.uint8))
200197
_, result_bytes = cv2.imencode("." + extension, image_output)
201198

202199
if masks_by_yolo is not None:
203-
_, mask_by_yolo_bytes = cv2.imencode("." + extension, masks_by_yolo.astype(np.uint8))
200+
mask_by_yolo_img = image.copy()
201+
mask_by_yolo_img[masks_by_yolo == 255] = [0, 0, 0]
202+
_, mask_by_yolo_bytes = cv2.imencode("." + extension, mask_by_yolo_img)
204203
else:
205204
mask_by_yolo_bytes = None
206205
if masks_by_user is not None:
207-
_, mask_by_user_bytes = cv2.imencode("." + extension, masks_by_user.astype(np.uint8))
206+
mask_by_user_img = image.copy()
207+
mask_by_user_img[masks_by_user == 255] = [0, 0, 0]
208+
_, mask_by_user_bytes = cv2.imencode("." + extension, mask_by_user_img)
208209
else:
209210
mask_by_user_bytes = None
211+
212+
mask_total_img = image.copy()
213+
mask_total_img[masks_total == 255] = [0, 0, 0]
214+
_, mask_bytes = cv2.imencode("." + extension, mask_total_img)
215+
210216
return (io.BytesIO(input_bytes), io.BytesIO(mask_bytes), io.BytesIO(result_bytes),
211217
io.BytesIO(mask_by_yolo_bytes), io.BytesIO(mask_by_user_bytes))

0 commit comments

Comments
 (0)