¿Cómo leer un marco del archivo YUV en OpenCV?¿Cómo leer un marco del archivo YUV en OpenCV?
Respuesta
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.
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:
- escribir su propia función para consumir los datos de cabecera del objeto
FILE
antes de usar el código de abajo - 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;
}
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()
Como se ha mencionado, hay muchos tipos de formatos YUV:
para convertir a RGB de un formato YUV en OpenCV es muy simple:
- crear uno -Dimensional OpenCV Mat del tamaño apropiado para los datos de ese marco
- Cree un Mat vacío para los datos RGB con el d deseado IMENSIÓN Y con 3 canales
- 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.
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
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
- 1. YUV 422, YUV 420, YUV 444
- 2. Leer valores nulos del archivo
- 3. ¿Cómo leer el contenido del archivo desde un archivo?
- 4. Leer del archivo en Eclipse
- 5. Cómo omitir las filas no válidas al leer el marco de datos del archivo en R?
- 6. ¿Cómo leer un archivo del jar en Java?
- 7. Cómo leer un archivo pim.vol
- 8. ¿Cómo puedo leer desde una cadena XML en OpenCV?
- 9. OpenCV anexa el marco al archivo de video existente (.avi)?
- 10. ¿Cómo lidiar con RGB a YUV conversión
- 11. Captura de marco OpenCV de AVI
- 12. ¿Dónde puedo obtener un archivo YUV sin procesar?
- 13. ¿Cómo puedo leer los detalles del archivo?
- 14. leer archivo del almacenamiento externo
- 15. ¿Cómo escribir/leer un marco de datos de pandas con MultiIndex desde/hacia un archivo ASCII?
- 16. Leer del archivo, borrarlo, escribir en él
- 17. Cómo leer en un archivo txt
- 18. Cómo leer un archivo abierto en Ruby
- 19. Leer del archivo o stdin
- 20. ¿Cómo leer un CD como un archivo?
- 21. Java: leer un archivo en una matriz
- 22. Cómo conseguir el marco del archivo de vídeo en Android
- 23. Visualización de la imagen YUV en Android
- 24. ¿Cómo leer el contenido del archivo en istringstream?
- 25. ¿Cómo se pueden leer bytes del archivo en Python
- 26. ¿Cómo leer líneas del archivo mmap en python?
- 27. ¿Cómo leer un archivo .properties dentro de un archivo .xsl?
- 28. ¿Cómo leer un archivo de un archivo jar?
- 29. ¿Cómo leer una clave privada del archivo pvk en C#?
- 30. curl: leer los encabezados del archivo
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
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