image — Преобразование RGBA в формат YUV422 с использованием неправильного вывода

Я хочу преобразовать изображение из RGBA в YUV422 формат. Ниже мой код:

#include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace cv;
using namespace std;

#define CLIP(X) ( (X) > 255 ? 255 : (X) < 0 ? 0 : X)
#define RGB2Y(R, G, B) CLIP(( (  66 * (R) + 129 * (G) +  25 * (B) + 128) >> 8) +  16)
#define RGB2U(R, G, B) CLIP(( ( -38 * (R) -  74 * (G) + 112 * (B) + 128) >> 8) + 128)
#define RGB2V(R, G, B) CLIP(( ( 112 * (R) -  94 * (G) -  18 * (B) + 128) >> 8) + 128)

int main(int argc, char *argv[])
{

Mat in_img, in_RGB, out_yuv;
in_img = imread(argv[1],1);
if(!in_img.data)
{
printf("Failed to load the image ... %s\n!", argv[1]);
return -1;
}
short imgwidth  = in_img.cols;
short imgheight = in_img.rows;

cvtColor(in_img, in_RGB, CV_BGR2RGB);
out_yuv.create(imgheight, imgwidth, CV_16U);

imwrite("RGB.jpg",in_RGB);

for(int i = 0; i< imgheight; i++)
for(int j = 0; j< imgwidth; j = j+2) {
unsigned int val = in_RGB.at<unsigned int>(i,j);

/*********** for 1st pixel ***********/
unsigned int tmp = val;
unsigned char B = (unsigned char)(((tmp<<16) >> 24) | 0x000000ff ); //Extracting B channel data

tmp = val;
unsigned char G = (unsigned char)(((tmp<<8) >> 24) | 0x000000ff ); //Extracting G channel data

tmp = val;
unsigned char R = (unsigned char)((tmp >> 24) | 0x000000ff );  //Extracting R channel data

unsigned char Y1 = RGB2Y(R, G, B);
unsigned char U = RGB2U(R, G, B);
unsigned char V = RGB2V(R, G, B);

/*********** for 2nd pixel ***********/
unsigned int val1 = in_RGB.at<unsigned int>(i,j+1);
unsigned int tmp1 = val1;
unsigned char B1 = (unsigned char)(((tmp1<<16) >> 24) | 0x000000ff );

tmp1 = val1;
unsigned char G1 = (unsigned char)(((tmp1<<8) >> 24) | 0x000000ff );

tmp1 = val1;
unsigned char R1 = (unsigned char)((tmp1 >> 24) | 0x000000ff );

unsigned char Y2 = RGB2Y(R, G, B);

/********** writing into out image in U-Y1-V-Y2 format *********************/

unsigned short p1 = ((U << 8) | Y1) ;
unsigned short p2 = ((V << 8) | Y2) ;
out_yuv.at<unsigned short>(i,j) = p1;
out_yuv.at<unsigned short>(i,j+1) = p2;

}
imwrite("YUV422.png",out_yuv);
return 0;
}

Но я не получаю правильное изображение на выходе. Я также попытался записать его в формате Y1-U-Y2-V, все тот же вывод. Что может быть не так с приведенным выше кодом или это формат выходного изображения (.png / .jpg), который создает проблему? (cv :: imwrite не позволяет сохранять в формате .yuv)

1

Решение

out_yuv.create(imgheight, imgwidth, CV_16U);
...
imwrite("YUV422.png",out_yuv);

Несколько вопросов здесь:

  • imwrite считает CV_16U быть моноканалом.
  • Вы не можете написать yuv внутри png. Вы должны сбросить необработанные данные и использовать специальный просмотрщик yuv, такой как сырой ювплеер чтобы убедиться, что ваши данные верны.

Редактировать:
Обратите внимание, что аббревиатуры необработанных пикселей имеют вид порядка байтов, то есть самое левое значение — это наименее значимый байт в памяти (в большинстве случаев видео люди любят путаницу)

  • RGBA означает R = RGB[0], G = RGB[1], B = RGB[2], A = RGB[3]
  • YUYV значит в буфере p средства p[0] это Y0, p[1] это U, p[2] это Y1, p[3] это V

Вы делаете прямо противоположное со своими сменами 🙂

Редактировать 2:
Если ваше изображение все еще зашифровано, вы, кажется, готовы писать в следующем плоском формате (YUV422п акаYV16). Планарный формат означает, что каждый канал находится в отдельной смежной плоскости. Более понятно использовать простой старый буфер для целевых данных (unsigned char*, или же std::vector<unsigned char>).

unsigned char* out_yuv_ptr = new unsigned char[imgwidth*imgheight*2];
unsigned char* y_ptr = out_yuv_ptr;
unsigned char* u_ptr = y_ptr + imgwidth*imgheight;
unsigned char* v_ptr = u_ptr + imgwidth*imgheight/2;
...
*y_ptr = Y1;
++y_ptr
*y_ptr = Y2;
++y_ptr
*u_ptr = U;
++u_ptr;
*v_ptr = V;
++v_ptr;
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]