@@ -166,6 +166,8 @@ def run_annotate(
166166 scale : float | None = None ,
167167 points : list [tuple [str , Coordinate , str ]] = [],
168168 camera_offset : Coordinate | None = None ,
169+ compenstation_mode : int = cv .detail .EXPOSURE_COMPENSATOR_GAIN ,
170+ blending_mode : int = cv .detail .BLENDER_MULTI_BAND ,
169171 color : tuple [int , int , int ] = (0 , 0 , 0 ),
170172 font : int = cv .FONT_HERSHEY_PLAIN ,
171173 fontscale : float = 1 ,
@@ -195,8 +197,10 @@ def run_annotate(
195197 BarColumn (),
196198 MofNCompleteColumn (),
197199 TimeRemainingColumn (),
198- console = console
200+ console = console ,
201+ transient = True
199202 ) as progress :
203+ warper : cv .PyRotationWarper | None = None
200204 for data in progress .track (
201205 meta ["images" ],
202206 description = "Preprocessing images"
@@ -219,10 +223,13 @@ def run_annotate(
219223 height , width , _ = img .shape
220224 f_w : float = width / 2 / np .tan (fov_w / 2 )
221225 f_h : float = height / 2 / np .tan (fov_h / 2 )
222- if scale is None :
223- scale = (f_w + f_h ) / 2
224226
225- scale = min (scale , _MAX_SCALE )
227+ if warper is None :
228+ if scale is None :
229+ scale = (f_w + f_h ) / 2
230+
231+ scale = min (scale , _MAX_SCALE )
232+ warper = cv .PyRotationWarper ("spherical" , scale )
226233
227234 instrinsics : npt .NDArray [np .float32 ] = np .array (
228235 (
@@ -236,7 +243,6 @@ def run_annotate(
236243 @ rot_x (np .pi / 2 - float (v ))
237244 ).astype ("float32" )
238245
239- warper = cv .PyRotationWarper ("spherical" , scale )
240246 corner , image_warped = warper .warp (
241247 img ,
242248 instrinsics ,
@@ -278,26 +284,37 @@ def run_annotate(
278284 apply_rotation (pos - center , np .linalg .inv (offset_rot ))
279285 )
280286
287+ console .print ("Preprocessed images" )
288+
281289 with Progress (transient = True ) as progress :
282290 progress .add_task (description = "Merging images..." , total = None )
291+ compensator = cv .detail .ExposureCompensator .createDefault (
292+ compenstation_mode
293+ )
294+ if compenstation_mode != cv .detail .EXPOSURE_COMPENSATOR_NO :
295+ compensator .feed (
296+ corners ,
297+ images_warped , # type: ignore[arg-type]
298+ masks_warped # type: ignore[arg-type]
299+ )
283300
284- blender = cv .detail .Blender .createDefault (cv . detail . BLENDER_MULTI_BAND )
301+ blender = cv .detail .Blender .createDefault (blending_mode )
285302 blender .prepare (
286303 corners ,
287304 [(i .shape [1 ], i .shape [0 ]) for i in images_warped ]
288305 )
289- for corner , img , msk in zip ( corners , images_warped , masks_warped ):
290- dilated_mask = cv . dilate ( msk , None ) # type: ignore[call-overload]
291- seam_mask = cv . resize (
292- dilated_mask ,
293- ( msk . shape [ 1 ], msk . shape [ 0 ]),
294- None ,
295- 0 ,
296- 0 ,
297- cv . INTER_LINEAR_EXACT
298- )
299- msk_warped = cv . bitwise_and ( seam_mask , msk )
300- blender .feed (img .astype ("int16" ), msk_warped , corner )
306+ for i , ( corner , img , msk ) in enumerate (
307+ zip ( corners , images_warped , masks_warped )
308+ ):
309+ if compenstation_mode != cv . detail . EXPOSURE_COMPENSATOR_NO :
310+ img = compensator . apply (
311+ i ,
312+ corner ,
313+ img ,
314+ msk
315+ )
316+
317+ blender .feed (img .astype ("int16" ), msk , corner )
301318
302319 result : cvt .MatLike
303320 result , _ = blender .blend (
@@ -395,7 +412,7 @@ def run_annotate(
395412 bottomLeftOrigin = False
396413 )
397414
398- console .print ("Annotated points" )
415+ console .print ("Annotated points" )
399416
400417 with Progress (transient = True ) as progress :
401418 progress .add_task ("Saving final image..." , total = None )
@@ -432,11 +449,27 @@ def run_annotate(
432449}
433450
434451
452+ _COMP_MAP = {
453+ "none" : cv .detail .EXPOSURE_COMPENSATOR_NO ,
454+ "channels" : cv .detail .EXPOSURE_COMPENSATOR_CHANNELS ,
455+ "gain" : cv .detail .EXPOSURE_COMPENSATOR_GAIN
456+ }
457+
458+
459+ _BLEND_MAP = {
460+ "none" : cv .detail .BLENDER_NO ,
461+ "multiband" : cv .detail .BLENDER_MULTI_BAND ,
462+ "feather" : cv .detail .BLENDER_FEATHER
463+ }
464+
465+
435466def main (
436467 metadata : Path ,
437468 output : Path ,
438469 image : tuple [Path ],
439470 camera_offset : tuple [float , float , float ] | None = None ,
471+ compensation : str = "channel" ,
472+ blending : str = "multiband" ,
440473 scale : float | None = None ,
441474 width : int | None = None ,
442475 height : int | None = None ,
@@ -529,6 +562,8 @@ def main(
529562 scale ,
530563 points ,
531564 cam_offset ,
565+ _COMP_MAP [compensation ],
566+ _BLEND_MAP [blending ],
532567 color ,
533568 _FONT_MAP [font ],
534569 fontscale ,
@@ -546,3 +581,4 @@ def main(
546581 )
547582 except cv .error as cve :
548583 echo_red (f"The process failed due to an OpenCV error ({ cve .code } )" )
584+ echo_red (cve .err )
0 commit comments