31
31
#include " opencv2/highgui.hpp"
32
32
#endif
33
33
34
+ static const cv::Scalar black = cv::Scalar (0 , 0 , 0 );
35
+ static const cv::Scalar white = cv::Scalar (255 , 255 , 255 );
36
+
34
37
GST_DEBUG_CATEGORY_STATIC (gst_classification_overlay_debug_category);
35
38
#define GST_CAT_DEFAULT gst_classification_overlay_debug_category
36
39
37
- #define MIN_FONT_SCALE 0
38
- #define DEFAULT_FONT_SCALE 1.5
39
- #define MAX_FONT_SCALE 100
40
- #define MIN_BOX_THICKNESS 1
41
- #define DEFAULT_BOX_THICKNESS 2
42
- #define MAX_BOX_THICKNESS 100
43
- #define DEFAULT_LABELS NULL
44
- #define DEFAULT_NUM_LABELS 0
45
-
46
40
/* prototypes */
47
- static void gst_classification_overlay_set_property (GObject * object,
48
- guint property_id, const GValue * value, GParamSpec * pspec);
49
- static void gst_classification_overlay_get_property (GObject * object,
50
- guint property_id, GValue * value, GParamSpec * pspec);
51
- static void gst_classification_overlay_dispose (GObject * object);
52
- static void gst_classification_overlay_finalize (GObject * object);
53
-
54
- static gboolean gst_classification_overlay_start (GstBaseTransform * trans);
55
- static gboolean gst_classification_overlay_stop (GstBaseTransform * trans);
56
- static GstFlowReturn
57
- gst_classification_overlay_transform_frame_ip (GstVideoFilter * trans,
58
- GstVideoFrame * frame);
41
+ static GstFlowReturn gst_classification_overlay_process_meta (GstVideoFrame *
42
+ frame, GstMeta * meta, gdouble font_scale, gint thickness,
43
+ gchar ** labels_list, gint num_labels);
59
44
60
45
enum
61
46
{
62
- PROP_0,
63
- PROP_FONT_SCALE,
64
- PROP_BOX_THICKNESS,
65
- PROP_LABELS
47
+ PROP_0
66
48
};
67
49
68
- /* pad templates */
69
-
70
- #define VIDEO_SRC_CAPS \
71
- GST_VIDEO_CAPS_MAKE (" { RGB }" )
72
-
73
- #define VIDEO_SINK_CAPS \
74
- GST_VIDEO_CAPS_MAKE (" { RGB }" )
50
+ struct _GstClassificationOverlay
51
+ {
52
+ GstInferenceOverlay parent;
53
+ };
75
54
55
+ struct _GstClassificationOverlayClass
56
+ {
57
+ GstInferenceOverlay parent;
58
+ };
76
59
77
60
/* class initialization */
78
61
79
62
G_DEFINE_TYPE_WITH_CODE (GstClassificationOverlay, gst_classification_overlay,
80
- GST_TYPE_VIDEO_FILTER ,
63
+ GST_TYPE_INFERENCE_OVERLAY ,
81
64
GST_DEBUG_CATEGORY_INIT (gst_classification_overlay_debug_category,
82
- " classification_overlay " , 0 ,
65
+ " classificationoverlay " , 0 ,
83
66
" debug category for classification_overlay element" ));
84
67
85
68
static void
86
69
gst_classification_overlay_class_init (GstClassificationOverlayClass * klass)
87
70
{
88
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
89
- GstBaseTransformClass *base_transform_class =
90
- GST_BASE_TRANSFORM_CLASS (klass);
91
- GstVideoFilterClass *video_filter_class = GST_VIDEO_FILTER_CLASS (klass);
92
-
93
- gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
94
- gst_pad_template_new (" src" , GST_PAD_SRC, GST_PAD_ALWAYS,
95
- gst_caps_from_string (VIDEO_SRC_CAPS)));
96
- gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
97
- gst_pad_template_new (" sink" , GST_PAD_SINK, GST_PAD_ALWAYS,
98
- gst_caps_from_string (VIDEO_SINK_CAPS)));
71
+ GstInferenceOverlayClass *io_class = GST_INFERENCE_OVERLAY_CLASS (klass);
99
72
100
73
gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass),
101
74
" classificationoverlay" , " Filter" ,
@@ -107,194 +80,34 @@ gst_classification_overlay_class_init (GstClassificationOverlayClass * klass)
107
80
" Miguel Taylor <[email protected] > \n\t\t\t "
108
81
" Greivin Fallas <[email protected] >" );
109
82
110
- gobject_class->set_property = gst_classification_overlay_set_property;
111
- gobject_class->get_property = gst_classification_overlay_get_property;
112
- gobject_class->dispose = gst_classification_overlay_dispose;
113
- gobject_class->finalize = gst_classification_overlay_finalize;
114
-
115
- g_object_class_install_property (gobject_class, PROP_FONT_SCALE,
116
- g_param_spec_double (" font-scale" , " font" , " Font scale" , MIN_FONT_SCALE,
117
- MAX_FONT_SCALE, DEFAULT_FONT_SCALE, G_PARAM_READWRITE));
118
-
119
- g_object_class_install_property (gobject_class, PROP_BOX_THICKNESS,
120
- g_param_spec_int (" thickness" , " thickness" ,
121
- " Box line thickness in pixels" , MIN_BOX_THICKNESS, MAX_BOX_THICKNESS,
122
- DEFAULT_BOX_THICKNESS, G_PARAM_READWRITE));
123
-
124
- g_object_class_install_property (gobject_class, PROP_LABELS,
125
- g_param_spec_string (" labels" , " labels" ,
126
- " Semicolon separated string containing inference labels" ,
127
- DEFAULT_LABELS, G_PARAM_READWRITE));
128
-
129
- base_transform_class->start =
130
- GST_DEBUG_FUNCPTR (gst_classification_overlay_start);
131
- base_transform_class->stop =
132
- GST_DEBUG_FUNCPTR (gst_classification_overlay_stop);
133
- video_filter_class->transform_frame_ip =
134
- GST_DEBUG_FUNCPTR (gst_classification_overlay_transform_frame_ip);
135
-
83
+ io_class->process_meta =
84
+ GST_DEBUG_FUNCPTR (gst_classification_overlay_process_meta);
85
+ io_class->meta_type = GST_CLASSIFICATION_META_API_TYPE;
136
86
}
137
87
138
88
static void
139
89
gst_classification_overlay_init (GstClassificationOverlay *
140
90
classification_overlay)
141
91
{
142
- classification_overlay->font_scale = DEFAULT_FONT_SCALE;
143
- classification_overlay->box_thickness = DEFAULT_BOX_THICKNESS;
144
- classification_overlay->labels = DEFAULT_LABELS;
145
- classification_overlay->labels_list = DEFAULT_LABELS;
146
- classification_overlay->num_labels = DEFAULT_NUM_LABELS;
147
- }
148
-
149
- void
150
- gst_classification_overlay_set_property (GObject * object, guint property_id,
151
- const GValue * value, GParamSpec * pspec)
152
- {
153
- GstClassificationOverlay *classification_overlay =
154
- GST_CLASSIFICATION_OVERLAY (object);
155
-
156
- GST_DEBUG_OBJECT (classification_overlay, " set_property" );
157
-
158
- switch (property_id) {
159
- case PROP_FONT_SCALE:
160
- classification_overlay->font_scale = g_value_get_double (value);
161
- GST_DEBUG_OBJECT (classification_overlay, " Changed font scale to %lf" ,
162
- classification_overlay->font_scale );
163
- break ;
164
- case PROP_BOX_THICKNESS:
165
- classification_overlay->box_thickness = g_value_get_int (value);
166
- GST_DEBUG_OBJECT (classification_overlay, " Changed box thickness to %d" ,
167
- classification_overlay->box_thickness );
168
- break ;
169
- case PROP_LABELS:
170
- if (classification_overlay->labels != NULL ) {
171
- g_free (classification_overlay->labels );
172
- }
173
- if (classification_overlay->labels_list != NULL ) {
174
- g_strfreev (classification_overlay->labels_list );
175
- }
176
- classification_overlay->labels = g_value_dup_string (value);
177
- classification_overlay->labels_list =
178
- g_strsplit (g_value_get_string (value), " ;" , 0 );
179
- classification_overlay->num_labels =
180
- g_strv_length (classification_overlay->labels_list );
181
- GST_DEBUG_OBJECT (classification_overlay, " Changed inference labels %s" ,
182
- classification_overlay->labels );
183
- break ;
184
- default :
185
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
186
- break ;
187
- }
188
- }
189
-
190
- void
191
- gst_classification_overlay_get_property (GObject * object, guint property_id,
192
- GValue * value, GParamSpec * pspec)
193
- {
194
- GstClassificationOverlay *classification_overlay =
195
- GST_CLASSIFICATION_OVERLAY (object);
196
-
197
- GST_DEBUG_OBJECT (classification_overlay, " get_property" );
198
-
199
- switch (property_id) {
200
- case PROP_FONT_SCALE:
201
- g_value_set_double (value, classification_overlay->font_scale );
202
- break ;
203
- case PROP_BOX_THICKNESS:
204
- g_value_set_int (value, classification_overlay->box_thickness );
205
- break ;
206
- case PROP_LABELS:
207
- g_value_set_string (value, classification_overlay->labels );
208
- break ;
209
- default :
210
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
211
- break ;
212
- }
213
92
}
214
93
215
- void
216
- gst_classification_overlay_dispose (GObject * object)
217
- {
218
- GstClassificationOverlay *classification_overlay =
219
- GST_CLASSIFICATION_OVERLAY (object);
220
-
221
- GST_DEBUG_OBJECT (classification_overlay, " dispose" );
222
-
223
- /* clean up as possible. may be called multiple times */
224
- if (classification_overlay->labels_list != NULL ) {
225
- g_strfreev (classification_overlay->labels_list );
226
- }
227
- if (classification_overlay->labels != NULL ) {
228
- g_free (classification_overlay->labels );
229
- }
230
-
231
- G_OBJECT_CLASS (gst_classification_overlay_parent_class)->dispose (object);
232
- }
233
-
234
- void
235
- gst_classification_overlay_finalize (GObject * object)
236
- {
237
- GstClassificationOverlay *classification_overlay =
238
- GST_CLASSIFICATION_OVERLAY (object);
239
-
240
- GST_DEBUG_OBJECT (classification_overlay, " finalize" );
241
-
242
- /* clean up object here */
243
-
244
- G_OBJECT_CLASS (gst_classification_overlay_parent_class)->finalize (object);
245
- }
246
-
247
- static gboolean
248
- gst_classification_overlay_start (GstBaseTransform * trans)
249
- {
250
- GstClassificationOverlay *classification_overlay =
251
- GST_CLASSIFICATION_OVERLAY (trans);
252
-
253
- GST_DEBUG_OBJECT (classification_overlay, " start" );
254
-
255
- return TRUE ;
256
- }
257
-
258
- static gboolean
259
- gst_classification_overlay_stop (GstBaseTransform * trans)
260
- {
261
- GstClassificationOverlay *classification_overlay =
262
- GST_CLASSIFICATION_OVERLAY (trans);
263
-
264
- GST_DEBUG_OBJECT (classification_overlay, " stop" );
265
-
266
- return TRUE ;
267
- }
268
-
269
- /* transform */
270
94
static GstFlowReturn
271
- gst_classification_overlay_transform_frame_ip (GstVideoFilter * trans ,
272
- GstVideoFrame * frame )
95
+ gst_classification_overlay_process_meta (GstVideoFrame * frame, GstMeta * meta ,
96
+ gdouble font_scale, gint thickness, gchar ** labels_list, gint num_labels )
273
97
{
274
- GstClassificationOverlay *classification_overlay =
275
- GST_CLASSIFICATION_OVERLAY (trans);
276
98
GstClassificationMeta *class_meta;
277
99
gint index , i, width, height;
278
100
gdouble max, current;
279
101
cv::Mat cv_mat;
280
102
cv::String str;
281
103
cv::Size size;
282
- const gint bpp = 3 ;
283
- cv::Scalar black = cv::Scalar (0 , 0 , 0 );
284
- cv::Scalar white = cv::Scalar (255 , 255 , 255 );
285
104
286
- width = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0 ) / bpp;
105
+ width =
106
+ GST_VIDEO_FRAME_COMP_STRIDE (frame,
107
+ 0 ) / GST_VIDEO_FRAME_N_COMPONENTS (frame);
287
108
height = GST_VIDEO_FRAME_HEIGHT (frame);
288
109
289
- class_meta =
290
- (GstClassificationMeta *) gst_buffer_get_meta (frame->buffer ,
291
- GST_CLASSIFICATION_META_API_TYPE);
292
- if (NULL == class_meta) {
293
- GST_LOG_OBJECT (trans, " No classification meta found" );
294
- return GST_FLOW_OK;
295
- }
296
-
297
- GST_LOG_OBJECT (trans, " Valid classification meta found" );
110
+ class_meta = (GstClassificationMeta *) meta;
298
111
299
112
/* Get the most probable label */
300
113
index = 0 ;
@@ -306,27 +119,22 @@ gst_classification_overlay_transform_frame_ip (GstVideoFilter * trans,
306
119
index = i;
307
120
}
308
121
}
309
- if (classification_overlay->num_labels > index ) {
310
- str = cv::format (" %s prob:%f" , classification_overlay->labels_list [index ],
311
- max);
122
+ if (num_labels > index ) {
123
+ str = cv::format (" %s prob:%f" , labels_list[index ], max);
312
124
} else {
313
125
str = cv::format (" Label #%d prob:%f" , index , max);
314
126
}
315
127
/* Get size of string on screen */
316
128
int baseline = 0 ;
317
129
size =
318
- cv::getTextSize (str, cv::FONT_HERSHEY_TRIPLEX,
319
- classification_overlay->box_thickness , classification_overlay->font_scale ,
130
+ cv::getTextSize (str, cv::FONT_HERSHEY_TRIPLEX, thickness, font_scale,
320
131
&baseline);
321
132
/* Put string on screen */
322
133
cv_mat = cv::Mat (height, width, CV_8UC3, (char *) frame->data [0 ]);
323
- cv::putText (cv_mat, str, cv::Point (0 , size.height ),
324
- cv::FONT_HERSHEY_PLAIN, classification_overlay->font_scale , white,
325
- classification_overlay->box_thickness + 1 );
326
-
327
- cv::putText (cv_mat, str, cv::Point (0 , size.height ),
328
- cv::FONT_HERSHEY_PLAIN, classification_overlay->font_scale , black,
329
- classification_overlay->box_thickness );
134
+ cv::putText (cv_mat, str, cv::Point (0 , size.height ), cv::FONT_HERSHEY_PLAIN,
135
+ font_scale, white, thickness + 1 );
136
+ cv::putText (cv_mat, str, cv::Point (0 , size.height ), cv::FONT_HERSHEY_PLAIN,
137
+ font_scale, black, thickness);
330
138
331
139
return GST_FLOW_OK;
332
140
}
0 commit comments