简体   繁体   English

将 RGB 视频转换为灰度视频以减小文件大小

[英]Convert RGB Video to Gray Scale video for file size reduction

I am creating Color Video(RGB) using OpenCV in my application and generated video file needs to be uploaded to server.我正在我的应用程序中使用 OpenCV 创建彩色视频(RGB),生成的视频文件需要上传到服务器。 Color video file size is large enough to create bottleneck while uploading to server in the current bandwidth available.彩色视频文件大小足以在当前可用带宽下上传到服务器时产生瓶颈。 So, i tried to reduce the file size by converting it to grayscale video in the opencv.因此,我尝试通过将其转换为 opencv 中的灰度视频来减小文件大小。 Please find below the OpenCV implementation of my current work:请在下面找到我当前工作的 OpenCV 实现:

cap = cv2.VideoCapture(RGB_video_filepath)
    fps = cap.get(cv2.CAP_PROP_FPS)
    print("Input Video FPS: ".format(fps))
    outputfilepath = "gray_video_output.avi"

    mjpg_forcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')
    divx_forcc = cv2.VideoWriter_fourcc(*'DIVX')
    xvid_forcc = cv2.VideoWriter_fourcc(*'XVID')
    fmpp4_codec = cv2.VideoWriter_fourcc('F','M','P','4')
    mp4v_codec = cv2.VideoWriter_fourcc(*'MP4V')
    vid_writer = cv2.VideoWriter(outputfilepath, mjpg_codec, 2, (640, 480), 0)

    while cv2.waitKey(1) < 0:
        # get frame from the video
        hasFrame, frame = cap.read()


        # Stop the program if reached end of video
        if not hasFrame:
            print("Done processing !!!")
            print("Output file is stored as ", outputfilepath)
            break

        gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        vid_writer.write(gray_frame)
        print("Frame shape: {} {}".format(frame_count, frame.shape))
        cv2.imshow("Camera frame", frame)
        cv2.waitKey(1)

    print("Total frames: {}".format(frame_count))
    vid_writer.release()
    cap.release()

Using above workflow, i created the GRAY scale video, but i found that video file sizes are almost same (RGB video file size : 25 MB, Gray scale video size: 23 MB).使用上述工作流程,我创建了灰度视频,但我发现视频文件大小几乎相同(RGB 视频文件大小:25 MB,灰度视频大小:23 MB)。

After digging into OpenCV, i found that OpenCV copies the grayscale(single channel) frame 3 times and writes into video as 3 channel although OpenCV uses FFMPEG for video file writing on Linux based OS.在深入研究 OpenCV 后,我发现 OpenCV 将灰度(单通道)帧复制了 3 次,并作为 3 通道写入视频,尽管 OpenCV 使用 FFMPEG 在基于 Linux 的操作系统上写入视频文件。

I tried to convert the same RGB video file to Grayscale video file using FFMPEG as below:我尝试使用 FFMPEG将相同的RGB 视频文件转换为灰度视频文件,如下所示:

ffmpeg -i inputvideofile -vf hue=s=0 outputvideofile

Here, i kept the Hue and saturation channel to be empty and surprisingly RGB video file(25 MB) gets converted to gray scale with file size reduced to 6 MB.在这里,我保持色相和饱和度通道为空,令人惊讶的是RGB 视频文件(25 MB)被转换为灰度,文件大小减少到 6 MB。

**I am curious to know if we can achieve the video file size reduction by converting RGB to Gray scale using OpenCV on the fly? **我很想知道我们是否可以通过使用 OpenCV 即时将 RGB 转换为灰度来实现视频文件大小的减小? ** **

Any help/update is appreciated.任何帮助/更新表示赞赏。 Thanks!!谢谢!!

OpenCV uses FFMPEG. OpenCV 使用 FFMPEG。 Try below code to save numpy array of each frame as video using ffmpeg-python and compare the size.尝试使用以下代码使用 ffmpeg-python 将每帧的 numpy 数组保存为视频并比较大小。

import numpy as np
import cv2
import ffmpeg

def save_video(cap,saving_file_name,fps=33.0):

    if cap.isOpened():
        ret, frame = cap.read()
        if ret:
            i_width,i_height = frame.shape[1],frame.shape[0]

    process = (
    ffmpeg
        .input('pipe:',format='rawvideo', pix_fmt='rgb24',s='{}x{}'.format(i_width,i_height))
        .output(saved_video_file_name,pix_fmt='yuv420p',vcodec='libx264',r=fps,crf=37)
        .overwrite_output()
        .run_async(pipe_stdin=True)
    )

    return process

if __name__=='__main__':

    cap = cv2.VideoCapture(0,cv2.CAP_DSHOW)
    cap.set(3,1920)
    cap.set(4,1080)
    saved_video_file_name = 'output.avi'
    process = save_video(cap,saved_video_file_name)

    while(cap.isOpened()):
        ret, frame = cap.read()
        if ret==True:
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # Convert frame/img to gray
            frame = cv2.flip(frame,0)
            process.stdin.write(
                cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                    .astype(np.uint8)
                    .tobytes()
                    )

            cv2.imshow('frame',frame)
            if cv2.waitKey(1) & 0xFF == ord('q'):
                process.stdin.close()
                process.wait()
                cap.release()
                cv2.destroyAllWindows()
                break
        else:
            process.stdin.close()
            process.wait()
            cap.release()
            cv2.destroyAllWindows()
            break

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM