一、保存特征图片
在英伟达官方例子deepstream-image-meta-test代码中,提供了保存特征区域(ROI)的代码:
static GstPadProbeReturn
pgie_src_pad_buffer_probe(GstPad *pad, GstPadProbeInfo *info, gpointer ctx)
{
GstBuffer *buf = (GstBuffer *)info->data;
GstMapInfo inmap = GST_MAP_INFO_INIT;
if (!gst_buffer_map(buf, &inmap, GST_MAP_READ))
{
GST_ERROR("input buffer mapinfo failed");
return GST_FLOW_ERROR;
}
NvBufSurface *ip_surf = (NvBufSurface *)inmap.data;
gst_buffer_unmap(buf, &inmap);
NvDsObjectMeta *obj_meta = NULL;
guint vehicle_count = 0;
guint person_count = 0;
NvDsMetaList *l_frame = NULL;
NvDsMetaList *l_obj = NULL;
NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta(buf);
for (l_frame = batch_meta->frame_meta_list; l_frame != NULL;
l_frame = l_frame->next)
{
NvDsFrameMeta *frame_meta = (NvDsFrameMeta *)(l_frame->data);
guint num_rects = 0;
for (l_obj = frame_meta->obj_meta_list; l_obj != NULL; l_obj = l_obj->next)
{
obj_meta = (NvDsObjectMeta *)(l_obj->data);
if (obj_meta->class_id == PGIE_CLASS_ID_VEHICLE)
{
vehicle_count++;
num_rects++;
}
if (obj_meta->class_id == PGIE_CLASS_ID_PERSON)
{
person_count++;
num_rects++;
}
/* Conditions that user needs to set to encode the detected objects of
* interest. Here, by default all the detected objects are encoded.
* For demonstration, we will encode the first object in the frame */
if ((obj_meta->class_id == PGIE_CLASS_ID_PERSON || obj_meta->class_id == PGIE_CLASS_ID_VEHICLE) && num_rects == 1)
{
NvDsObjEncUsrArgs userData = {0};
/* To be set by user */
userData.saveImg = save_img;
userData.attachUsrMeta = attach_user_meta;
/* Set if Image scaling Required */
userData.scaleImg = FALSE;
userData.scaledWidth = 0;
userData.scaledHeight = 0;
/* Preset */
userData.objNum = num_rects;
/* Quality */
userData.quality = 80;
/*Main Function Call */
nvds_obj_enc_process(ctx, &userData, ip_surf, obj_meta, frame_meta);
}
}
}
nvds_obj_enc_finish(ctx);
return GST_PAD_PROBE_OK;
}
这段代码关键是调用了nvds_obj_enc_process生成图片,默认的图片名称为"frame-number_stream-number_object-number_object-type_widthxheight.jpg",例如0_2_3_PERSON_126x148.jpg,保存在程序的同级目录下。
二、保存完整图片
根据英伟达开发者论坛的帖子,保存完整图片的代码:
static GstPadProbeReturn
pgie_src_pad_buffer_probe (GstPad * pad, GstPadProbeInfo * info, gpointer ctx)
{
GstBuffer *buf = (GstBuffer *) info->data;
GstMapInfo inmap = GST_MAP_INFO_INIT;
if (!gst_buffer_map (buf, &inmap, GST_MAP_READ)) {
GST_ERROR ("input buffer mapinfo failed");
return GST_FLOW_ERROR;
}
NvBufSurface *ip_surf = (NvBufSurface *) inmap.data;
gst_buffer_unmap (buf, &inmap);
NvDsObjectMeta *obj_meta = NULL;
NvDsMetaList *l_frame = NULL;
NvDsMetaList *l_obj = NULL;
NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta (buf);
for (l_frame = batch_meta->frame_meta_list; l_frame != NULL; l_frame = l_frame->next)
{
NvDsFrameMeta *frame_meta = (NvDsFrameMeta *) (l_frame->data);
guint num_rects = 0;
for (l_obj = frame_meta->obj_meta_list; l_obj != NULL; l_obj = l_obj->next)
{
obj_meta = (NvDsObjectMeta *) (l_obj->data);
if (obj_meta->class_id == 0) {
num_rects++;
}
/* Conditions that user needs to set to encode the detected objects of
* interest. Here, by default all the detected objects are encoded.
* For demonstration, we will encode the first object in the frame */
if ( frame_meta->source_id == 0 && obj_meta->class_id == 0 && num_rects == 1 )
{
NvDsObjEncUsrArgs userData = { 0 };
/* To be set by user */
userData.saveImg = TRUE;
userData.attachUsrMeta = TRUE;
/* Set if Image scaling Required */
userData.scaleImg = FALSE;
userData.scaledWidth = 0;
userData.scaledHeight = 0;
/* Preset */
userData.objNum = num_rects;
obj_meta->rect_params.width = frame_meta->source_frame_width ;
obj_meta->rect_params.height = frame_meta->source_frame_height ;
obj_meta->rect_params.top = 0.0f ;
obj_meta->rect_params.left = 0.0f ;
nvds_obj_enc_process (ctx, &userData, ip_surf, obj_meta, frame_meta);
}
}
}
nvds_obj_enc_finish (ctx);
return GST_PAD_PROBE_OK;
}
其中,关键部分是
obj_meta->rect_params.width = frame_meta->source_frame_width ;
obj_meta->rect_params.height = frame_meta->source_frame_height ;
三、设置文件名
使用userData的fileNameImg来设置文件名,如下代码将文件名保存为images/1.jpg,images/2.jpg...。
char fileNameString[30];
snprintf(userData.fileNameImg, sizeof(userData.fileNameImg), "images/%d.jpg", ++image_index);
四、未检测到特征的图片保存
如果我们想把未检测到特征(例如 人)的图片存一下,看看是不是误判,会遇到一个问题:obj_meta = (NvDsObjectMeta *) (l_obj->data); 这句执行不到,obj_meta 等于 NULL。没有查到NvDsObjectMeta如果创建新实例,我的做法是定义一个全局的NvDsObjectMeta *obj_meta = NULL,用前次不为NULL的obj_meta传递给nvds_obj_enc_process保存即可。