1
1
import cv2
2
2
import numpy as np
3
3
import itertools
4
+ #import cvxpy
5
+ #from shapely.geometry import Polygon
4
6
5
7
from models .controllers .translator .BubbleDetect import BubbleDetectEngine
6
8
@@ -27,7 +29,15 @@ def get_bubble_from_file(self,file_name):
27
29
results = []
28
30
for box_stat in box_stats :
29
31
approx , (y0 , y1 , x0 , x1 ) = box_stat
30
- results .append ([x0 ,y0 ,x1 - x0 ,y1 - y0 ])
32
+ #print("==========",flush=True)
33
+ #print(approx[:,0])
34
+ new_x0 ,new_y0 ,new_x1 ,new_y1 = self .get_maximal_rectangle (approx [:,0 ])
35
+ #print([x0,y0,x1-x0,y1-y0])
36
+ #print([new_x0,new_y0,new_x1-new_x0,new_y1-new_y0])
37
+ #print(rectangle)
38
+
39
+ #results.append([x0,y0,x1-x0,y1-y0])
40
+ results .append ([new_x0 ,new_y0 ,new_x1 - new_x0 ,new_y1 - new_y0 ])
31
41
32
42
return results
33
43
@@ -100,12 +110,12 @@ def _bubble_contours(image, box_candidates, iom_threshold=0.5, convexify=False):
100
110
circle_area_ratio = int (3.14 * circle_radius ** 2 / (cnt_area + 1e-6 ))
101
111
rect_area_ratio = int (w * h / cnt_area )
102
112
# This is a speech "bubble" heuristic, it should also work for boxes
103
- # The basic idea is that a bubbles area should approximate that of an enclosing circle
113
+ # The basic idea is that a bubble area should approximate that of an enclosing circle
104
114
if ((circle_area_ratio <= 2 ) & (cnt_area > 4000 )) or (rect_area_ratio == 1 ):
105
115
if convexify :
106
116
approx = cv2 .convexHull (approx )
107
117
box_stats .append ((approx , (y , y + h , x , x + w )))
108
- cv2 .fillPoly (draw_mask , [approx ], (255 , 255 , 255 ))
118
+ # cv2.fillPoly(draw_mask, [approx], (255, 255, 255))
109
119
110
120
# Remove overlapping boxes
111
121
coordinates = [pts for _ , pts in box_stats ]
@@ -149,4 +159,171 @@ def _calculate_iom(bb1, bb2):
149
159
iom = intersection_area / float (min (bb1_area , bb2_area ) + 1e-6 )
150
160
bigger_area = max (bb1_area , bb2_area )
151
161
bigger_ix = int (bigger_area == bb2_area )
152
- return iom , bigger_ix
162
+ return iom , bigger_ix
163
+
164
+
165
+
166
+ # @staticmethod
167
+ # def get_maximal_rectangle(coordinates):
168
+ # """
169
+ # Find the largest, inscribed, axis-aligned rectangle.
170
+ # :param coordinates:
171
+ # A list of of [x, y] pairs describing a closed, convex polygon.
172
+ # """
173
+ #
174
+ # coordinates = np.array(coordinates)
175
+ # x_range = np.max(coordinates, axis=0)[0] - np.min(coordinates, axis=0)[0]
176
+ # y_range = np.max(coordinates, axis=0)[1] - np.min(coordinates, axis=0)[1]
177
+ #
178
+ # scale = np.array([x_range, y_range])
179
+ # sc_coordinates = coordinates / scale
180
+ #
181
+ # poly = Polygon(sc_coordinates)
182
+ # inside_pt = (poly.representative_point().x,
183
+ # poly.representative_point().y)
184
+ #
185
+ # A1, A2, B = SimpleBubbleDetectEngine.pts_to_leq(sc_coordinates)
186
+ #
187
+ # bl = cvxpy.Variable(2)
188
+ # tr = cvxpy.Variable(2)
189
+ # br = cvxpy.Variable(2)
190
+ # tl = cvxpy.Variable(2)
191
+ # obj = cvxpy.Maximize(cvxpy.log(tr[0] - bl[0]) + cvxpy.log(tr[1] - bl[1]))
192
+ # constraints = [bl[0] == tl[0],
193
+ # br[0] == tr[0],
194
+ # tl[1] == tr[1],
195
+ # bl[1] == br[1],
196
+ # ]
197
+ #
198
+ # for i in range(len(B)):
199
+ # if inside_pt[0] * A1[i] + inside_pt[1] * A2[i] <= B[i]:
200
+ # constraints.append(bl[0] * A1[i] + bl[1] * A2[i] <= B[i])
201
+ # constraints.append(tr[0] * A1[i] + tr[1] * A2[i] <= B[i])
202
+ # constraints.append(br[0] * A1[i] + br[1] * A2[i] <= B[i])
203
+ # constraints.append(tl[0] * A1[i] + tl[1] * A2[i] <= B[i])
204
+ #
205
+ # else:
206
+ # constraints.append(bl[0] * A1[i] + bl[1] * A2[i] >= B[i])
207
+ # constraints.append(tr[0] * A1[i] + tr[1] * A2[i] >= B[i])
208
+ # constraints.append(br[0] * A1[i] + br[1] * A2[i] >= B[i])
209
+ # constraints.append(tl[0] * A1[i] + tl[1] * A2[i] >= B[i])
210
+ #
211
+ # prob = cvxpy.Problem(obj, constraints)
212
+ # prob.solve(solver=cvxpy.CVXOPT, verbose=False, max_iters=1000, reltol=1e-9)
213
+ #
214
+ # bottom_left = np.array(bl.value).T * scale
215
+ # top_right = np.array(tr.value).T * scale
216
+ #
217
+ # return list(bottom_left[0]), list(top_right[0])
218
+ #
219
+ # @staticmethod
220
+ # def two_pts_to_line(pt1, pt2):
221
+ # """
222
+ # Create a line from two points in form of
223
+ # a1(x) + a2(y) = b
224
+ # """
225
+ # pt1 = [float(p) for p in pt1]
226
+ # pt2 = [float(p) for p in pt2]
227
+ # try:
228
+ # slp = (pt2[1] - pt1[1]) / (pt2[0] - pt1[0])
229
+ # except ZeroDivisionError:
230
+ # slp = 1e5 * (pt2[1] - pt1[1])
231
+ # a1 = -slp
232
+ # a2 = 1.
233
+ # b = -slp * pt1[0] + pt1[1]
234
+ #
235
+ # return a1, a2, b
236
+ #
237
+ # @staticmethod
238
+ # def pts_to_leq(coords):
239
+ # """
240
+ # Converts a set of points to form Ax = b, but since
241
+ # x is of length 2 this is like A1(x1) + A2(x2) = B.
242
+ # returns A1, A2, B
243
+ # """
244
+ #
245
+ # A1 = []
246
+ # A2 = []
247
+ # B = []
248
+ # for i in range(len(coords) - 1):
249
+ # pt1 = coords[i]
250
+ # pt2 = coords[i + 1]
251
+ # a1, a2, b = SimpleBubbleDetectEngine.two_pts_to_line(pt1, pt2)
252
+ # A1.append(a1)
253
+ # A2.append(a2)
254
+ # B.append(b)
255
+ # return A1, A2, B
256
+
257
+ # ref from https://stackoverflow.com/questions/21410449/how-do-i-crop-to-largest-interior-bounding-box-in-opencv/21479072#21479072
258
+ @staticmethod
259
+ def get_maximal_rectangle (contour ):
260
+ rect = []
261
+
262
+ for i in range (len (contour )):
263
+ x1 , y1 = contour [i ]
264
+ for j in range (len (contour )):
265
+ x2 , y2 = contour [j ]
266
+ area = abs (y2 - y1 ) * abs (x2 - x1 )
267
+ rect .append (((x1 , y1 ), (x2 , y2 ), area ))
268
+
269
+ # the first rect of all_rect has the biggest area, so it's the best solution if he fits in the picture
270
+ all_rect = sorted (rect , key = lambda x : x [2 ], reverse = True )
271
+
272
+ # we take the largest rectangle we've got, based on the value of the rectangle area
273
+ # only if the border of the rectangle is not in the black part
274
+
275
+ # if the list is not empty
276
+ if all_rect :
277
+
278
+ best_rect_found = False
279
+ index_rect = 0
280
+ nb_rect = len (all_rect )
281
+
282
+ # we check if the rectangle is a good solution
283
+ while not best_rect_found and index_rect < nb_rect :
284
+
285
+ rect = all_rect [index_rect ]
286
+ (x1 , y1 ) = rect [0 ]
287
+ (x2 , y2 ) = rect [1 ]
288
+
289
+ valid_rect = True
290
+
291
+ # we search a black area in the perimeter of the rectangle (vertical borders)
292
+ x = min (x1 , x2 )
293
+ while x < max (x1 , x2 ) + 1 and valid_rect :
294
+ #if mask[y1, x] == 0 or mask[y2, x] == 0:
295
+ # # if we find a black pixel, that means a part of the rectangle is black
296
+ # # so we don't keep this rectangle
297
+ # valid_rect = False
298
+ x += 1
299
+
300
+ y = min (y1 , y2 )
301
+ while y < max (y1 , y2 ) + 1 and valid_rect :
302
+ #if mask[y, x1] == 0 or mask[y, x2] == 0:
303
+ # valid_rect = False
304
+ y += 1
305
+
306
+ if valid_rect :
307
+ best_rect_found = True
308
+
309
+ index_rect += 1
310
+
311
+ if best_rect_found :
312
+ return min (x1 ,x2 ),min (y1 ,y2 ),max (x1 ,x2 ),max (y1 ,y2 )
313
+ #return x1, y1, x2, y2
314
+
315
+ # cv2.rectangle(gray, (x1, y1), (x2, y2), (255, 0, 0), 1)
316
+ # cv2.imshow("Is that rectangle ok?", gray)
317
+ # cv2.waitKey(0)
318
+ #
319
+ # # Finally, we crop the picture and store it
320
+ # result = input_picture[min(y1, y2):max(y1, y2), min(x1, x2):max(x1, x2)]
321
+ #
322
+ # cv2.imwrite("Lena_cropped.png", result)
323
+ else :
324
+ print ("No rectangle fitting into the area" )
325
+ return 0 , 0 , 0 , 0
326
+
327
+ else :
328
+ print ("No rectangle found" )
329
+ return 0 , 0 , 0 , 0
0 commit comments