Ask Your Question
0

CUDA::remap with shared-memory -> black output

asked 2020-02-06 01:20:51 -0500

MicTie gravatar image

updated 2020-02-10 05:38:50 -0500

I am trying to undistort images by using CUDA following the 'aged' (opencv2) approach from here. I managed to get all 3 approaches (CPU, CUDA w/o memory mapping, CUDA with memory mapping) running - so I assume my code is more or less ok. When I try to change the 3rd approach to color-output, all I get is a black-image.

   cv::Mat K = (cv::Mat_<float>(3,3) << 3.11260842e+03, 0.00000000e+00, 2.06650405e+03, 0.00000000e+00, 3.11421108e+03, 1.52851715e+03, 0.00000000e+00, 0.00000000e+00, 1.00000000e+00  );
cv::Mat D = (cv::Mat_<float>(5,1) << 1.07797852e-01, -2.83055545e-01, -3.52214618e-05, 3.60758721e-04, 2.30318706e-01);

    cv::Mat src_bgr = cv::imread("left01.jpg");
    cv::Mat map1, map2;
    cv::Mat Knew = (cv::Mat_<float>(3,3));
    Knew =  cv::getOptimalNewCameraMatrix(K, D, src_bgr.size() , 1, src_bgr.size());
    cv::initUndistortRectifyMap(K, D, cv::Mat::eye(3, 3, CV_32FC1), Knew, src_bgr.size(), CV_32FC1, map1, map2);

    cv::cuda::GpuMat gpu_map1, gpu_map2;
    gpu_map1.upload(map1);
    gpu_map2.upload(map2);

    enum    AllocType {  PAGE_LOCKED = 1,   SHARED = 2,  WRITE_COMBINED = 4 };
    cv::cuda::HostMem cudamem_src(src_bgr.size(), CV_8UC3, cv::cuda::HostMem::AllocType::SHARED );
    cv::cuda::HostMem cudamem_dst(src_bgr.size(), CV_8UC3, cv::cuda::HostMem::AllocType::SHARED);

    cv::cuda::GpuMat gpu_src = cudamem_src.createGpuMatHeader();
    cv::cuda::GpuMat gpu_dst = cudamem_dst.createGpuMatHeader();
    cv::Mat src = cudamem_src.createMatHeader();
    cv::Mat dst = cudamem_dst.createMatHeader();
    src = src_bgr;        
    // cv::cvtColor(src_bgr, src, cv::COLOR_BGR2GRAY);

    cv::cuda::remap(gpu_src, gpu_dst, gpu_map1, gpu_map2, cv::INTER_LINEAR);
    cv::imwrite("imgout.jpg", dst);

If I change AllocType::SHARED to AllocType::PAGE_LOCKED or WRITE_COMBINED I get a runtime error.

I completely inexperienced with C++ and using a Jetson Nano with Opencv4.2.0 installed.

Thank you for your kind help!

edit retag flag offensive close merge delete

Comments

I am not sure what you are trying to do? If you use AllocType::PAGE_LOCKED then the memory is not mapped to the GPU so I would expect the CUDA functions to fail? AllocType::PAGE_LOCKED is normally for host memory which you use to transfer from the device to, that is page_locked_mat = GPUMat.download().

cudawarped gravatar imagecudawarped ( 2020-02-06 12:42:52 -0500 )edit

Thanks for your reply! I want to use SHARED as it should be the fastest option, but the image I receive is black. So I wonder what I am doing wrong here.

If I set src to a grey-scale image by uncommenting // cv::cvtColor(src_bgr, src, cv::COLOR_BGR2GRAY);, I receive a gray-scale output. But it does not work by setting src to a color-image with src = src_bgr; - then I only get a black-output.

I am aware that in 'PAGE_LOCKED' mode I have to download the Gpu-data.

MicTie gravatar imageMicTie ( 2020-02-06 19:07:54 -0500 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2020-02-10 05:38:18 -0500

MicTie gravatar image

updated 2020-02-10 05:57:51 -0500

Here is how I solved the issue: Essentially, if I replace src = src_bgr; with src_bgr.copyTo(src); or gpu_src.upload(src_bgr); it's working.


    enum    AllocType {  PAGE_LOCKED = 1,   SHARED = 2,  WRITE_COMBINED = 4 };
    cv::cuda::HostMem cudamem_src(src_bgr.size(), CV_8UC3, cv::cuda::HostMem::AllocType::SHARED );
    cv::cuda::HostMem cudamem_dst(src_bgr.size(), CV_8UC3, cv::cuda::HostMem::AllocType::SHARED);

    cv::cuda::GpuMat gpu_src = cudamem_src.createGpuMatHeader();
    cv::cuda::GpuMat gpu_dst = cudamem_dst.createGpuMatHeader();
    cv::Mat src = cudamem_src.createMatHeader();
    cv::Mat dst = cudamem_dst.createMatHeader();

//    src_bgr.copyTo(src);
    gpu_src.upload(src_bgr);

    cv::cuda::remap(gpu_src, gpu_dst, gpu_map1, gpu_map2, cv::INTER_LINEAR);
    cv::imwrite("imgout.jpg", dst);

I wonder what's the difference between src = src_bgr; and src_bgr.copyTo(src);

edit flag offensive delete link more

Comments

The = operator in OpenCV is a soft-copy (just the mat header) while a copyTo is an hard-copy. Hard copy means that the entire data structure (Mat header+the data itself) is copied. In a soft copy with the operator = only the Mat header is copied while regarding the data it is make a reference. It is a common mistake, I broke my head for weeks with similar problems. Regarding the GPU things are a little bit different because of the different addressing of the memory, for that reason it is necessary do the upload method (that is a wrapper for cudaMalloc and cudaMemcpy) and eventually the download to retrieve the result.

HYPEREGO gravatar imageHYPEREGO ( 2020-06-19 10:19:09 -0500 )edit

Thank you for the clarifdication!

MicTie gravatar imageMicTie ( 2020-06-21 20:59:29 -0500 )edit
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2020-02-06 01:20:51 -0500

Seen: 271 times

Last updated: Feb 10