Performing OpenCV operations on pipeline buffer

In continuing with the discussion here , as the post has been archived, here is the updated get_converted_mat function.

static GstFlowReturn
get_converted_mat (GstDsExample * dsexample, NvBufSurface *input_buf, gint idx,
    NvOSD_RectParams * crop_rect_params, gdouble & ratio, gint input_width,
    gint input_height)
{
  NvBufSurfTransform_Error err;
  NvBufSurfTransformConfigParams transform_config_params;
  NvBufSurfTransformParams transform_params;
  NvBufSurfTransformRect src_rect;
  NvBufSurfTransformRect dst_rect;
  NvBufSurface ip_surf;
  cv::Mat in_mat;
  ip_surf = *input_buf;
  cv::Rect2f roi;
  auto bbox_color = cv::Scalar(0, 255, 0);

  ip_surf.numFilled = ip_surf.batchSize = 1;
  ip_surf.surfaceList = &(input_buf->surfaceList[idx]);

  gint src_left = GST_ROUND_UP_2(crop_rect_params->left);
  gint src_top = GST_ROUND_UP_2(crop_rect_params->top);
  gint src_width = GST_ROUND_DOWN_2(crop_rect_params->width);
  gint src_height = GST_ROUND_DOWN_2(crop_rect_params->height);

  // Maintain aspect ratio
  double hdest = dsexample->processing_width * src_height / (double) src_width;
  double wdest = dsexample->processing_height * src_width / (double) src_height;
  guint dest_width, dest_height;

  if (hdest <= dsexample->processing_height) {
    dest_width = dsexample->processing_width;
    dest_height = hdest;
  } else {
    dest_width = wdest;
    dest_height = dsexample->processing_height;
  }

  // Configure transform session parameters for the transformation
  transform_config_params.compute_mode = NvBufSurfTransformCompute_Default;
  transform_config_params.gpu_id = dsexample->gpu_id;
  transform_config_params.cuda_stream = dsexample->cuda_stream;

  // Set the transform session parameters for the conversions executed in this
  // thread.
  err = NvBufSurfTransformSetSessionParams (&transform_config_params);
  if (err != NvBufSurfTransformError_Success) {
    GST_ELEMENT_ERROR (dsexample, STREAM, FAILED,
        ("NvBufSurfTransformSetSessionParams failed with error %d", err), (NULL));
    goto error;
  }

  // Calculate scaling ratio while maintaining aspect ratio
  ratio = MIN (1.0 * dest_width/ src_width, 1.0 * dest_height / src_height);

  if ((crop_rect_params->width == 0) || (crop_rect_params->height == 0)) {
    GST_ELEMENT_ERROR (dsexample, STREAM, FAILED,
        ("%s:crop_rect_params dimensions are zero",__func__), (NULL));
    goto error;
  }

#ifdef __aarch64__
  if (ratio <= 1.0 / 16 || ratio >= 16.0) {
    // Currently cannot scale by ratio > 16 or < 1/16 for Jetson
    goto error;
  }
#endif
  // Set the transform ROIs for source and destination
  src_rect = {(guint)src_top, (guint)src_left, (guint)src_width, (guint)src_height};
  dst_rect = {0, 0, (guint)dest_width, (guint)dest_height};

  // Set the transform parameters
  transform_params.src_rect = &src_rect;
  transform_params.dst_rect = &dst_rect;
  transform_params.transform_flag =
    NVBUFSURF_TRANSFORM_FILTER | NVBUFSURF_TRANSFORM_CROP_SRC |
      NVBUFSURF_TRANSFORM_CROP_DST;
  transform_params.transform_filter = NvBufSurfTransformInter_Default;

  //Memset the memory
  NvBufSurfaceMemSet (dsexample->inter_buf, 0, 0, 0);

  GST_DEBUG_OBJECT (dsexample, "Scaling and converting input buffer\n");

  // Transformation scaling+format conversion if any.
  err = NvBufSurfTransform (&ip_surf, dsexample->inter_buf, &transform_params);
  if (err != NvBufSurfTransformError_Success) {
    GST_ELEMENT_ERROR (dsexample, STREAM, FAILED,
        ("NvBufSurfTransform failed with error %d while converting buffer", err),
        (NULL));
    goto error;
  }
    // Map the buffer so that it can be accessed by CPU
    if (NvBufSurfaceMap (dsexample->inter_buf, 0, 0, NVBUF_MAP_READ_WRITE) != 0){
        goto error;
    }

  // Cache the mapped data for CPU access
  NvBufSurfaceSyncForCpu (dsexample->inter_buf, 0, 0);

  // Use openCV to remove padding and convert RGBA to BGR. Can be skipped if
  // algorithm can handle padded RGBA data.
  in_mat =
      cv::Mat (dsexample->processing_height, dsexample->processing_width,
      CV_8UC4, dsexample->inter_buf->surfaceList[0].mappedAddr.addr[0],
      dsexample->inter_buf->surfaceList[0].pitch);

#if (CV_MAJOR_VERSION >= 4)
  cv::cvtColor (in_mat, *dsexample->cvmat, cv::COLOR_RGBA2BGR);
#else
  cv::cvtColor (in_mat, *dsexample->cvmat, CV_RGBA2BGR);
#endif

  roi.x = 10;
  roi.y = 10;
  roi.width = 50;
  roi.height = 50;
  cv::rectangle(*dsexample->cvmat,roi, bbox_color, 1);
  cv::putText(*dsexample->cvmat, "car", cv::Point(roi.x, roi.y-10), cv::FONT_HERSHEY_PLAIN, 1, bbox_color);	
   cv::cvtColor (*dsexample->cvmat, in_mat, cv::COLOR_BGR2RGBA);
   NvBufSurfaceSyncForDevice (dsexample->inter_buf, 0, 0);
  // Set the transform ROIs for source and destination
  src_rect = {(guint)0, (guint)0, (guint)dest_width, (guint)dest_height};
  dst_rect = {0, 0, (guint)dest_width, (guint)dest_height};
  // Set the transform parameters
  transform_params.src_rect = &src_rect;
  transform_params.dst_rect = &dst_rect;
  transform_params.transform_flag =
    NVBUFSURF_TRANSFORM_FILTER | NVBUFSURF_TRANSFORM_CROP_SRC |
      NVBUFSURF_TRANSFORM_CROP_DST;
  transform_params.transform_filter = NvBufSurfTransformInter_Default;

  //Memset the memory
  NvBufSurfaceMemSet (&ip_surf, 0, 0, 0);
  // Transformation scaling+format conversion if any.
  err = NvBufSurfTransform (dsexample->inter_buf, &ip_surf, &transform_params);
  if (err != NvBufSurfTransformError_Success) {
    GST_ELEMENT_ERROR (dsexample, STREAM, FAILED,
        ("NvBufSurfTransform failed with error %d while converting buffer", err),
        (NULL));
    goto error;
  }
  GST_DEBUG_OBJECT (dsexample, "Scaling and converting input buffer\n");

  if (NvBufSurfaceUnMap (dsexample->inter_buf, 0, 0)){
    goto error;
  }

#ifdef __aarch64__
  // To use the converted buffer in CUDA, create an EGLImage and then use
  // CUDA-EGL interop APIs
  if (USE_EGLIMAGE) {
    if (NvBufSurfaceMapEglImage (dsexample->inter_buf, 0) !=0 ) {
      goto error;
    }

    // dsexample->inter_buf->surfaceList[0].mappedAddr.eglImage
    // Use interop APIs cuGraphicsEGLRegisterImage and
    // cuGraphicsResourceGetMappedEglFrame to access the buffer in CUDA

    // Destroy the EGLImage
    NvBufSurfaceUnMapEglImage (dsexample->inter_buf, 0);
  }
#endif

  /* We will first convert only the Region of Interest (the entire frame or the
   * object bounding box) to RGB and then scale the converted RGB frame to
   * processing resolution. */
  return GST_FLOW_OK;

error:
  return GST_FLOW_ERROR;
}

The flickering of lines is still observed.

Hi,
We will try to reproduce it with the patch. One thing to confirm is that you have to set full-frame=1 in [ds-example], or the frame is possibly overwritten multiple times due to the for loop in gst_dsexample_transform_ip():

      for (l_obj = frame_meta->obj_meta_list; l_obj != NULL;
          l_obj = l_obj->next)

Yes, full-frame is set to 1.

Even if the frame is overwritten multiple times, may I know the reason why this kind of flickering is observed. It’s understandable if the bbox themselves don’t get drawn. But sometimes, only two sides are drawn, sometimes 3 sometimes all 4. And the remaining sides have whitish colour.

Hi neophyte1,

We are using your code and build the gstdsexample.cpp, then run the deepstream-app, it can run successful.
Attached our output “Nano-gstdsexample.jpg” for you reference.

Hi,
Thanks for the quick response. Continuing with comment, can you elaborate upon it.
Also, I am using EGL sink for rendering. i.e option 2.

Hi neophyte1,

I also check Eglsink (type=2), result looks good.
For my above picture is test with default setting, type=5.

Test with “source8_1080p_dec_infer-resnet_tracker_tiled_display_fp16_nano.txt” config and add below:

[ds-example]
enable=1
processing-width=640
processing-height=480
full-frame=1
unique-id=15

Hi,
I am already adding ds-example in the spec file.
I would like to know, why if the frame is overwritten, there is a chance of such flickering as mentioned in the above comments. Can you elaborate upon it ?

Hi,
Would need your help to share a consistent way of reproducing the flickering. We have tested the patch and don’t see the issue. In your description, it seems to be certain issue in NvBufSurfaceSyncForDevice(). Need to reproduce the issue first so that we can do investigation.