I need to read a yuv video file, extract individual frames from it, convert it to grayscale and then calculate Lucas Kanade optical flow between adjacent frames. I was initially using mp4 videos and this was my code for extracting individual frames:
import cv2 as cv
import numpy as np
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.shape
while(1):
ret, frame2 = cap.read()
if ret==False: break
next = cv.cvtColor(frame2, cv.COLOR_BGR2GRAY)
#Code for calculating Lucas Kanade optical flow
N=N+1
prvs = next
cap.release()
Now some things changed and I have to use a dataset of yuv video files. But when I give a yuv file to VideoCapture() I'm getting error as follows:
[IMGUTILS @ 00000078a4bee5c0] Picture size 0x0 is invalid [ERROR:0] global C:\projects\opencv-python\opencv\modules\videoio\src\cap.cpp (116) cv::VideoCapture::open VIDEOIO(CV_IMAGES): raised OpenCV exception:
OpenCV(4.1.2) C:\projects\opencv-python\opencv\modules\videoio\src\cap_images.cpp:253: error: (-5:Bad argument) CAP_IMAGES: can't find starting number (in the name of file): C:\Users\Ann Baiju\Project\Copy_Move_Datasets\new original\DERF\hall.yuv in function 'cv::icvExtractPattern'
Traceback (most recent call last): File "test1.py", line 6, in prvs = cv.cvtColor(frame1, cv.COLOR_BGR2GRAY) cv2.error: OpenCV(4.1.2) C:\projects\opencv-python\opencv\modules\imgproc\src\color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cv::cvtColor'
How do I solve this? Also I understand yuv is a raw video file format and does not have size or fps information in it. Is there some way it can be inferred from the file or do I have to manually input that information?
Regarding my question as to how to get frame size information (height and width) from yuv video is it possible to convert the yuv video to some other format (say mp4) using FFmpeg, obtain the information from it and then delete the mp4 video and continue to work with the yuv video? If so how to do that?
import cv2
import numpy as np
import os
import subprocess as sp
yuv_filename = 'can_0.yuv'
#flow=[]
width, height = 320, 240
file_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 Grayscale
old_gray = cv2.cvtColor(old_yuv, cv2.COLOR_YUV2GRAY_I420)
cv2.imshow('frame_gs',old_gray)
cv2.waitKey(3000)
When I run the above code, the yuv image I get is:
Is that normal for a yuv image or some kind of resolution problem? Also why is there no color? When I convert it to grayscale however, it comes out normal:
The original frame is (as viewed using yuvplayer 2.5):