ОБНОВЛЕНИЕ есть более новая версия кода здесь: https://github.com/chelyaev/opencv-yuv
Я публикую некоторый код, который будет читать одиночный YUV 4: 2: 0 файл планарного изображения. Вы можете напрямую применить это к большинству файлов YUV (просто продолжайте чтение с того же объекта FILE
). Исключение для этого имеет место при работе с YUV-файлами с заголовком (обычно они имеют расширение *.y4m
). Если вы хотите иметь дело с такими файлами, у вас есть два варианта:
- Напишите свою собственную функцию для использования данных заголовка из объекта
FILE
перед использованием кода ниже
- Удалите заголовки из изображений * .y4m (используя
ffmpeg
или аналогичный инструмент). Это вариант, который я предпочитаю, так как он самый простой.
Он также не будет работать для любой другой формы формата YUV (неплоский, различное прореживание цветности). Как отметил @Stephane, существует много таких форматов (и большинство из них не имеют идентифицирующих заголовков), поэтому, вероятно, OpenCV не поддерживает их «из коробки».
Но работать с ними довольно просто:
- Начните с изображения и его размеров (это необходимо при чтении файла YUV)
- Считывание яркости и цветности в 3 отдельных изображения
- Увеличение цветности изображения в 2 раза для компенсации прореживания цветности. Обратите внимание , что на самом деле существует несколько способов компенсации прореживания цветности. Апсэмплинг - это самое простое
- Объединить в изображение YUV. Если вы хотите RGB, вы можете использовать
cvCvtColor
.
Наконец, код:
IplImage *
cvLoadImageYUV(FILE *fin, int w, int h)
{
assert(fin);
IplImage *py = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
IplImage *pu = cvCreateImage(cvSize(w/2,h/2), IPL_DEPTH_8U, 1);
IplImage *pv = cvCreateImage(cvSize(w/2,h/2), IPL_DEPTH_8U, 1);
IplImage *pu_big = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
IplImage *pv_big = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 1);
IplImage *image = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, 3);
IplImage *result = NULL;
assert(py);
assert(pu);
assert(pv);
assert(pu_big);
assert(pv_big);
assert(image);
for (int i = 0; i < w*h; ++i)
{
int j = fgetc(fin);
if (j < 0)
goto cleanup;
py->imageData[i] = (unsigned char) j;
}
for (int i = 0; i < w*h/4; ++i)
{
int j = fgetc(fin);
if (j < 0)
goto cleanup;
pu->imageData[i] = (unsigned char) j;
}
for (int i = 0; i < w*h/4; ++i)
{
int j = fgetc(fin);
if (j < 0)
goto cleanup;
pv->imageData[i] = (unsigned char) j;
}
cvResize(pu, pu_big, CV_INTER_NN);
cvResize(pv, pv_big, CV_INTER_NN);
cvMerge(py, pu_big, pv_big, NULL, image);
result = image;
cleanup:
cvReleaseImage(&pu);
cvReleaseImage(&pv);
cvReleaseImage(&py);
cvReleaseImage(&pu_big);
cvReleaseImage(&pv_big);
if (result == NULL)
cvReleaseImage(&image);
return result;
}