@@ -62,49 +62,32 @@ def object_detection(self, img):
62
62
logging .info (f'객체 탐지 - { self .indices } 박스에 동그라미 존재' )
63
63
return bbox
64
64
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 ):
76
66
results = self .sam_model .predict (source = image , bboxes = bbox )
77
67
mask_boxes = results [0 ].masks .data
78
68
79
69
masks_np = np .zeros (mask_boxes .shape [- 2 :], dtype = np .uint8 )
80
70
for i , mask in enumerate (mask_boxes ):
81
71
mask_np = mask .cpu ().numpy ().astype (np .uint8 ) * 255 # True는 255, False는 0으로 변환
82
72
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)
84
75
# 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)'''
87
78
masks_np = cv2 .bitwise_or (masks_np , mask_np )
88
79
# cv2.imwrite(f'mask_box{i}.jpg', masks_np)
89
80
90
81
# cv2.imwrite(save_path, masks_np)
91
82
logging .info (f'1차 마스킹 - 바운딩 박스 { len (mask_boxes )} 개 세그먼트 완료.' )
92
83
return masks_np
93
84
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 ):
103
86
# filtered_points, filtered_labels = self.remove_points_in_bboxes(user_points, user_labels, bbox)
104
87
# logging.info(f'2차 마스킹 - 사용자 입력 필터링: from {len(user_points)}개 to {len(filtered_points)}개')
105
88
106
89
# 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 )
108
91
mask_points = results [0 ].masks .data
109
92
110
93
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=
117
100
logging .info (f'2차 마스킹 - 사용자 입력에 대해 { len (mask_points )} 개 영역으로 세그먼트 완료.' )
118
101
return masks_np
119
102
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
+
122
123
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)
126
125
# cv2.imwrite('test_images/inpainted_init.png', inpainted_image)
127
126
# cv2.imwrite('test_images/inpainted_final.png', final_image)
128
- logging .info ('인페인팅 및 후보정 완료.' )
127
+ logging .info ('Yolo 결과 인페인팅 및 후보정 완료.' )
129
128
130
129
return final_image
131
130
132
- def inpaint_from_points (self , image , user_boxes , save_path = None ):
131
+ def inpaint_from_user (self , image , user_boxes , save_path = None ):
133
132
masks_np = np .zeros (image .shape [:2 ], dtype = np .uint8 )
134
133
for b in user_boxes : # 박스 내부 다 채우기(마스킹)
135
- minx , miny , maxx , maxy = b
134
+ minx , miny , maxx , maxy = map ( int , b )
136
135
masks_np [miny :maxy , minx :maxx ] = 255 # 박스 영역을 255로 채움
137
136
138
137
# cv2.imwrite(save_path, mask_points_uint8)
@@ -167,45 +166,52 @@ def process(self, img_bytes, user_inputs, extension='jpg'):
167
166
#self.predictor.set_image(image)
168
167
masks_total = np .zeros (image .shape [:2 ], dtype = np .uint8 )
169
168
170
- ### 1차: Object Detection & Segment by Box
169
+ ### 1차: Segment by Object Detection
171
170
bbox = self .object_detection (image )
172
171
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'
175
174
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)
177
175
else :
178
- logging .info ("***** 객체 탐지 세그멘테이션 스킵 ******" )
176
+ logging .info ("***** 1차: 객체 탐지 세그멘테이션 스킵 ******" )
179
177
masks_by_yolo = None
180
- ### 2차: points arguments by User & Segment by Points
178
+
179
+
180
+ ### 2차: Segment by User Prompt
181
181
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 )
186
186
_ , mask_bytes = cv2 .imencode ("." + extension , image_output )
187
187
else :
188
- logging .info ("***** 사용자 입력 세그멘테이션 스킵 ******" )
188
+ logging .info ("***** 2차: 사용자 입력 세그멘테이션 스킵 ******" )
189
189
masks_by_user = None
190
190
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 )
194
194
logging .info ('***** 인페인팅 수행 완료 ******' )
195
- else :
196
- logging .info ('입력과 동일한 결과 이미지입니다.' )
197
195
198
196
_ , input_bytes = cv2 .imencode ("." + extension , image )
199
- # _, mask_bytes = cv2.imencode("." + extension, masks_total.astype(np.uint8))
200
197
_ , result_bytes = cv2 .imencode ("." + extension , image_output )
201
198
202
199
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 )
204
203
else :
205
204
mask_by_yolo_bytes = None
206
205
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 )
208
209
else :
209
210
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
+
210
216
return (io .BytesIO (input_bytes ), io .BytesIO (mask_bytes ), io .BytesIO (result_bytes ),
211
217
io .BytesIO (mask_by_yolo_bytes ), io .BytesIO (mask_by_user_bytes ))
0 commit comments