This is the code I wrote to save the images, can you review it? Maybe it might have some errors. nvinfer->resizedFrames_surf
is a custom surface that I created to store the transformed surface. I created it in the following way:
NvBufSurfaceCreateParams create_params;
create_params.gpuId = nvinfer->gpu_id;
create_params.width = 608;
create_params.height = 608;
create_params.size = 0;
create_params.colorFormat = NVBUF_COLOR_FORMAT_RGBA;
create_params.layout = NVBUF_LAYOUT_PITCH;
create_params.memType = NVBUF_MEM_CUDA_UNIFIED;
//create surface for holding
if (NvBufSurfaceCreate(&nvinfer->resizedFrames_surf, 1, &create_params) != 0) {
g_printf("\nError: Could not allocate internal buffer for dsexample");
return false;
}
And then I wrote these two functions to extract the image and save it to disk
static void save_transformed_plate_images(NvBufSurface * surface) {
/* Map the buffer so that it can be accessed by CPU */
if (NvBufSurfaceMap(surface, 0, 0, NVBUF_MAP_READ) != 0) {
g_printf("\nunable to map intermediate surface");
return;
}
for (uint frameIndex = 0; frameIndex < surface->numFilled;
frameIndex++) {
NvBufSurfaceSyncForCpu(surface, frameIndex, 0);
cv::Mat rgbFrame = cv::Mat(
cv::Size(surface->surfaceList[frameIndex].width,
surface->surfaceList[frameIndex].height),
CV_8UC3);
cv::Mat *rgbaFrame = new cv::Mat(
surface->surfaceList[frameIndex].height,
surface->surfaceList[frameIndex].width, CV_8UC4,
surface->surfaceList[frameIndex].mappedAddr.addr[0],
surface->surfaceList[frameIndex].pitch);
#if (CV_MAJOR_VERSION >= 4)
cv::cvtColor(*rgbaFrame, rgbFrame, cv::COLOR_RGBA2BGR);
#else
cv::cvtColor(*rgbaFrame, rgbFrame, CV_RGBA2BGR);
#endif
++i;
std::string saveLocation =
"../plates/img_" + std::to_string(i) + std::string(".jpg");
cv::imwrite(saveLocation, rgbFrame);
}
if (NvBufSurfaceUnMap(surface, 0, 0) != 0) {
g_printf("\nunable to map intermediate surface");
return;
}
}
static gboolean
convert_batch_and_push_to_input_thread (GstNvInfer *nvinfer,
GstNvInferBatch *batch, GstNvInferMemory *mem)
{
NvBufSurfTransform_Error err = NvBufSurfTransformError_Success;
std::string nvtx_str;
/* Set the transform session parameters for the conversions executed in this
* thread. */
err = NvBufSurfTransformSetSessionParams (&nvinfer->transform_config_params);
if (err != NvBufSurfTransformError_Success) {
GST_ELEMENT_ERROR (nvinfer, STREAM, FAILED,
("NvBufSurfTransformSetSessionParams failed with error %d", err), (NULL));
return FALSE;
}
nvtxEventAttributes_t eventAttrib = {0};
eventAttrib.version = NVTX_VERSION;
eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE;
eventAttrib.colorType = NVTX_COLOR_ARGB;
eventAttrib.color = 0xFFFF0000;
eventAttrib.messageType = NVTX_MESSAGE_TYPE_ASCII;
nvtx_str = "convert_buf batch_num=" + std::to_string(nvinfer->current_batch_num);
eventAttrib.message.ascii = nvtx_str.c_str();
nvtxDomainRangePushEx(nvinfer->nvtx_domain, &eventAttrib);
if (batch->frames.size() > 0) {
/* Batched tranformation. */
err = NvBufSurfTransform(&nvinfer->tmp_surf, mem->surf,
&nvinfer->transform_params);
}
if (err != NvBufSurfTransformError_Success) {
GST_ELEMENT_ERROR (nvinfer, STREAM, FAILED,
("NvBufSurfTransform failed with error %d while converting buffer", err),
(NULL));
return FALSE;
}
// save transformed plate images to disk
// save plates if operating in secondary mode
if (err == NvBufSurfTransformError_Success && !nvinfer->process_full_frame
&&
batch->frames.size() > 0) {
nvinfer->resizedFrames_surf->surfaceList->dataSize =
mem->surf->surfaceList->dataSize;
nvinfer->resizedFrames_surf->surfaceList->layout =
mem->surf->surfaceList->layout;
nvinfer->resizedFrames_surf->surfaceList->pitch =
mem->surf->surfaceList->pitch;
nvinfer->resizedFrames_surf->surfaceList->planeParams =
mem->surf->surfaceList->planeParams;
nvinfer->resizedFrames_surf->surfaceList->bufferDesc =
mem->surf->surfaceList->bufferDesc;
nvinfer->resizedFrames_surf->surfaceList->height =
mem->surf->surfaceList->height;
nvinfer->resizedFrames_surf->surfaceList->width =
mem->surf->surfaceList->width; nvinfer->resizedFrames_surf->isContiguous =
false;
NvBufSurfaceMemSet(nvinfer->resizedFrames_surf, 0, 0, 0);
err = NvBufSurfTransform(&nvinfer->tmp_surf, nvinfer->resizedFrames_surf, &nvinfer->transform_params);
nvinfer->resizedFrames_surf->numFilled = nvinfer->tmp_surf.numFilled;
if (err != NvBufSurfTransformError_Success) {
GST_ELEMENT_ERROR(
nvinfer, STREAM, FAILED,
("NvBufSurfTransform failed with error %d while converting buffer",
err),
(NULL));
return FALSE;
}
save_transformed_plate_images(nvinfer->resizedFrames_surf);
g_printf(
"\n---------------->saved transformed plate images to disk prior to sgie "
"detection");
}
nvtxDomainRangePop(nvinfer->nvtx_domain);
LockGMutex locker (nvinfer->process_lock);
/* Push the batch info structure in the processing queue and notify the output
* thread that a new batch has been queued. */
g_queue_push_tail (nvinfer->input_queue, batch);
g_cond_broadcast (&nvinfer->process_cond);
return TRUE;
}