Проблема с преобразованием изображения unsigned char * в OpenCV Mat

У меня проблема с синтаксическим анализом данных изображения из фреймграббера в формат OpenCV Mat. Я могу получить данные изображения из моего фреймграббера EDT в виде беззнакового указателя char и передать его во вновь созданный Mat, но я теряю ценные данные в процессе и не знаю, как это исправить.

Моя камера - это инфракрасная камера, которая выводит 12-битное изображение Байера 320x256. Я вполне уверен, что использую API EDT правильно. Используя программное обеспечение EDT, «pdvshow», я могу просматривать данные изображения, как и ожидалось, но когда я конвертирую возвращенный кадр из API EDT в мат OpenCV и отображаю его, я теряю значительный объем данных. Когда у меня мат установлен на CV16UC1, рамка почти черная, когда мат установлен на CV8UC1, рамка отображает большую часть данных, но выглядит очень зернистой, а некоторые пятна полностью размыты. Я знаю, что фрейм-граббер хранит каждый 12-битный пиксель в двух байтах, и данные соответствуют MSB. GetStride возвращает 0.

unsigned char *pdvImage;
pdvImage = pdv_image(pdv_p); 

cv::Mat freshFrame;
freshFrame = cv::Mat(GetHeight(), GetWidth(), CV_16UC1, pdvImage, GetStride()); //was CV_16UC1 but 8UC1 shows more data

return freshFrame.clone();

person user2640018    schedule 04.10.2013    source источник


Ответы (2)


Я написал код, который рисует изображение char *, а затем преобразует его в OpenCV Mat:

const int WIDTH = 800, HEIGHT = 600;

uchar *data = new uchar[WIDTH * HEIGHT * 3];

for (int i = 0; i < WIDTH*HEIGHT*3;i+=3)
{
    if (i < WIDTH*HEIGHT*3/2)
    {
        data[i + 0] = (uchar)0;
        data[i + 1] = (uchar)0;
        data[i + 2] = (uchar)255;
    }
    else
    {
        data[i + 0] = (uchar)255;
        data[i + 1] = (uchar)0;
        data[i + 2] = (uchar)0;
    }
}

cout << "May God be pleased with you, amen!\n";

Mat colorfrm = Mat(HEIGHT, WIDTH, CV_8UC3);
colorfrm.data = data;

while (1)
{
    imshow("Original Image", colorfrm);

    /////////

    int c = cvWaitKey(30);
    if (c == ' ')
    {
        break;
    }
    if (c == 'q' || c == 'Q' || c == 27)
    {
        return 0;
    }
}

Надеюсь, это поможет!

person Hasan Zakaria Alhajhamad    schedule 17.10.2014

Когда вы создаете freshFrame как циновку CV_16UC1, 12 бит данных находятся в младших битах. Масштабирование данных решит проблему, когда результирующее изображение будет слишком черным. Так что вместо

return freshFrame.clone();

тебе нужно

return freshFrame * 16;

Вам также может потребоваться проверить порядок байтов двух байтов для каждого пикселя в pdvImage.

По поводу CV_8UC1 это не сработает

freshFrame = cv::Mat(GetHeight(), GetWidth(), CV_8UC1, pdvImage, GetStride()); 

потому что первые два байта pdvImage составляют значение первого пикселя изображения, но становятся двумя отдельными пикселями в freshFrame. Однако, если вы создаете freshFrame, как в приведенной выше строке, первый байт становится значением для первого пикселя в freshFrame, а второй байт становится значением для второго пикселя и так далее. Очевидно, это неправильно. Если вам действительно нужен коврик CV_8UC1, проще всего будет создать коврик CV_16UC1, а затем преобразовать его.

person Bull    schedule 04.10.2013