Hello,
I’m using the Jetson inference Detectnet over a RTSP stream. While using the python examples, this works fine.
Python snippet:
input_stream = videoSource(input_stream_link, argv=[f'--input-width={width}', f'--input-height={height}', '--input-frameRate=10'])
output_stream_link = "rtsp://172.16.160.37:855" + str(5+index) + "/AI_stream" + str(index)
output_stream = videoOutput(output_stream_link, argv=[f'--output-width={width}', f'--output-height={height}', '--output-frameRate=10', '--output-codec=h264'])
net = jetson_inference.detectNet("ssd-mobilenet-v2", threshold=0.3)
print(f"output_stream_link: {output_stream_link}")
i = 0
timeout = 20000
while True:
img = input_stream.Capture()
if img==None or i == timeout:
print(f"Exiting Thread {index}")
break
detections = net.Detect(img)
output_stream.Render(img)
The detection is as expected. No, while integrating this into our C++ application, here we have some issues. The detections are all over the place. Where the python application draws a bounding box over a person fine, the C++ application draws wherever. (using the same Jetson nano for both runs)
C++ Snippet:
inference.h
uchar3* img_RGB = NULL;
detectNet* net = NULL;
detectNet::Detection* detections = NULL;
int numDetections = 0;
uint32_t overlayFlags = detectNet::OverlayFlagsFromStr("overlay,box,labels,conf");
inference.cpp
int Inference::do_inference(NvEglImage* frame, int width, int height){
size_t img_RGB_size = width * height * sizeof(uchar3);
CUresult status;
cudaError cuda_error;
CUeglFrame egl_frame;
CUgraphicsResource pResource = NULL;
cudaFree(0);
status = cuGraphicsEGLRegisterImage(&pResource, frame->image, CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE);
if (status != CUDA_SUCCESS){
g_warning("cuGraphicsEGLRegisterImage failed: %d\n", status);
return status;
}
status = cuGraphicsResourceGetMappedEglFrame(&egl_frame, pResource, 0, 0);
if (status != CUDA_SUCCESS){
g_warning("cuGraphicsSubResourceGetMappedArray failed: %d\n", status);
return status;
}
cuda_error = cudaMallocManaged (&img_RGB, img_RGB_size);
if(cuda_error != cudaSuccess){
g_warning("cudaMallocManaged failed: %d", cuda_error);
return cuda_error;
}
// convert from i420 to rgba32
cuda_error = cudaConvertColor(egl_frame.frame.pPitch[0], IMAGE_I420, img_RGB, IMAGE_RGB8 , width, height);
if(cuda_error != cudaSuccess ) {
g_warning("cudaConvertColor I420 -> RGB failed: %d", cuda_error);
return cuda_error;
}
numDetections = net->Detect(img_RGB, width, height, &detections, overlayFlags);
// convert from i420 to rgba32
cuda_error = cudaConvertColor(img_RGB, IMAGE_RGB8, egl_frame.frame.pPitch[0], IMAGE_I420, width, height);
if(cuda_error != cudaSuccess ){
g_warning("cudaConvertColor RGB -> I420 failed: %d", cuda_error);
return cuda_error;
}
status = cuCtxSynchronize();
if (status != CUDA_SUCCESS){
g_warning("cuCtxSynchronize failed\n");
return status;
}
last_height = height;
last_width = width;
cuGraphicsUnregisterResource(pResource);
if (img_RGB != NULL){
cudaFree(img_RGB);
}
return 0;
}
For context, a gstreamer pipeline writes the NvEglImage to the do_inference function. Here I do the needed conversions, do the detection, and write this back to the NvEglImage* frame.
Is there anything inherently wrong the way I’m doing this?
Kind regards