0. 前言
上一篇寫的是基於test4的更改,後來應用到app的demo裏發現顏色轉換存在問題。
首先要確定自己的探針添加位置,以及該位置獲取的圖像顏色空間是什麼。在deepstream-app裏我查看的是NV12,CV裏沒有NV12轉BGR(或許有,我沒找到),所以需要利用NvBufSurfTransform 和NvBufSurfTransformParams進行轉換。
1. 分源截圖
如果演示的視頻一共有4路,如何將這4路分別截圖呢?方法是利用source_id和batch_id。
其中source_id代表不同的源,這些信息進入隊列後,不是按照順序排列的,有可能第二個先進入,然後第四個又進入了,後面纔是1、3。batch_id對應的就是隊列裏的位置。NvBufSurface的surfacelist對應的是batch_id。
如何獲取source_id和batch_id呢?這些都存在NvDsFrameMeta的結構裏。
可令:
NvBufSurface *surface = NULL;
NvBufSurface surface_idx;
surface_idx.surfaceList = &(surface->surfaceList[batch_id]);
2. 參數轉換
先轉成RGBA,再用opencv轉BGR
/** save pictures */
// GstBuffer *buf;
NvBufSurfTransformRect src_rect, dst_rect;
NvBufSurfTransformParams nvbufsurface_params;
NvBufSurface *dst_surface = NULL;
NvBufSurfaceCreateParams nvbufsurface_create_params;
cudaError_t cuda_err;
cudaStream_t cuda_stream;
gint create_result;
NvBufSurfTransformConfigParams transform_config_params;
NvBufSurfTransform_Error err;
cv::Mat bgr_frame, in_mat;
batch_size = surface_idx.batchSize;
src_rect.top = 0;
src_rect.left = 0;
src_rect.width = (guint) surface->surfaceList[batch_id].width;
src_rect.height = (guint) surface->surfaceList[batch_id].height;
dst_rect.top = 0;
dst_rect.left = 0;
dst_rect.width = (guint) surface->surfaceList[batch_id].width;
dst_rect.height = (guint) surface->surfaceList[batch_id].height;
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_create_params.gpuId = surface->gpuId;
nvbufsurface_create_params.width = (guint) surface->surfaceList[batch_id].width;
nvbufsurface_create_params.height = (guint) surface->surfaceList[batch_id].height;
nvbufsurface_create_params.size = 0;
nvbufsurface_create_params.isContiguous = true;
nvbufsurface_create_params.colorFormat = NVBUF_COLOR_FORMAT_RGBA;
nvbufsurface_create_params.layout = NVBUF_LAYOUT_PITCH;
// THE memType PARAM IS SET TO CUDA UNIFIED IN dGPU DEVICES COMMENT IT out
// AND USE THE IMMEDIATE NEXT LINE TO SET THE memType PARAM FOR JETSON DEVICES
#ifdef PLATFORM_TEGRA
nvbufsurface_create_params.memType = NVBUF_MEM_DEFAULT;
#else
nvbufsurface_create_params.memType = NVBUF_MEM_CUDA_UNIFIED;
#endif
cuda_err = cudaSetDevice (surface->gpuId);
cuda_err = cudaStreamCreate(&cuda_stream);
create_result = NvBufSurfaceCreate(&dst_surface, batch_size, &nvbufsurface_create_params);
transform_config_params.compute_mode = NvBufSurfTransformCompute_Default;
transform_config_params.gpu_id = surface->gpuId;
transform_config_params.cuda_stream = cuda_stream;
err = NvBufSurfTransformSetSessionParams (&transform_config_params);
NvBufSurfaceMemSet (dst_surface, 0, 0, 0);
err = NvBufSurfTransform (&surface_idx, dst_surface, &nvbufsurface_params);
if (err != NvBufSurfTransformError_Success) {
g_print ("NvBufSurfTransform failed with error %d while converting buffer\n", err);
}
NvBufSurfaceMap (dst_surface, 0, 0, NVBUF_MAP_READ);
NvBufSurfaceSyncForCpu (dst_surface, 0, 0);
用完不要忘記釋放空間
NvBufSurfaceUnMap(dst_surface, 0, 0);
NvBufSurfaceUnMap(&surface_idx, 0, 0);
NvBufSurfaceDestroy(dst_surface);
cudaStreamDestroy (cuda_stream);
gst_buffer_unmap (buf, &in_map_info);
3. 其他問題
(1)目前我調試還會遇到以下錯誤:
CUDA error at nvbufsurftransform.cpp:1793 code=-57(NPP_RECTANGLE_ERROR) “nppiResizeSqrPixel_8u_C4R ( src_ptr + src_offset, jnppSrcSize, jsrc_pitch, jnppSrcROI, intermediate_buffer + dst_offset, jdst_pitch, jnppDstROI, scale_x, scale_y, jdx, jdy, nppInterFlag)”
NvBufSurfTransfrom failed with error -3 while converting buffer
目前無解,但不影響截圖~~有哪位大佬找到問題所在後可以私戳我。
(2)糾錯
上篇文章裏寫到,對於非jetson,用不到下面兩個函數:
NvBufSurfaceMap (dst_surface, 0, 0, NVBUF_MAP_READ);
NvBufSurfaceSyncForCpu (dst_surface, 0, 0);
這裏闢謠一下。這種說法是不對的,能不能在GPU上跑,和這倆函數無關。一定要有buffer的拷貝就對了。
4. makefile
補充一下,有人問makefile是否需要修改。
需要的。
需要添加opencv的頭文件,庫,以及-lnvbufsurface -lnvbufsurftransform 兩個庫。如果用到了cuda,也需要添加cuda的相關內容。
5. 結果
存的圖片分路保存了,加了個時間戳
截圖效果如下: