91 lines
2.9 KiB
Python
91 lines
2.9 KiB
Python
|
|
import cv2
|
|||
|
|
import numpy as np
|
|||
|
|
import struct
|
|||
|
|
import sys
|
|||
|
|
import os
|
|||
|
|
import argparse
|
|||
|
|
|
|||
|
|
|
|||
|
|
def BGR888_2_RGB565(img):
|
|||
|
|
'''BGR888 转化为 RGB565
|
|||
|
|
|
|||
|
|
Arguments:
|
|||
|
|
- img -- 待转化的 numpy 数组
|
|||
|
|
'''
|
|||
|
|
|
|||
|
|
img_B = img[:, :, 0]
|
|||
|
|
img_G = img[:, :, 1]
|
|||
|
|
img_R = img[:, :, 2]
|
|||
|
|
img_RGB565 = ((img_B & 0xF8) >> 3) | (
|
|||
|
|
(img_G & 0xFC) << 3) | ((img_R & 0xF8) << 8)
|
|||
|
|
return img_RGB565.flatten()
|
|||
|
|
|
|||
|
|
|
|||
|
|
if __name__ == '__main__':
|
|||
|
|
|
|||
|
|
parser = argparse.ArgumentParser(
|
|||
|
|
description='生成供 STM32-Player (https://github.com/StopPointTeam/STM32-Player) 播放的视频')
|
|||
|
|
parser.add_argument('-i', '-input', help='输入视频路径')
|
|||
|
|
arg = vars(parser.parse_args())
|
|||
|
|
|
|||
|
|
if os.path.exists(arg['i']) == False:
|
|||
|
|
print('输入视频路径不存在,请检查路径!')
|
|||
|
|
sys.exit(1)
|
|||
|
|
|
|||
|
|
cap = cv2.VideoCapture(arg['i'])
|
|||
|
|
if cap.isOpened() == False:
|
|||
|
|
print('打开输入视频失败!')
|
|||
|
|
sys.exit(1)
|
|||
|
|
|
|||
|
|
fps = cap.get(cv2.CAP_PROP_FPS)
|
|||
|
|
frame_count = cap.get(cv2.CAP_PROP_FRAME_COUNT)
|
|||
|
|
frame_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
|
|||
|
|
frame_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
|
|||
|
|
|
|||
|
|
print('输入视频分辨率:', frame_width, '*', frame_height)
|
|||
|
|
print('输入视频 FPS:', fps)
|
|||
|
|
print('输入视频总帧数:', round(frame_count))
|
|||
|
|
print('输入视频时长:', round(frame_count / fps, 2), 's')
|
|||
|
|
|
|||
|
|
if fps > 30:
|
|||
|
|
frame_interval = int(fps / (fps - 30))
|
|||
|
|
fps = 30
|
|||
|
|
print('输入视频 FPS 超过 30,将自动转换为 30')
|
|||
|
|
else:
|
|||
|
|
frame_interval = 0
|
|||
|
|
|
|||
|
|
frame_seq = 0 # 输入视频帧序号
|
|||
|
|
new_seq = 0 # 输出视频帧序号
|
|||
|
|
|
|||
|
|
# 保存到二进制文件中
|
|||
|
|
filename = os.path.basename(arg['i']) + '.32v'
|
|||
|
|
file = open(filename, 'wb')
|
|||
|
|
file.seek(153600, os.SEEK_SET)
|
|||
|
|
|
|||
|
|
while True:
|
|||
|
|
ret, img = cap.read() # 捕获一帧
|
|||
|
|
if ret == True:
|
|||
|
|
frame_seq += 1
|
|||
|
|
if (frame_interval == 0 or frame_seq % frame_interval != 0):
|
|||
|
|
new_seq += 1
|
|||
|
|
|
|||
|
|
# 变换尺寸,并转化为 uint16 类型 numpy 数组
|
|||
|
|
img_resized = np.array(cv2.resize(
|
|||
|
|
img, (320, 240))).astype('uint16')
|
|||
|
|
|
|||
|
|
img_RGB565 = BGR888_2_RGB565(img_resized) # 颜色空间转换
|
|||
|
|
|
|||
|
|
fmt = '>' + len(img_RGB565) * 'H' # 格式化字符串,大端模式
|
|||
|
|
data = struct.pack(fmt, *img_RGB565) # 列表转换为二进制字节流
|
|||
|
|
|
|||
|
|
file.write(data)
|
|||
|
|
print('正在处理:第', frame_seq, '/', round(frame_count), '帧,进度:',
|
|||
|
|
round(frame_seq / frame_count * 100, 2), '%')
|
|||
|
|
|
|||
|
|
else:
|
|||
|
|
# 写入视频信息头
|
|||
|
|
file.seek(0, os.SEEK_SET)
|
|||
|
|
file.write(struct.pack('<dI', fps, int(new_seq))) # 小端模式
|
|||
|
|
print('处理完成,输出视频共', new_seq, '帧, FPS 为', fps)
|
|||
|
|
break
|