1
+ import os
2
+ import numpy as np
3
+ import cv2
4
+ import pickle as pkl
5
+ import random
6
+ from utils import *
7
+
8
+ classes = ["aeroplane" , "bicycle" , "bird" , "boat" , "bottle" , "bus" , "car" , "cat" ,
9
+ "chair" , "cow" , "diningtable" , "dog" , "horse" , "motorbike" , "person" , "pottedplant" , "sheep" , "sofa" , "train" , "tvmonitor" ]
10
+
11
+
12
+ def draw_single (img_name , label_dir = './' , out_dir = './' , show_flag = False ):
13
+ """
14
+ Draw bounding boxes of a SINGLE image.
15
+
16
+ Note: Labels share the same name as images, using YOLO format.
17
+ e.g. Image = 000001.jpg
18
+ Label = 000001.txt
19
+ format = <class> <x> <y> <w> <h>
20
+ 11 0.344192634561 0.611 0.416430594901 0.262
21
+ 14 0.509915014164 0.51 0.974504249292 0.972
22
+
23
+
24
+ :param img_name: single image name / path + name
25
+ :param label_dir: the corresponding label directory
26
+ :param out_dir: declare output directory, which will be created if not exist.
27
+ :param show_flag: display if True.
28
+ :return:
29
+ """
30
+ # Read image
31
+ file_name = img_name .split ('/' )[- 1 ].split ('.' )[0 ]
32
+
33
+ img = cv2 .imread (img_name )
34
+ height , width = img .shape [:2 ]
35
+
36
+ # Read label
37
+ labels = read_labels (os .path .join (label_dir , file_name + '.txt' ))
38
+
39
+ # Color
40
+ colors = pkl .load (open ('pallete' , 'rb' ))
41
+ font = cv2 .FONT_HERSHEY_SIMPLEX
42
+ m = 10
43
+
44
+ # Draw box + class
45
+ for l in labels :
46
+ cls = classes [int (l [0 ])]
47
+ upper_left_x = int ((l [1 ] - l [3 ] / 2 ) * width )
48
+ upper_left_y = int ((l [2 ] - l [4 ] / 2 ) * height )
49
+ bottom_right_x = int ((l [1 ] + l [3 ] / 2 ) * width )
50
+ bottom_right_y = int ((l [2 ] + l [4 ] / 2 ) * height )
51
+
52
+ color = random .choice (colors )
53
+ cv2 .rectangle (img , (upper_left_x , upper_left_y ), (bottom_right_x , bottom_right_y ), color , 3 )
54
+
55
+ if len (l ) > 5 :
56
+ # has confidence score
57
+ cv2 .putText (img , cls + ' ' + str (l [5 ]), (upper_left_x - m , upper_left_y - m ), font , 0.8 , color , 2 )
58
+ else :
59
+ # no confidence score
60
+ cv2 .putText (img , cls , (upper_left_x - m , upper_left_y - m ), font , 0.8 , color , 2 )
61
+
62
+ cv2 .imwrite (os .path .join (out_dir , 'det_' + file_name + '.png' ), img )
63
+
64
+ if show_flag :
65
+ cv2 .imshow (file_name , img )
66
+ cv2 .waitKey (0 )
67
+ cv2 .destroyAllWindows ()
68
+
69
+
70
+ def draw (img_dir , label_dir , out_dir , show_flag = False ):
71
+ """
72
+ Draw bounding boxes of MULTIPLE images.
73
+
74
+ Note: Labels share the same name as images, using YOLO format.
75
+ e.g. Image = 000001.jpg
76
+ Label = 000001.txt
77
+ format = <class> <x> <y> <w> <h>
78
+ 11 0.344192634561 0.611 0.416430594901 0.262
79
+ 14 0.509915014164 0.51 0.974504249292 0.972
80
+
81
+ :param img_dir: directory of images OR
82
+ list of image names
83
+ :param label_dir: directory of labels
84
+ :param out_dir: declare output directory, which will be created if not exist.
85
+ :param show_flag: display if True.
86
+ :return:
87
+ """
88
+ if not os .path .exists (out_dir ):
89
+ os .makedirs (out_dir )
90
+ print ('"{}" is created.' .format (out_dir ))
91
+ else :
92
+ print ('"{}" exists.' .format (out_dir ))
93
+
94
+
95
+ # Image sources
96
+ if isinstance (img_dir , list ): # from list of image names
97
+ img_list = img_dir
98
+ else : # from directory of images
99
+ img_list = os .listdir (img_dir )
100
+ img_list = [os .path .join (img_dir , elem ) for elem in img_list ]
101
+
102
+ for img_name in img_list :
103
+ draw_single (img_name , label_dir , out_dir , show_flag ) # core
104
+
105
+
106
+ def visualize (y_out_epoch , img_name_epoch , image_list , out_dir , conf_threshold = 0.1 ):
107
+ """
108
+ Visualize bbox a batch/epoch of images
109
+ :param y_out_epoch: N * S * S * (B * 5+C) Tensor
110
+ :param img_name_epoch: list of image name
111
+ :param image_list: list of path + image_name
112
+ :param out_dir: output to be stored here
113
+ :param conf_threshold: filter out bbox with small confidence
114
+ :return:
115
+ """
116
+ assert y_out_epoch .size (0 ) == len (img_name_epoch )
117
+
118
+ # convert to image coordinate [0,1]
119
+ # #### Do ONLY once !!!
120
+ Tensors = [convert_coord_cell2img (y_out_epoch [i ]) for i in range (y_out_epoch .size (0 ))]
121
+
122
+ # loop over each image
123
+ for k in range (y_out_epoch .size (0 )):
124
+ T = y_out_epoch [k ]
125
+ img_name = img_name_epoch [k ]
126
+ res = [] # results to be write to .txt
127
+
128
+ # loop over each grid cell
129
+ for i in range (S ):
130
+ for j in range (S ):
131
+ _ , cls = torch .max (T [i , j , :][- C :], 0 )
132
+
133
+ best_conf = 0
134
+ for b in range (B ):
135
+ bbox = [cls .item ()]
136
+ bbox = bbox + T [i , j , 5 * b : 5 * b + 5 ].tolist ()
137
+
138
+ if b == 0 :
139
+ best_bbox = bbox
140
+
141
+ # for each grid cell, select the box with highest confidence score
142
+ if T [i , j , 5 * b + 4 ] > best_conf :
143
+ best_bbox = bbox
144
+
145
+ # filter out bbox with small confidence
146
+ if best_bbox [- 1 ] > conf_threshold :
147
+ res .append (best_bbox )
148
+
149
+ # write to file
150
+ with open (os .path .join (out_dir , img_name .split ('.' )[0 ] + '.txt' ), 'w' ) as f :
151
+ for r in res :
152
+ for index in range (len (r )):
153
+ if index == 0 :
154
+ f .write ("%d " % r [index ])
155
+ else :
156
+ f .write ("%.4f " % r [index ])
157
+ f .write ("\n " )
158
+
159
+ # draw box
160
+ draw (image_list , out_dir , out_dir )
161
+
162
+
163
+ if __name__ == "__main__" :
164
+ # # Single
165
+ img_name = '000001.jpg'
166
+ draw_single (img_name , show_flag = True )
167
+
168
+ # # Multiple
169
+ '''
170
+ img_dir = '/Users/erica/Workspace/my-yolo-implementation/data/image'
171
+ label_dir = '/Users/erica/Workspace/my-yolo-implementation/data/label'
172
+ out_dir = '/Users/erica/Workspace/my-yolo-implementation/det'
173
+
174
+ draw(img_dir, label_dir, out_dir)
175
+ '''
176
+
177
+ print ('Done.' )
0 commit comments