How to convert object image to base64

Hi all
In deepstream test5 app, i was get object image file by function nvds_obj_enc_process. But this function write obj to jpeg file in disk, so i can’t get this object to convert to base64.
How can i convert this image to base64 in deepstream test5 app ?
thank so much

**• Hardware Platform Jetson **
• DeepStream 5.0
• JetPack Version 4.4

I write some code:

#include <gst/gst.h>
#include <glib.h>
#include <iostream>
#include <unordered_map>
#include <sstream>
#include "gstnvdsmeta.h"
#include "nvds_analytics_meta.h"

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"

#include <cuda.h>
#include <cuda_runtime.h>
#include "nvbufsurface.h"
#include "nvbufsurftransform.h"

/* parse_nvdsanalytics_meta_data
 * and extract nvanalytics metadata etc. */
extern "C" bool
parse_nvdsanalytics_meta_data (NvDsObjectMeta *obj_meta)
{
    gboolean objectIsAnalytics = FALSE;
    for (NvDsMetaList *l_user_meta = obj_meta->obj_user_meta_list; l_user_meta != NULL;
                    l_user_meta = l_user_meta->next) {
        NvDsUserMeta *user_meta = (NvDsUserMeta *) (l_user_meta->data);
        if(user_meta->base_meta.meta_type == NVDS_USER_OBJ_META_NVDSANALYTICS)
        {
//            g_print("in parse_nvdsanalytics_meta_data %d");
            objectIsAnalytics = TRUE;
        }
    }
    return objectIsAnalytics;
}

extern "C" void
enc_object2base64(NvBufSurface *input_buf, gint idx, NvDsFrameMeta *frame_meta)
{
    NvBufSurface ip_surf;
    NvBufSurfTransformRect src_rect, dst_rect;

    ip_surf = *input_buf;

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


    int batch_size= input_buf->batchSize;
    printf("\nBatch Size : %d, resolution : %dx%d \n",batch_size,
        input_buf->surfaceList[idx].width, input_buf->surfaceList[idx].height);

    src_rect.top   = 0;
    src_rect.left  = 0;
    src_rect.width = (guint) input_buf->surfaceList[idx].width;
    src_rect.height= (guint) input_buf->surfaceList[idx].height;

    dst_rect.top   = 0;
    dst_rect.left  = 0;
    dst_rect.width = (guint) input_buf->surfaceList[idx].width;
    dst_rect.height= (guint) input_buf->surfaceList[idx].height;

    NvBufSurfTransformParams nvbufsurface_params;
    nvbufsurface_params.src_rect = &src_rect;
    nvbufsurface_params.dst_rect = &dst_rect;
    nvbufsurface_params.transform_flag =  NVBUFSURF_TRANSFORM_CROP_SRC | NVBUFSURF_TRANSFORM_CROP_DST;
    nvbufsurface_params.transform_filter = NvBufSurfTransformInter_Default;

    NvBufSurface *dst_surface = NULL;
    NvBufSurfaceCreateParams nvbufsurface_create_params;

    /* An intermediate buffer for NV12/RGBA to BGR conversion  will be
     * required. Can be skipped if custom algorithm can work directly on NV12/RGBA. */
    nvbufsurface_create_params.gpuId  = input_buf->gpuId;
    nvbufsurface_create_params.width  = (gint) input_buf->surfaceList[idx].width;
    nvbufsurface_create_params.height = (gint) input_buf->surfaceList[idx].height;
    nvbufsurface_create_params.size = 0;
    nvbufsurface_create_params.colorFormat = NVBUF_COLOR_FORMAT_RGBA;
    nvbufsurface_create_params.layout = NVBUF_LAYOUT_PITCH;
    nvbufsurface_create_params.memType = NVBUF_MEM_DEFAULT;

    cudaError_t cuda_err;

    cuda_err = cudaSetDevice (input_buf->gpuId);
    if (cuda_err != cudaSuccess){
        g_print("Cuda set device error");
    }

    cudaStream_t cuda_stream;

    cuda_err=cudaStreamCreate (&cuda_stream);
    if (cuda_err != cudaSuccess){
        g_print("Cuda create stream error");
    }

    int create_result = NvBufSurfaceCreate(&dst_surface,1,&nvbufsurface_create_params);
    if (create_result != 0){
        g_print("NvBufSurfaceCreate Error\n");
    }

    NvBufSurfTransformConfigParams transform_config_params;
    NvBufSurfTransform_Error err;

    transform_config_params.compute_mode = NvBufSurfTransformCompute_Default;
    transform_config_params.gpu_id = input_buf->gpuId;
    transform_config_params.cuda_stream = cuda_stream;
    err = NvBufSurfTransformSetSessionParams (&transform_config_params);

    if (err != NvBufSurfTransformError_Success) {
        g_print ("NvBufSurfTransformSetSessionParams failed with error %d while setting parameter\n", err);
    }

    NvBufSurfaceMemSet (dst_surface, frame_meta->batch_id, 0, 0);
    err = NvBufSurfTransform (&ip_surf, dst_surface, &nvbufsurface_params);

    if (err != NvBufSurfTransformError_Success) {
  	  g_print ("NvBufSurfTransform failed with error %d while converting buffer\n", err);
    }

    NvBufSurfaceMap (dst_surface, frame_meta->batch_id, 0, NVBUF_MAP_READ_WRITE);
    NvBufSurfaceSyncForCpu (dst_surface, frame_meta->batch_id, 0);
//
    cv::Mat in_mat =
            cv::Mat (dst_surface->surfaceList[frame_meta->batch_id].planeParams.height[0],
            dst_surface->surfaceList[frame_meta->batch_id].planeParams.width[0], CV_8UC4,
            dst_surface->surfaceList[frame_meta->batch_id].mappedAddr.addr[0],
            dst_surface->surfaceList[frame_meta->batch_id].planeParams.pitch[0]);

    //try to write out image to disk
    cv::imwrite("out.jpeg", in_mat);
    // convert in_mat to base64 string 
    //....
    //

    NvBufSurfaceUnMap (dst_surface, 0, 0);
    NvBufSurfaceDestroy (dst_surface);
    cudaStreamDestroy (cuda_stream);
}

make not error, but when i run so get Segmentation fault (core dumped) at line: cv::imwrite(“out.jpeg”, in_mat);
help me

i try with mp4 source with type=3 it working well, but change to rtsp source with type=4 it not working and get Segmentation fault ( core dumped ) at line:

help me

Are you using deepstream-app? If so, you need to show us your deepstream-app config file. If you have modified deepstream-app source codes, you need to tell us where and how the codes are changed and why you change them in this way. In fact, your above description is vague and confused, we don’t understand what is happenning.E.g.you don’t tell us where your “enc_object2base64” function is invoked, and what your “base64” mean?

i run on deepstream test5 app with custom:

  • Create file deepstream_nvdsanalytics_meta.cpp with contain

  • Cutom makefile to include opencv and use deepstream_nvdsanalytics_meta.cpp in deepstream_test5_app_main.c Makefile (3.1 KB)

  • in deepstream_test5_app_main.c file i call extern char* enc_object2base64(GstBuffer * buf) and use this function in generate_event_msg_meta to get base64 string of image object decode. deepstream_test5_app_main.c (52.0 KB) deepstream_nvdsanalytics_meta.cpp (7.5 KB)

You transferred “GstBuffer *” to enc_object2base64(), but why you use this “GstBuffer *” as “NvBufSurface *” inside enc_object2base64()? It is wrong. “GstBuffer” is not “NvBufSurface”.

Look at this line in generate_event_msg_meta():
meta->videoPath = g_strdup(enc_object2base64(buf));

But you define enc_object2base64() as an “void” function, it does not return anything.

How could you pass the return value to “meta->videoPath”? Do you really understand what you are doing?

The last and most fatal error is that “in_mat” is defined in enc_object2base64() function, it will not be maintained outside this function. It will cause crash if the address of “in_mat” is been used in other places. The address means nothing outside enc_object2base64(), I don’t understand why you want to transfer this address to others. I think it is not a reasonable requirement for DeepStream or even for any c/c++ based application.

sory, this is old code, you can check in file

i run success with source is mp4 file, but with source is http or rtsp link so it not run and crash at cv::imwrite or cv::imencode

What “type”?

type =4

The color format may be different. Please check the “surface->surfaceList[0].colorFormat” value when use RTSP source.

i was check color format is NVBUF_COLOR_FORMAT_NV12

So, in your codes:
cv::cvtColor (in_mat, bgr_frame, cv::COLOR_RGBA2BGR);
//
std::string encoded_jpeg;
std::vector encode_buffer;

cv::imencode(".jpg",bgr_frame,encode_buffer);

//
auto base64_jpeg = reinterpret_cast<const unsigned char*>(encode_buffer.data());
encoded_jpeg = g_base64_encode(base64_jpeg, encode_buffer.size());
//
char *encoded_jpeg_out = new char[encoded_jpeg.length() + 1];
strcpy(encoded_jpeg_out, encoded_jpeg.c_str());

// std::ofstream out(“output.txt”);
// out << encoded_jpeg;
// out.close();
// char filename[64];
// snprintf(filename, 64, “/tmp/timage%03d.jpg”, dump);
// cv::imwrite(filename,bgr_frame);
// dump ++;

The line of “// cv::imwrite(filename,bgr_frame);” will crash if you switch to rtsp source?

1 Like

yes, this line and line

i check this rtsp link in dsexample use cv::imwrite or cv::imencode work well, but i don’t know why in this source not working

this is error:

Core dumped :

when i commented out cv::imwrite or cv::imencode so run normal with rtsp source

help me

It may take some time. Will be back to you when there is any finding.

1 Like

thank you