4

这个问题是这个链接的下一步。

简而言之,我正在处理来自 kinect 的深度图像,该图像检索 16 位图像。使用 C++Amp,我们确实对数据的位大小有一些限制。所以,我正在尝试使用纹理来处理它。

现在,我确定我正在写入正确的像素。但是,从我的纹理原始数据中检索似乎存在一些问题。

那是代码:

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);
}

结果:

使用 gpu 复制后:

我还尝试使用 kinect 图像来查看会发生什么。结果让我吃惊:

原来的:

结果:

有谁知道发生了什么?

这就是我直接使用 16 位图像所做的修改(也许有帮助)

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

与往常一样,任何帮助都将不胜感激。如果您认为可以帮助我,请随时向我询问更多详细信息。

谢谢,大卫

4

1 回答 1

4

主要问题是您正在尝试访问非 32 位texture. 如果您通过调试器运行此代码,它实际上会抛出.set()指令。

MSDN 和 AMP 团队的博客都没有很好地解释这一点,但解决方案似乎是将输入纹理声明为包含const类型。我假设您使用的是 VS 2013,如果没有,请告诉我,我将发布 2012 年的代码。

这是整个程序。它的行为似乎符合我的预期。

#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;
}
于 2014-05-04T08:00:44.120 回答