C++Amp Копирование 16-битного изображения из текстуры в текстуру (из OpenCV Mat)

Эта проблема является следующим шагом по этой ссылке.

Короче говоря, я работаю с изображениями глубины из 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);

Как всегда, любая помощь будет очень благодарна. Не стесняйтесь спрашивать меня о более подробной информации, если вы думаете, что могли бы помочь мне.

Спасибо Дэвид

1 ответ

Решение

Основная проблема заключается в том, что вы пытаетесь получить доступ не к 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;
}
Другие вопросы по тегам