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