python opencv rgb转yuv_如何使用python和openCV从.yuv视频文件(YUV420)中提取帧?

这篇博客介绍了如何在Python中使用OpenCV从.yuv视频文件中读取和处理帧,包括转换为灰度以及解决相关错误。作者通过示例代码展示了读取YUV420格式文件并转换为BGR和灰度图像的过程,同时也讨论了YUV的格式和范围问题。此外,还提供了使用FFmpeg将YUV文件转换为其他格式以获取元数据的方法。

我需要读取一个yuv视频文件,从中提取单个帧,将其转换为灰度,然后计算相邻帧之间的Lucas Kanade光学通量。我最初使用的是mp4视频,这是我提取单个帧的代码:

importcv2ascvimportnumpyasnp

cap=cv.VideoCapture('C:\\Users\\Ann Baiju\\Project\\video_tampering_dataset\\videos\\h264_lossless\\07_forged.mp4')ret,frame1=cap.read()prvs=cv.cvtColor(frame1,cv.COLOR_BGR2GRAY)height,width,_=frame1.shapewhile(1):ret,frame2=cap.read()ifret==False:breaknext=cv.cvtColor(frame2,cv.COLOR_BGR2GRAY)#Code for calculating Lucas Kanade optical flowN=N+1prvs=next

cap.release()

现在有些事情发生了变化,我必须使用yuv视频文件的数据集。但是,当我给VideoCapture()一个yuv文件时,出现如下错误:

[IMGUTILS @ 00000078a4bee5c0]图片大小0x0无效[ERROR:0]全局C:\ projects \ opencv-python \ opencv \ modules \ videoio \ src \ cap.cpp(116)cv :: VideoCapture :: open VIDEOIO(CV_IMAGES) :引发OpenCV异常:

OpenCV(4.1.2)C:\ projects \ opencv-python \ opencv \ modules \ videoio \ src \ cap_images.cpp:253:错误:(-5:错误的参数)CAP_IMAGES:找不到起始编号(在名称中的文件):函数“ cv :: icvExtractPattern”中的C:\ Users \ Ann Baiju \ Project \ Copy_Move_Datasets \ new original \ DERF \ hall.yuv

追溯(最近一次通话):文件“ test1.py”,第6行,在prvs = cv.cvtColor(frame1,cv.COLOR_BGR2GRAY)cv2.error:OpenCV(4.1.2)C:\ projects \ opencv-python \ opencv \ modules \ imgproc \ src \ color.cpp:182:错误:(-215:断言失败)!_src.empty()在函数'cv :: cvtColor'中

我该如何解决?我也知道yuv是原始视频文件格式,并且没有大小或fps信息。有什么方法可以从文件中推断出该信息,还是必须手动输入该信息?

关于我的问题,如何从yuv视频中获取帧大小信息(高度和宽度),是否可以使用FFmpeg将yuv视频转换为其他格式(例如mp4),从中获取信息,然后删除mp4视频,继续使用yuv视频吗?如果是这样,该怎么做?

importcv2importnumpyasnpimportosimportsubprocessassp

yuv_filename='can_0.yuv'#flow=[]width,height=320,240file_size=os.path.getsize(yuv_filename)n_frames=file_size//(width*height*3//2)f=open(yuv_filename,'rb')old_yuv=np.frombuffer(f.read(width*height*3//2),dtype=np.uint8).reshape((height*3//2,width))cv2.imshow('frame',old_yuv)cv2.waitKey(3000)# Convert YUV420 to Grayscaleold_gray=cv2.cvtColor(old_yuv,cv2.COLOR_YUV2GRAY_I420)cv2.imshow('frame_gs',old_gray)cv2.waitKey(3000)

当我运行上面的代码时,得到的yuv图像是:

对于yuv图像或某种分辨率问题,这正常吗?又为什么没有颜色?但是,当我将其转换为灰度时,它正常显示:

原始帧为(使用yuvplayer 2.5进行查看):

解决方案

没有单一的YUV420文件格式,但是有许多可能的像素顺序。

我创建了一个“自包含”代码示例,该示例演示了如何读取YUV420帧。

代码示例:

使用FFmpeg生成YUV420格式的合成视频。

要执行该示例,请下载(或安装)最新的稳定版本。

对于Windows操作系统,您可以将其放置ffmpeg.exe在与Python脚本相同的路径中。

逐帧读取YUV420,转换为BGR,然后显示每一帧。

您不需要颜色,但对于测试而言可能很重要。

将YUV420转换为灰度,并将每个帧显示为灰度。

FFmpeg以I420平面格式创建YUV:

YYYYYY

YYYYYY

YYYYYY

YYYYYY

UUU

UUU

VVV

VVV

YUV像素的范围是“有限范围”:

Y范围是[16,235]。

U和V范围是[16,240]。

这是代码:

importcv2importnumpyasnpimportosimportsubprocessassp# Build synthetic video and read binary data into memory (for testing):#########################################################################mp4_filename='input.mp4'# the mp4 is used just as referenceyuv_filename='input.yuv'width,height=640,480fps=1# 1Hz (just for testing)# Build synthetic video, for testing (the mp4 is used just as reference):sp.run('ffmpeg -y -f lavfi -i testsrc=size={}x{}:rate=1 -vcodec libx264 -crf 18 -t 10 {}'.format(width,height,mp4_filename))sp.run('ffmpeg -y -f lavfi -i testsrc=size={}x{}:rate=1 -pix_fmt yuv420p -t 10 {}'.format(width,height,yuv_filename))#########################################################################file_size=os.path.getsize(yuv_filename)# Number of frames: in YUV420 frame size in bytes is width*height*1.5n_frames=file_size//(width*height*3//2)# Open 'input.yuv' a binary file.f=open(yuv_filename,'rb')foriinrange(n_frames):# Read Y, U and V color channels and reshape to height*1.5 x width numpy arrayyuv=np.frombuffer(f.read(width*height*3//2),dtype=np.uint8).reshape((height*3//2,width))# Convert YUV420 to BGR (for testing), applies BT.601 "Limited Range" conversion.bgr=cv2.cvtColor(yuv,cv2.COLOR_YUV2BGR_I420)# Convert YUV420 to Grayscalegray=cv2.cvtColor(yuv,cv2.COLOR_YUV2GRAY_I420)#Show RGB image and Grayscale image for testingcv2.imshow('rgb',bgr)cv2.waitKey(500)# Wait a 0.5 second (for testing)cv2.imshow('gray',gray)cv2.waitKey(500)# Wait a 0.5 second (for testing)f.close()cv2.destroyAllWindows()

注意:

您的YUV420文件很有可能不是I420“有限范围”格式。

更新:

使用以下示例转换YUV420为未压缩的AVI的示例FFmpeg:

输入文件必须带有.yuv扩展名。

在命令行控制台中:

ffmpeg-y-s640x480-pixel_format yuv420p-i input.yuv-vcodec rawvideo-pix_fmt bgr24 input.avi

subprocess在Python中使用:

sp.run('ffmpeg -y -s {}x{} -pixel_format yuv420p -i input.yuv -vcodec rawvideo -pix_fmt bgr24 input.avi'.format(width,height))

未压缩的AVI视频文件将非常大(是YUV文件大小的两倍)。

如果视频质量不是最重要的,则可以使用H.264压缩(例如):

ffmpeg-y-s640x480-pixel_format yuv420p-i input.yuv-vcodec libx264-crf17-pix_fmt yuv420p input.mp4

该-crf 17参数使质量保持较高(几乎无损)。

注意:使用H.264编码时,文件格式.mp4或.avi不重要(但.mp4使用H.264编码时更常见)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值