如何在OpenCV中从YUV文件读取帧?如何在OpenCV中从YUV文件读取帧?
回答
我不认为这是可能的,至少在目前的版本。当然,这样做并不难,但它不是那么有趣的功能,因为:
- OpenCV通常适用于RGB格式的网络摄像头流或编码文件,它们是直接解码为RGB以用于显示目的;
- OpenCV致力于计算机视觉,其中YUV是一种比在编码社区中不太常见的格式;
- 有很多不同的YUV格式,这意味着很多工作来实现它们。
尽管使用cvCvtColor()
,转换仍然是可能的,这意味着它仍然有一些利益。
UPDATE这里有代码的一个新版本:https://github.com/chelyaev/opencv-yuv
我张贴一些代码,会读一个单一 YUV 4:2:0平面图像文件。您可以直接将其应用于大多数YUV文件(只需继续读取相同的FILE
对象)。 例外这是当处理YUV files that have a header(通常,他们有一个*.y4m
扩展名)。如果要对付这样的文件,你有两个选择:
- 写自己的函数使用下面的代码
- 剥去* .y4m图像头之前消耗从
FILE
对象的报头数据(使用ffmpeg
或类似的工具)。这是我喜欢的选项,因为它是最简单的。
它也不适用于任何其他形式的YUV格式(非平面,不同的色度抽取)。正如@Stephane指出的,有很多这样的格式(其中大多数没有任何标识头),这可能是OpenCV不支持它们的原因。
但与他们的合作是相当简单:
- 开始用图像和它的尺寸
- 读取亮度和色度分为3个独立的图像
- 高档(该读YUV文件时需要)色度图像减少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;
}
我遇到同样的问题。我的解决方案是 1。读取一个yuv帧(如I420)到一个字符串对象“yuv”。 2.将yuv帧转换为BGR24格式。我使用libyuv来做到这一点。为libyuv函数编写python包装很容易。现在你得到另一个BGR24格式的字符串对象“bgr”。 3.使用numpy.fromstring从“bgr”字符串对象中获取图像对象。您需要更改图像对象的形状。
下面是一个简单的yuv查看器供您参考。
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()
如前所述,有许多类型的YUV格式:
要从OpenCV的YUV格式转换为RGB格式很简单:
- 创建一个用于该帧数据的适当尺寸的三维OpenCV Mat
- 用所需的d为RGB数据创建一个空Mat imension并用3个信道
- 最后使用cvtColor于两个垫之间进行转换,使用正确的转换标志枚举
这里是一个例子用于YUV缓冲在YV12格式:
Mat mYUV(height + height/2, width, CV_8UC1, (void*) frameData);
Mat mRGB(height, width, CV_8UC3);
cvtColor(mYUV, mRGB, CV_YUV2RGB_YV12, 3);
关键技巧是在您转换之前定义您的RGB垫的尺寸。
这是正确答案。 我正在处理YUV的NV12变化,这些帮助我了解了格式: https://wiki.videolan.org/YUV/#NV12,https://commons.wikimedia.org/wiki/File:Common_chroma_subsampling_ratios .SVG – rhardih 2016-10-11 13:05:05
我写了一个非常简单的python代码来读取二进制文件中的YUV NV21流。
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. 在opencv中读取YUV文件
- 2. 如何从YUV文件中提取帧?
- 3. 我如何从给定的yuv 4:2:0文件中提取yuv帧
- 4. 如何在OpenCV中逐帧读取视频文件?
- 5. 无法将YUV帧从ffmpeg写入.yuv文件
- 6. 如何从MPEG2 TS文件中提取原始YUV文件?
- 7. 如何YUV帧(从OTVideoFrame)转换为CVPixelBuffer
- 8. 如何从Android中的电影文件中读取每个帧?
- 9. 如何OpenCV的C++读取.xml文件
- 10. Gstreamer自定义插件从文件读取数据(YUV)?
- 11. 如何从Android中的文件读取OpenCV Mat对象?
- 12. 在OpenCV中读取YAML文件
- 13. 如何在matlab中读取y4m视频(获取帧)文件
- 14. 从文件夹(OpenCV)读取图像
- 15. 如何在OpenCV中读取Android中的AVI文件
- 16. 如何从视频MATLAB中读取帧?
- 17. YUV帧到CGContext
- 18. OpenCV Python - 读取pgm文件
- 19. 如何在OpenCv中读取不同格式的XML文件?
- 20. 从视频文件中抓取帧的最快方法OpenCV
- 21. 如何处理yuv文件
- 22. 如何从csv文件读取数据帧时设置列?
- 23. 从OpenCV中的VideoCapture读取每第n帧
- 24. 无法读取OpenCV中的AVI文件
- 25. OpenCV挂在读取(),抓取()等从文件
- 26. Android中的YUV帧缩放
- 27. 如何给YUV数据输入到Opencv?
- 28. 如何从文件中读取,然后继续从cin读取?
- 29. 如何获得YUV帧的分辨率
- 30. 如何将YUV帧转换为视频?
我现在有同样的问题,我试图打开并使用具有UYVY视频工作(4:2:2)编解码器,我想你的代码,但它没有工作,我知道,你在回答中提到过,但你能否说出原因?在此先感谢您的帮助 – Engine 2013-02-13 10:09:08
我发布的代码处理YUV 4:2:0。由于您的视频采用YUV 4:2:2格式,因此我的代码无法直接在您的视频上播放。您需要修改代码来处理您的格式。有关更多详细信息,请参阅:http://en.wikipedia.org/wiki/Chroma_subsampling#4:2:2 – misha 2013-02-14 04:21:46