2010-02-09 17 views

Respuesta

0

No creo que sea posible, al menos con la versión actual. Por supuesto, no sería tan difícil de hacer, pero no es una característica muy interesante, ya que:

  • OpenCV por lo general trabaja en funcionamiento de cámaras, que están en formato RGB, o en archivos codificados, que son decodificado directamente en RGB para fines de visualización;
  • OpenCV está dedicado a Computer Vision, donde YUV es un formato menos común que en la comunidad de codificación, por ejemplo;
  • hay muchos formatos YUV diferentes, lo que implicaría mucho trabajo para implementarlos.

Las conversiones aún son posibles, usando cvCvtColor(), lo que significa que es de algún interés.

3

ACTUALIZACIÓN hay una versión más reciente del código aquí: https://github.com/chelyaev/opencv-yuv

les dejo algo de código que leerá un YUV 4 sola: 2: 0 archivo de imagen planar. Puede aplicar esto directamente a la mayoría de los archivos YUV (simplemente siga leyendo desde el mismo objeto FILE). La excepción a esto es cuando se trata de YUV files that have a header (por lo general, tienen una extensión *.y4m). Si usted quiere tratar con este tipo de archivos, usted tiene dos opciones:

  1. escribir su propia función para consumir los datos de cabecera del objeto FILE antes de usar el código de abajo
  2. de Gaza las cabeceras de imágenes * .y4m (usando ffmpeg o herramienta similar). Esta es la opción que prefiero, ya que es la más simple.

Tampoco funcionará para ninguna otra forma de formato YUV (no planar, diferente decimación de crominancia). Como señaló @Stephane, existen muchos de estos formatos (y la mayoría de ellos no tienen ningún encabezado de identificación), que es probablemente la razón por la que OpenCV no los admite de inmediato.

Pero trabajar con ellos es bastante simple:

  • de inicio con una imagen y sus dimensiones (esto es necesario cuando se lee un archivo YUV)
  • Leer luma y croma en 3 imágenes separadas
  • exclusivo imágenes de croma por un factor de 2 a la compensación por la decimación de crominancia. Nota que en realidad hay varias formas de compensar la decimación de crominancia. Upsampling es simplemente el más simple
  • Combine en la imagen YUV. Si desea RGB, puede usar cvCvtColor.

Por último, el código:

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

que tienen el mismo problema ahora, estoy tratando de abrir y trabajar con un vídeo que tiene UYVY (4: 2: 2) como códec, he intentado que el código, pero no funcionó Sé que Mencionaste eso en tu respuesta, pero ¿puedes decir por qué? gracias de antemano por su ayuda – Engine

+1

El código que publiqué maneja YUV 4: 2: 0. Como tu video está en YUV 4: 2: 2, entonces mi código definitivamente no funcionará en tu video directamente. Tendrá que adaptar el código para manejar su formato. Para obtener más información, consulte: http://en.wikipedia.org/wiki/Chroma_subsampling#4:2:2 – misha

0

me encontré con el mismo problema. Mi solución es 1.lea un marco yuv (como I420) a un objeto de cadena "yuv". 2. convierta el marco yuv al formato BGR24. Yo uso libyuv para hacerlo. Es fácil escribir un contenedor de Python para las funciones de libyuv. ahora obtienes otro objeto de cadena "bgr" con formato BGR24. 3. usa numpy.fromstring para obtener el objeto de imagen del objeto de cadena "bgr". necesitas cambiar la forma del objeto de la imagen.

A continuación se muestra un visor yuv simple para su referencia.

import cv2 
# below is the extension wrapper for libyuv 
import yuvtorgb 
import numpy as np 

f = open('i420_cif.yuv', 'rb') 

w = 352 
h = 288 
size = 352*288*3/2 

while True: 
    try: 
     yuv = f.read(size) 
    except: 
     break 
    if len(yuv) != size: 
     f.seek(0, 0) 
     continue 

    bgr = yuvtorgb.i420_to_bgr24(yuv, w, h) 

    img = np.fromstring(bgr, dtype=np.uint8) 
    img.shape = h,w,3 

    cv2.imshow('img', img) 

    if cv2.waitKey(50) & 0xFF == ord('q'): 
     break 

cv2.destroyAllWindows() 
4

Como se ha mencionado, hay muchos tipos de formatos YUV:

http://www.fourcc.org/yuv.php

para convertir a RGB de un formato YUV en OpenCV es muy simple:

  1. crear uno -Dimensional OpenCV Mat del tamaño apropiado para los datos de ese marco
  2. Cree un Mat vacío para los datos RGB con el d deseado IMENSIÓN Y con 3 canales
  3. Finalmente utilizar cvtColor para convertir entre los dos Mats, usando la conversión correcta bandera enum

Aquí está un ejemplo de un tampón de YUV en YV12 formato:

Mat mYUV(height + height/2, width, CV_8UC1, (void*) frameData); 
Mat mRGB(height, width, CV_8UC3); 
cvtColor(mYUV, mRGB, CV_YUV2RGB_YV12, 3); 

El truco clave es definir las dimensiones de su tapete RGB antes de que convierta.

+0

Esta es la respuesta correcta. Estaba manejando la variación NV12 de YUV y esto me ayudó a entender el formato: https://wiki.videolan.org/YUV/#NV12, https://commons.wikimedia.org/wiki/File:Common_chroma_subsampling_ratios .svg – rhardih

2

Escribí un código python muy simple para leer la secuencia YUV NV21 desde un archivo binario.

import cv2 
import numpy as np 

class VideoCaptureYUV: 
    def __init__(self, filename, size): 
     self.height, self.width = size 
     self.frame_len = self.width * self.height * 3/2 
     self.f = open(filename, 'rb') 
     self.shape = (int(self.height*1.5), self.width) 

    def read_raw(self): 
     try: 
      raw = self.f.read(self.frame_len) 
      yuv = np.frombuffer(raw, dtype=np.uint8) 
      yuv = yuv.reshape(self.shape) 
     except Exception as e: 
      print str(e) 
      return False, None 
     return True, yuv 

    def read(self): 
     ret, yuv = self.read_raw() 
     if not ret: 
      return ret, yuv 
     bgr = cv2.cvtColor(yuv, cv2.COLOR_YUV2BGR_NV21) 
     return ret, bgr 


if __name__ == "__main__": 
    #filename = "data/20171214180916RGB.yuv" 
    filename = "data/20171214180916IR.yuv" 
    size = (480, 640) 
    cap = VideoCaptureYUV(filename, size) 

    while 1: 
     ret, frame = cap.read() 
     if ret: 
      cv2.imshow("frame", frame) 
      cv2.waitKey(30) 
     else: 
      break 
Cuestiones relacionadas