I am performing a 4-point perspective transform using OpenCV functions, but would like to use NPP to perform the same thing. This is similar to trying to create a “birdseye” view projection from 4 points in the image. After trying what I thought were the right functions, nothing seems to work.
Input to my function:
- an 8U 3C image
- 4 points within the image that define a quadrangle, which is likely not a square or rectangle.
- output rectangle size
Desired output:
An image, the size of “output rectangle” that is built from the projected pixels within the defined quadrangle.
This is easily done in OpenCV with a combination of cv::getPerspectiveTransform to get the transformation matrix, followed by cv::warpPerspective to create the output image.
When first looking at the NPP docs, I thought that there would be a similar process: find the transform matrix and then apply the transform. I couldn’t find an example for performing the perspective transform, so here’s basically what I did:
void NPP_Util::warpImage(int width, int height, uint8_t* h_data, double roiCorners[4][2],
int targetWidth, int targetHeight, uint8_t* targetData)
{
uint8_t *d_data, *d_dest;
size_t imageSize = width * height * 3; // this is the input image size
size_t targetSize = targetWidth * targetHeight * 3; // this is the output image size
// move input image to gpu
cudaMalloc(&d_data, imageSize);
cudaMemcpy(d_data,h_data, imageSize,cudaMemcpyHostToDevice);
// allocate for output image
cudaMalloc(&d_dest, targetSize);
// define size of output image ????
NppiRect roiRect;
roiRect.x = 0;
roiRect.y = 0;
roiRect.width = width;
roiRect.height = height;
// calc perspective transformation matrix
double T[3][3];
NppStatus status = nppiGetPerspectiveTransform(roiRect, d_roiCorners, T);
// declare a host image object for an 8-bit, 3 channel color image
npp::ImageCPU_8u_C3 oHostSrc;
NppiSize oSrcSize;
oSrcSize.width = width;
oSrcSize.height = height;
NppiRect oSrcROI;
oSrcROI.x = 0; oSrcROI.y = 0; oSrcROI.width = width; oSrcROI.height = height;
NppiRect oDstROI;
oDstROI.x = 0; oDstROI.y = 0; oDstROI.width = targetWidth; oDstROI.height = targetHeight;
// perform perspective transformation onto output image ... should this be backwards transform??
nppiWarpPerspective_8u_C3R (h_data, oSrcSize, width*3, oSrcROI,
d_dest, targetWidth*3, oDstROI, T, NPPI_INTER_LINEAR);
// copy output image to cpu buffer
cudaMemcpy(targetData, d_data, targetSize, cudaMemcpyDeviceToHost);
// clean up
cudaFree(d_data);
cudaFree(d_dest);
}
The output image is unrecognizable. I suspect that I’m not setting the function input parameters correctly, or I should be performing a “backwards” transform, or I’m trying to use functions that are not meant to do this.
Any suggestions would be greatly appreciated.
Thanks,
Bryan