@@ -540,68 +540,83 @@ def visualize_object_predictions(
540
540
# set text_size for category names
541
541
text_size = text_size or rect_th / 3
542
542
543
- # add masks to image if present
543
+ # add masks or obb polygons to image if present
544
544
for object_prediction in object_prediction_list :
545
545
# deepcopy object_prediction_list so that original is not altered
546
546
object_prediction = object_prediction .deepcopy ()
547
- # visualize masks if present
548
- if object_prediction .mask is not None :
549
- # deepcopy mask so that original is not altered
550
- mask = object_prediction .mask .bool_mask
551
- # set color
552
- if colors is not None :
553
- color = colors (object_prediction .category .id )
554
- # draw mask
555
- rgb_mask = apply_color_mask (mask , color or (0 , 0 , 0 ))
556
- image = cv2 .addWeighted (image , 1 , rgb_mask , 0.6 , 0 )
557
-
558
- # add bboxes to image if present
559
- for object_prediction in object_prediction_list :
560
- # deepcopy object_prediction_list so that original is not altered
561
- object_prediction = object_prediction .deepcopy ()
562
-
563
- bbox = object_prediction .bbox .to_xyxy ()
564
- category_name = object_prediction .category .name
565
- score = object_prediction .score .value
566
-
547
+ # arange label to be displayed
548
+ label = f"{ object_prediction .category .name } "
549
+ if not hide_conf :
550
+ label += f" { object_prediction .score .value :.2f} "
567
551
# set color
568
552
if colors is not None :
569
553
color = colors (object_prediction .category .id )
570
- # set bbox points
571
- point1 , point2 = (int (bbox [0 ]), int (bbox [1 ])), (int (bbox [2 ]), int (bbox [3 ]))
572
- # visualize boxes
573
- cv2 .rectangle (
574
- image ,
575
- point1 ,
576
- point2 ,
577
- color = color or (0 , 0 , 0 ),
578
- thickness = rect_th ,
579
- )
580
-
581
- if not hide_labels :
582
- # arange bounding box text location
583
- label = f"{ category_name } "
584
-
585
- if not hide_conf :
586
- label += f" { score :.2f} "
587
-
588
- box_width , box_height = cv2 .getTextSize (label , 0 , fontScale = text_size , thickness = text_th )[
589
- 0
590
- ] # label width, height
591
- outside = point1 [1 ] - box_height - 3 >= 0 # label fits outside box
592
- point2 = point1 [0 ] + box_width , point1 [1 ] - box_height - 3 if outside else point1 [1 ] + box_height + 3
593
- # add bounding box text
594
- cv2 .rectangle (image , point1 , point2 , color or (0 , 0 , 0 ), - 1 , cv2 .LINE_AA ) # filled
595
- cv2 .putText (
554
+ # visualize masks or obb polygons if present
555
+ has_mask = object_prediction .mask is not None
556
+ is_obb_pred = False
557
+ if has_mask :
558
+ segmentation = object_prediction .mask .segmentation
559
+ if len (segmentation ) == 1 and len (segmentation [0 ]) == 8 :
560
+ is_obb_pred = True
561
+
562
+ if is_obb_pred :
563
+ points = np .array (segmentation ).reshape ((- 1 , 1 , 2 )).astype (np .int32 )
564
+ cv2 .polylines (image , [points ], isClosed = True , color = color or (0 , 0 , 0 ), thickness = rect_th )
565
+
566
+ if not hide_labels :
567
+ lowest_point = points [points [:, :, 1 ].argmax ()][0 ]
568
+ box_width , box_height = cv2 .getTextSize (label , 0 , fontScale = text_size , thickness = text_th )[0 ]
569
+ outside = lowest_point [1 ] - box_height - 3 >= 0
570
+ text_bg_point1 = (lowest_point [0 ], lowest_point [1 ] - box_height - 3 if outside else lowest_point [1 ] + 3 )
571
+ text_bg_point2 = (lowest_point [0 ] + box_width , lowest_point [1 ])
572
+ cv2 .rectangle (image , text_bg_point1 , text_bg_point2 , color or (0 , 0 , 0 ), thickness = - 1 , lineType = cv2 .LINE_AA )
573
+ cv2 .putText (
574
+ image ,
575
+ label ,
576
+ (lowest_point [0 ], lowest_point [1 ] - 2 if outside else lowest_point [1 ] + box_height + 2 ),
577
+ 0 ,
578
+ text_size ,
579
+ (255 , 255 , 255 ),
580
+ thickness = text_th ,
581
+ )
582
+ else :
583
+ # draw mask
584
+ rgb_mask = apply_color_mask (object_prediction .mask .bool_mask , color or (0 , 0 , 0 ))
585
+ image = cv2 .addWeighted (image , 1 , rgb_mask , 0.6 , 0 )
586
+
587
+ # add bboxes to image if is_obb_pred=False
588
+ if not is_obb_pred :
589
+ bbox = object_prediction .bbox .to_xyxy ()
590
+
591
+ # set bbox points
592
+ point1 , point2 = (int (bbox [0 ]), int (bbox [1 ])), (int (bbox [2 ]), int (bbox [3 ]))
593
+ # visualize boxes
594
+ cv2 .rectangle (
596
595
image ,
597
- label ,
598
- (point1 [0 ], point1 [1 ] - 2 if outside else point1 [1 ] + box_height + 2 ),
599
- 0 ,
600
- text_size ,
601
- (255 , 255 , 255 ),
602
- thickness = text_th ,
596
+ point1 ,
597
+ point2 ,
598
+ color = color or (0 , 0 , 0 ),
599
+ thickness = rect_th ,
603
600
)
604
601
602
+ if not hide_labels :
603
+ box_width , box_height = cv2 .getTextSize (label , 0 , fontScale = text_size , thickness = text_th )[
604
+ 0
605
+ ] # label width, height
606
+ outside = point1 [1 ] - box_height - 3 >= 0 # label fits outside box
607
+ point2 = point1 [0 ] + box_width , point1 [1 ] - box_height - 3 if outside else point1 [1 ] + box_height + 3
608
+ # add bounding box text
609
+ cv2 .rectangle (image , point1 , point2 , color or (0 , 0 , 0 ), - 1 , cv2 .LINE_AA ) # filled
610
+ cv2 .putText (
611
+ image ,
612
+ label ,
613
+ (point1 [0 ], point1 [1 ] - 2 if outside else point1 [1 ] + box_height + 2 ),
614
+ 0 ,
615
+ text_size ,
616
+ (255 , 255 , 255 ),
617
+ thickness = text_th ,
618
+ )
619
+
605
620
# export if output_dir is present
606
621
if output_dir is not None :
607
622
# export image with predictions
@@ -614,7 +629,7 @@ def visualize_object_predictions(
614
629
return {"image" : image , "elapsed_time" : elapsed_time }
615
630
616
631
617
- def get_coco_segmentation_from_bool_mask (bool_mask ) :
632
+ def get_coco_segmentation_from_bool_mask (bool_mask : np . ndarray ) -> List [ List [ float ]] :
618
633
"""
619
634
Convert boolean mask to coco segmentation format
620
635
[
@@ -712,12 +727,13 @@ def get_coco_segmentation_from_obb_points(obb_points: np.ndarray) -> List[List[f
712
727
obb_points: np.ndarray
713
728
OBB points tensor from ultralytics.engine.results.OBB
714
729
Shape: (4, 2) containing 4 points with (x,y) coordinates each
730
+
715
731
Returns:
716
732
List[List[float]]: Polygon points in COCO format
717
- [[x1, y1, x2, y2, x3, y3, x4, y4, x1, y1 ], [...], ...]
733
+ [[x1, y1, x2, y2, x3, y3, x4, y4], [...], ...]
718
734
"""
719
735
# Convert from (4,2) to [x1,y1,x2,y2,x3,y3,x4,y4] format
720
- points = obb_points .reshape (- 1 ).tolist ()
736
+ points = obb_points .reshape (- 1 ).tolist () #
721
737
722
738
# Create polygon from points and close it by repeating first point
723
739
polygons = []
0 commit comments