C++Amp Copying an image of 16 bits from a texture to texture (from a openCV Mat)

StackOverflow https://stackoverflow.com/questions/23376701

  •  12-07-2023
  •  | 
  •  

سؤال

This issue is the next step from this one link.

In brief, I am working with depth images from a kinect which retrieve images of 16 bits. With C++Amp we do have some restrictions on the bit size of the data. So, I am trying to use textures to deal with it.

Now, I'm sure I am writing to the proper pixel. However, it seems there is some issue retrieving from my texture original data.

That's the code:

typedef concurrency::graphics::texture<unsigned int, 2> TextureData;
typedef concurrency::graphics::texture_view<unsigned int, 2> Texture;

cv::Mat image(480, 640, CV_16UC1);
cv::Mat image2(480, 640, CV_16UC1);

// create a gradient, just to see something meaningfull
for (int i = 0; i < 480; i++)
{
    for (int j = 0; j < 640; j++)
    {
        /*int gradientInY = (i / 480.f) * 65535;
        image.at<uint16_t>(i, j) = gradientInY;*/

        int gradientInX = (j / 640.f) * 65535;
        image.at<uint16_t>(i, j) = gradientInX;
        image2.at<uint16_t>(i, j) = gradientInX;
    }
}


cv::imshow("image", image);
cv::waitKey(50);

concurrency::extent<2> imageSize(480, 640);
int bits = 16;

const unsigned int nBytes = imageSize.size() * 2; // 614400


{
    uchar* data = image.data;

    // Source Data
    TextureData texDataS(imageSize, data, nBytes, bits);
    Texture texS(texDataS);

    // Result data
    TextureData texDataD(imageSize, bits);
    Texture texR(texDataD);


    parallel_for_each(
        imageSize,
        [=, &texDataS](concurrency::index<2> idx) restrict(amp)
    {
        //I tried either this:
        int val = texDataS(idx);

        // and this:
        //int val = texS(idx);
        texR.set(idx, val);
    });
    //concurrency::graphics::copy(texR, image2.data, imageSize.size() *(bits / 8u));
    concurrency::graphics::copy_async(texR, image2.data, imageSize.size() *(bits / 8u) );

    cv::imshow("result", image2);
    cv::waitKey(50);
}

And the results:

And after copy using gpu:

I also tried to use a kinect image to see what happen. The result surprises me:

Original:

Result:

Anyone know what's going on?

That's the modification I did to work with a image of 16 bits directly (maybe it's helpful)

cv::Mat image = cv::imread("Depth247.tiff", CV_LOAD_IMAGE_ANYDEPTH);
cv::Mat image2(480, 640, CV_16UC1);

As always, any help will be very gratefully. Do not hesitate to ask me for more details if you think you could help me.

Thanks, David

هل كانت مفيدة؟

المحلول

The main issue is that your are trying to access a non-32 bit texture. If you run this code through the debugger it actually throws on the .set() instruction.

Neither MSDN not the AMP team's blog explain this very well but the solution appears to be to declare the input texture as containing a const type. I'm assuming you're using VS 2013, if not then let me know and I'll post the code for 2012.

Here's the whole program. it appears to behave as expected for me.

#include "opencv2/highgui/highgui.hpp"
#include <amp.h>
#include <amp_graphics.h>
#include <amp_short_vectors.h>

using namespace concurrency;
using namespace std;

int main( int argc, const char** argv )
{
    cv::Mat image(480, 640, CV_16UC1);
    cv::Mat image2(480, 640, CV_16UC1);

    // create a gradient, just to see something meaningful
    for (int i = 0; i < 480; i++)
    {
        for (int j = 0; j < 640; j++)
        {
            /*int gradientInY = (i / 480.f) * 65535;
            image.at<uint16_t>(i, j) = gradientInY;*/

            int gradientInX = (j / 640.f) * (i / 480.f) * 65535;
            image.at<uint16_t>(i, j) = gradientInX;
            image2.at<uint16_t>(i, j) = 65535 / 2;
        }
    }

    cv::imshow("image", image);
    cv::waitKey(50);

    concurrency::extent<2> imageSize(480, 640);
    int bits = 16;

    const unsigned int nBytes = imageSize.size() * bits / 8; // 614400

    // Source Data
    graphics::texture<unsigned int, 2> texDataS(imageSize, image.data, nBytes, bits);
    graphics::texture_view<const unsigned int, 2> texS(texDataS);

    // Result data
    graphics::texture<unsigned int, 2> texDataD(imageSize, 16);
    graphics::texture_view<unsigned int, 2> texD(texDataD);

    parallel_for_each(imageSize, [=, &texDataS](concurrency::index<2> idx) restrict(amp)
    {
        int val = texS(idx);

        // Do your image processing work here.
        int result = val;

        texD.set(idx, result);
    });

    // Don't copy async here as you need the result immediately.
    concurrency::graphics::copy(texDataD, image2.data, imageSize.size() * bits / 8);

    cv::imshow("result", image2);
    cv::waitKey(50);

    return 0;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top