Jetson Nano 系列之:保存整张图片

一、保存特征图片

在英伟达官方例子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保存即可。

你可能感兴趣的:(Jetson,jetson,deepstream,图片)