Having trouble tracking objects using nvds_mot_klt

Hey! I’m having trouble running the low level nvds_mot_klt tracker on an OpenCV image output. I’m not too sure if I’m doing the correct workflow or am populating the NvBufSurface in a correct fashion. The trackers bounding box does not seem to move / I don’t get any updated tracked objects.

I think I’m also confused between the the relationship between NvMOTObjToTrackList that goes into the NvMOTFrame and the NvMOTTrackedObjBatch that gets returned by the NvMOT_Process.

Here’s the code I have written:

auto configFile = std::string("/opt/nvidia/deepstream/deepstream-4.0/sources/apps/sample_apps/deepstream-test2/dstest2_tracker_config.txt");
auto configFileRecasted = const_cast<char*> (configFile.c_str());

NvMOTQuery query;
NvMOT_Query(configFile.size(), configFileRecasted, &query);

NvMOTPerTransformBatchConfig transformBatchConfig;
transformBatchConfig.bufferType = query.memType;
transformBatchConfig.colorFormat = query.colorFormats[0];
transformBatchConfig.maxWidth = 640;
transformBatchConfig.maxHeight = 368;
transformBatchConfig.maxPitch = 1;
transformBatchConfig.maxSize = 640 * 368 * 1;

//            uint8_t numTransforms: The number of color formats required by the lowlevel library. The valid range for this field is 0 to NVMOT_MAX_TRANSFORMS. Set
//            this to 0 if the library does not require any visual data. Note that 0 does not mean
//            that untransformed data will be passed to the library
NvMOTConfig config;
config.computeConfig = query.computeConfig;
config.maxStreams = 1;
config.customConfigFilePath = configFileRecasted;
config.customConfigFilePathSize = configFile.size();
config.perTransformBatchConfig = &transformBatchConfig;
config.numTransforms = query.numTransforms;

NvMOTContextHandle contextHandle;
NvMOTConfigResponse configResponse;

auto status_init = NvMOT_Init(&config, &contextHandle, &configResponse);
if (status_init == NvMOTStatus_OK)
{
	std::cout << "STATUS INIT OK" << std::endl;
}

NvBufSurface *surface = new NvBufSurface();

NvBufSurfaceCreateParams surfaceCreateParams;
surfaceCreateParams.layout = NVBUF_LAYOUT_PITCH;
surfaceCreateParams.colorFormat = query.colorFormats[0];
surfaceCreateParams.width = 640;
surfaceCreateParams.height = 368;
surfaceCreateParams.gpuId = 0;
surfaceCreateParams.isContiguous = true;
surfaceCreateParams.size = 0;
surfaceCreateParams.memType = query.memType;

auto result = NvBufSurfaceCreate(&surface, 1, &surfaceCreateParams);
if (result == -1)
	throw std::string("NvBufSurfaceCreate ERROR!");

NvMOTObjToTrack objToTrack;
objToTrack.bbox = NvMOTRect
{
	100, 130, 60, 150
};
objToTrack.doTracking = true;
objToTrack.classId = 0;
objToTrack.confidence = 100.0 f;
objToTrack.pPreservedData = nullptr;

NvMOTObjToTrackList objToTrackList;
objToTrackList.list = &objToTrack;
objToTrackList.numFilled = 1;
objToTrackList.numAllocated = 1;
objToTrackList.detectionDone = false;

int frameNum = 0;
cv::VideoCapture videoCapture("/opt/nvidia/deepstream/deepstream-4.0/samples/streams/sample_720p.h264");
while (videoCapture.isOpened())
{
	cv::Mat frame;
	auto result = videoCapture.read(frame);

	if (result)
	{
		cv::cvtColor(frame, frame, cv::COLOR_BGR2GRAY);
		cv::resize(frame, frame, cv::Size(640, 368));

		//                    cv::Mat frameDraw (frame);
		//                    cv::rectangle(frameDraw, cv::Rect(100, 130, 60, 150), cv::Scalar(255, 0, 0));
		//                    cv::imshow("DRAW FRAME", frameDraw);
		//                    cv::waitKey(30);

		surface->surfaceList->mappedAddr.addr[0] = (void*) frame.data;
		surface->numFilled = 1;
		//                    cudaMemcpy(surface->surfaceList->dataPtr, (void*)frame.data, surface->surfaceList[0].dataSize, cudaMemcpyHostToDevice);
		//                    cv::cuda::GpuMat dst(368, 640, CV_8UC1, surface->surfaceList->dataPtr);
		//                    cv::imshow("GPU MAT", cv::Mat(dst));
		//

		NvMOTFrame motFrame;
		motFrame.streamID = 0;
		motFrame.frameNum = frameNum;
		motFrame.doTracking = true;
		motFrame.reset = false;
		motFrame.timeStamp = std::time(0);
		motFrame.timeStampValid = true;
		motFrame.numBuffers = 1;
		motFrame.bufferList = &surface->surfaceList;
		motFrame.objectsIn = objToTrackList;

		NvMOTProcessParams processParams;
		processParams.numFrames = 1;
		processParams.frameList = &motFrame;

		NvMOTTrackedObj trackedObj;
		trackedObj.associatedObjectIn = &objToTrack;
		trackedObj.bbox = objToTrack.bbox;

		NvMOTTrackedObjList trackedObjList;
		trackedObjList.streamID = 0;
		trackedObjList.numAllocated = 1;
		trackedObjList.numFilled = 0;
		trackedObjList.frameNum = frameNum;
		trackedObjList.valid = true;
		trackedObjList.list = &trackedObj;

		NvMOTTrackedObjBatch trackedObjBatch;
		trackedObjBatch.list = &trackedObjList;
		trackedObjBatch.numFilled = 1;
		trackedObjBatch.numAllocated = 1;

		auto status_process = NvMOT_Process(contextHandle, &processParams, &trackedObjBatch);
		if (status_process == NvMOTStatus_Error)
		{
			std::cout << "PROCESS STATUS ERROR" << std::endl;
		}
		else
		{
			std::cout << "PROCESS STATUS OK" << std::endl;
			std::cout << "CONF: " << trackedObj.confidence << std::endl;
		}

		frameNum++;
	}
}

User is free to use LL APIs but NVIDIA does not fix any issues arising from it.