This section demonstrates matchFrames function implementation in NVX CUDA API.
The first step is to create necessary data objects:
Arrays for corners.
*ref_features = createArrayKeyPoint(1000u);
*cur_features = createArrayKeyPoint(1000u);
CUDA device pointer for the total number of detections.
uint32_t *num_corners_dev_ptr = NULL;
cudaMalloc((void **)&num_corners_dev_ptr, sizeof(uint32_t));
Pyramid objects.
const uint32_t num_levels = 3;
Execution target (CUDA stream and CUDA device properties).
cudaStreamCreate(&exec_target.
stream);
cudaGetDeviceProperties(&exec_target.
dev_prop, 0);
The second step is to preallocate temporary buffers that are needed for primitives:
Gets the required buffer size from all used primitives.
3.0f ,
3 ,
3 ,
&border,
&border,
6u ,
0 ,
&border,
Calculates total size of temporary buffers and allocates them.
The third step is to call primitives.
Harris corner detector.
0.00004f ,
3.0f ,
0.04f ,
3 ,
3 ,
&ref_features->base,
num_corners_dev_ptr,
&tmp_buf,
&border,
Gaussian pyramids. Note that pyramids are built from the first level, so the code copies input images to the first level of the corresponding pydamid.
ref_image->
planes[0].dev_ptr, ref_image->
planes[0].pitch_in_bytes,
ref_image->
base.
width *
sizeof(uint8_t), ref_image->base.height,
cudaMemcpyDeviceToDevice,
&tmp_buf,
&border,
cur_image->
planes[0].dev_ptr, cur_image->
planes[0].pitch_in_bytes,
cur_image->
base.
width *
sizeof(uint8_t), cur_image->base.height,
cudaMemcpyDeviceToDevice,
&tmp_buf,
&border,
Optical flow. Note that the cur_features parameter must be initialized with initial estimation. Points from the first image (ref_features) are used.
cudaMemcpyAsync(cur_features->dev_ptr, ref_features->dev_ptr,
cudaMemcpyDeviceToDevice,
cudaMemcpyAsync(cur_features->num_items_dev_ptr, ref_features->num_items_dev_ptr,
sizeof(uint32_t),
cudaMemcpyDeviceToDevice,
&ref_features->base,
&cur_features->base,
0.01f ,
30 ,
6u ,
0 ,
&tmp_buf,
&border,
Synchronize with CUDA stream to be sure that all pending operations are finished.
cudaStreamSynchronize(exec_target.
stream);
The last step is to clean up all the temporarily allocated buffers and data objects:
cudaFree(num_corners_dev_ptr);
for (uint32_t i = 0; i < num_levels; ++i)
{
}
cudaStreamDestroy(exec_target.
stream);
The full code of the matchFrames function:
{
*ref_features = createArrayKeyPoint(1000u);
*cur_features = createArrayKeyPoint(1000u);
uint32_t *num_corners_dev_ptr = NULL;
cudaMalloc((void **)&num_corners_dev_ptr, sizeof(uint32_t));
const uint32_t num_levels = 3;
cudaStreamCreate(&exec_target.
stream);
cudaGetDeviceProperties(&exec_target.
dev_prop, 0);
3.0f ,
3 ,
3 ,
&border,
&border,
6u ,
0 ,
&border,
{
}
{
}
0.00004f ,
3.0f ,
0.04f ,
3 ,
3 ,
num_corners_dev_ptr,
&tmp_buf,
&border,
ref_image->
planes[0].dev_ptr, ref_image->
planes[0].pitch_in_bytes,
cudaMemcpyDeviceToDevice,
&tmp_buf,
&border,
cur_image->
planes[0].dev_ptr, cur_image->
planes[0].pitch_in_bytes,
cudaMemcpyDeviceToDevice,
&tmp_buf,
&border,
cudaMemcpyDeviceToDevice,
sizeof(uint32_t),
cudaMemcpyDeviceToDevice,
0.01f ,
30 ,
6u ,
0 ,
&tmp_buf,
&border,
cudaStreamSynchronize(exec_target.
stream);
cudaFree(num_corners_dev_ptr);
for (uint32_t i = 0; i < num_levels; ++i)
{
}
cudaStreamDestroy(exec_target.
stream);
}