@@ -72,7 +72,38 @@ def base64_2_mask(s):
72
72
return mask
73
73
74
74
75
- def load_mask (path , image , mask_name = 'module_unet' ):
75
+ def has_mask (mask_name , path = None , data = None ):
76
+ """Check if mask exists
77
+ Parameters
78
+ ----------
79
+ mask_name: str
80
+ The annotation name of the mask.
81
+
82
+ path: str or pathlib.PosixPath
83
+ The path of annotation json file
84
+
85
+ data: dict
86
+ If provided, will not open path
87
+
88
+ Returns
89
+ -------
90
+ If exist, return the index in objects list
91
+ If not, return False
92
+ """
93
+ if path is None and data is None :
94
+ raise ValueError ("Mask file not provided." )
95
+ if path :
96
+ with open (path , 'r' ) as file :
97
+ data = json .load (file )
98
+
99
+ for inx , obj in enumerate (data ["objects" ]):
100
+ if obj ['classTitle' ] == mask_name :
101
+ return inx
102
+
103
+ return False
104
+
105
+
106
+ def load_mask (path , image , mask_name = 'module_unet' , center = True ):
76
107
"""Load the image of mask
77
108
78
109
Parameters
@@ -86,6 +117,9 @@ def load_mask(path, image, mask_name='module_unet'):
86
117
mask_name: str
87
118
The annotation name of the mask. Default is 'module_unet'.
88
119
120
+ center: bool
121
+ If True, return mask center.
122
+
89
123
Returns
90
124
-------
91
125
mask: array
@@ -96,14 +130,27 @@ def load_mask(path, image, mask_name='module_unet'):
96
130
"""
97
131
with open (path , 'r' ) as file :
98
132
data = json .load (file )
99
- if len (data ["objects" ]) == 1 :
100
- code = data ["objects" ][0 ]["bitmap" ]["data" ]
101
- origin = data ["objects" ][0 ]["bitmap" ]["origin" ]
133
+ # if len(data["objects"]) == 0:
134
+ # return None
135
+ # code = data["objects"][0]["bitmap"]["data"]
136
+ # origin = data["objects"][0]["bitmap"]["origin"]
137
+ # else:
138
+ # flag = True
139
+ # for obj in data["objects"]:
140
+ # if obj['classTitle'] == mask_name:
141
+ inx = has_mask (mask_name , data = data )
142
+ if inx is not False :
143
+ obj = data ["objects" ][inx ]
144
+ code = obj ["bitmap" ]["data" ]
145
+ origin = obj ["bitmap" ]["origin" ]
102
146
else :
103
- for obj in data ["objects" ]:
104
- if obj ['classTitle' ] == mask_name :
105
- code = obj ["bitmap" ]["data" ]
106
- origin = obj ["bitmap" ]["origin" ]
147
+ mask = np .zeros ((image .shape [0 ], image .shape [1 ]))
148
+ mask = mask .astype ('uint8' )
149
+ mask_center = np .array ([mask .shape [1 ]/ 2 , mask .shape [0 ]/ 2 ])
150
+ if center :
151
+ return mask , mask_center
152
+ else :
153
+ return mask
107
154
mask = base64_2_mask (code )
108
155
mask_center = np .array ([mask .shape [1 ]/ 2 , mask .shape [0 ]/ 2 ])
109
156
mask_center += origin
@@ -117,7 +164,10 @@ def load_mask(path, image, mask_name='module_unet'):
117
164
right = np .zeros ((mask4 .shape [0 ], image .shape [1 ] - mask4 .shape [1 ]))
118
165
mask5 = np .hstack ((mask4 , right ))
119
166
120
- return mask5 .astype ('uint8' ), mask_center .astype (int )
167
+ if center :
168
+ return mask5 .astype ('uint8' ), mask_center .astype (int )
169
+ else :
170
+ return mask5 .astype ('uint8' )
121
171
122
172
123
173
def find_intersection (mask_part , houghlinePara = 50 ):
@@ -281,7 +331,7 @@ def find_module_corner(mask, mask_center, dist=200, displace=0, method=0, corner
281
331
return np .array (corners_order )
282
332
283
333
284
- def perspective_transform (image , src , sizex , sizey ):
334
+ def perspective_transform (image , src , sizex , sizey , rotate = True ):
285
335
"""Do perspective transform on the solar modules. Orientation of the input module is auto-detected. The output
286
336
module has short side vertically arranged and long side horizontally arranged.
287
337
@@ -296,16 +346,24 @@ def perspective_transform(image, src, sizex, sizey):
296
346
sizex, sizey: int
297
347
size of the output image. x is the long side and y is the short side.
298
348
349
+ rotate: bool
350
+ If true, auto-detection of orientation is on.
351
+
299
352
Returns
300
353
-------
301
354
warped: array
302
355
Transformed image of solar module
303
356
"""
304
357
src = np .float32 (src )
305
- if np .sum ((src [0 ] - src [2 ])** 2 ) <= np .sum ((src [0 ] - src [1 ])** 2 ):
306
- dst = np .float32 ([(0 , 0 ), (sizex , 0 ), (0 , sizey ), (sizex , sizey )])
307
- else :
358
+
359
+ if rotate and np .sum ((src [0 ] - src [2 ])** 2 ) > np .sum ((src [0 ] - src [1 ])** 2 ):
308
360
dst = np .float32 ([(0 , sizey ), (0 , 0 ), (sizex , sizey ), (sizex , 0 )])
361
+ else :
362
+ dst = np .float32 ([(0 , 0 ), (sizex , 0 ), (0 , sizey ), (sizex , sizey )])
363
+ #if np.sum((src[0] - src[2])**2) <= np.sum((src[0] - src[1])**2):
364
+ # dst = np.float32([(0, 0), (sizex, 0), (0, sizey), (sizex, sizey)])
365
+ #else:
366
+
309
367
M = cv .getPerspectiveTransform (src , dst )
310
368
311
369
warped = cv .warpPerspective (image , M , (sizex , sizey ))
@@ -441,6 +499,7 @@ def find_module_corner2(mask, mode=0):
441
499
mode == 1: detect corners of the approximated convex of module
442
500
mode == 2: detect corners of the approximated contour of the module
443
501
mode == 3: detect corners of the blurred mask of the module
502
+ mode == 4: detect corners using boudingRect
444
503
445
504
Returns
446
505
-------
@@ -457,6 +516,13 @@ def find_module_corner2(mask, mode=0):
457
516
length = len (cnt )
458
517
inx = i
459
518
519
+ if mode == 4 :
520
+ rect = cv .minAreaRect (contours [inx ])
521
+ corners = cv .boxPoints (rect )
522
+ corners_sorted = sort_corners (np .array (corners ))
523
+ corners_displaced = np .array ([[- 1 , - 1 ], [1 , - 1 ], [- 1 , 1 ], [1 , 1 ]]) * 3 + corners_sorted
524
+ return corners_displaced
525
+
460
526
cnt_approx = cv .approxPolyDP (contours [inx ], 8 , True )
461
527
convex = cv .convexHull (contours [inx ])
462
528
conv_approx = cv .approxPolyDP (convex , 8 , True )
@@ -473,7 +539,7 @@ def find_module_corner2(mask, mode=0):
473
539
elif mode == 3 :
474
540
corners = find_polygon_corners (blur )
475
541
else :
476
- print ("mode must be one of 0, 1, 2" )
477
- return
542
+ raise Exception ("mode must be one of 0, 1, 2, 3, 4 " )
543
+
478
544
return corners
479
545
0 commit comments