Я использую openCV C ++ API и пытаюсь преобразовать буфер камеры (YUV_NV12) в формат RGB. Однако размеры моего изображения изменились (ширина уменьшилась с 720 до 480), и цвета неправильные (вроде фиолетового / зеленого цвета).
unsigned char* myYUVBufferPointer = (something passed as argument)
int myYUVBufferHeight = 1280
int myYUVBufferWidth = 720
cv::Mat yuvMat(myYUVBufferHeight, myYUVBufferWidth, CV_8U, myYUVBufferPointer);
cv::Mat rgbMat;
cv::cvtColor(yuvMat, rgbMat, CV_YUV2RGB_NV12);
cv::imwrite("path/to/my/image.jpg",rgbMat);
Есть идеи? * (Меня больше интересует размер, измененный, чем цвет, так как я в конечном итоге преобразую его в CV_YUV2GRAY_NV12, и это работает, но размер — нет). *
Ваш код создает одноканальное (в градациях серого) изображение, называемое yuvMat
из серии unsigned char
s. Когда вы пытаетесь — принудительно — преобразовать одноканальное изображение из YUV 4: 2: 0 в многоканальный RGB, библиотека OpenCV предполагает, что в каждой строке содержится 2/3 полной информации 4: 4: 4 (1 x height x width
за Y
а также 1/2 height x width
за U
а также V
каждый вместо 3 x height x width
для нормального YUV
) поэтому ваша ширина конечного изображения уменьшается до 2/3 от первоначальной ширины. Можно предположить, что половина данных, считанных с исходного изображения, поступает из нераспределенной памяти, хотя исходное изображение имеет только width x height uchar
но 2 x width x height uchar
с читаются из памяти!
Если твой uchar
буфер уже правильно отформатирован для серии байтов, представляющих YUV_NV12 (4: 2: 0 субсэмплинг) в обычном width x height
байт на канал, все, что вам нужно сделать, это создать свой оригинальный yuvMat
как CV_8UC3
и ты в порядке. Выше предполагается, что все чередование и позиционирование канала уже реализованы в буфере. Скорее всего, это не так. YUV_NV12 данные приходят с width x height uchar
с Y
, с последующим (1/2) width x (1/2) x height of 2 x uchar
с представляет UV
вместе взятые. Вы, вероятно, должны написать свой собственный читатель, чтобы прочитать Y
, U
, а также V
данные отдельно и построить 3 одноканальных Mat
с размером width x height
— заполнение горизонтальных и вертикальных пробелов в обоих U
а также V
каналы — тогда используйте cv::merge()
объединить эти одноканальные изображения в 3-канальный YUV
Перед использованием cv::cvtColor()
конвертировать это изображение с помощью CV_YUV2BGR
вариант. Обратите внимание на использование BGR
вместо RGB
,
Возможно, что «что-то передано в качестве аргумента» не имеет достаточно данных для заполнения 720 строк. В некоторых видеокамерах не все три канала представлены с одинаковым количеством битов. Например, при захвате видео на iPhone три канала используют 8-4-4 байта вместо 8-8-8. Я не использовал этот тип камеры с OpenCV, но, скорее всего, проблема здесь.