本文通过使用一个yuv图片放大和显示的例子,学习 opencv 的 resize 、SDL2显示yuv图片, argparse命令解析。其中涉及numpy数组的指针转换(调用 c 库时会有要求)
(以下方法适用于无法连接网络的电脑;若电脑可以联网,可以使用pip install进行安装)
参考官方安装文档:https://pysdl2.readthedocs.io/en/latest/install.html
A. 如果可以联网,直接 pip install pysdl2;如果不能联网,则需另外下载最新release的 pysdl2;https://bitbucket.org/marcusva/py-sdl2/downloads/
B. 到 http://www.libsdl.org 下载 SDL2.0 的 Runtime Binaries (我的系统是wind7 64bit),解压后,将 SDL2.dll 拷贝到C:\Windows\System32目录;
SDL2.dll也可以放到其他目录,但python代码中在 import sdl2 前需要加上
os.environ["PYSDL2_DLL_PATH"] = "c:\\directory\of\\sdl2\\library"
参考 https://stackoverflow.com/questions/25835117/python-with-pysdl2-could-not-find-any-library-for-sdl2
其中 Prerequisites,我本地的是 anaconda3 的python3.6;
C. (若能 pip install pysdl2,跳过步骤C)在 Anaconda Prompt 命令行中,cd 到 pysdl2 的解压目录(如果在其他目录,install 时会提示找不到一些文件),输入 python setup.py install,即可安装完成
D. 测试,到 pysdl2 解压目录下的 example 文件夹,运行 sdl2hello.py,图片正常秀出来,说明安装正确。或者输入以下代码,没有报错则说明安装正确。
import sdl2
sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)
初始化过程类似c/c++中的接口。
def display_init(width, height, title):
posx = sdl2.SDL_WINDOWSPOS_UNDEFINED
posy = sdl2.SDL_WINDOWSPOS_UNDEFINED
window = sdl2.SDL_CreateWindow(tile, posx, posy, width, height, flag)
render = sdl2.SDL_CreateRenderer(window, -1, sdl2.SDL_RENDERER_SOFTWARE)
texture = sdl2.SDL_CreateTexture(render,
sdl2.SDL_PIXELFORMAT_IYUV,
sdl2.SDL_TEXTUREACCESS_STREAMING,
width, height)
return window, render, texture
def display_frame(render, texture, rect, datay, datau, datav, stridey, strideuv):
#首先将传进来的yuv数据指针做转换
ptry = datay.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte))
ptru = datau.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte))
ptrv = datav.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte))
sdl2.SDL_UpdateYUVTexture(texture, ctypes.byref(rect),
ptry, stridey,
ptru, strideuv,
ptrv, strideuv)
sdl2.SDL_RenderCear(render)
sdl2.SDL_RenderCopy(render, texture, None, ctypes.byref(rect))
sdl2.SDL_RenderPresent(window)
def destroy_frame(render, texture, window):
sdl2.SDL_DestroyTexture(texture)
sdl2.SDL_DestroyRenderer(render)
sdl2.SDL_DestroyWindow(window)
def init_args():
parser = argparse.ArgumentParser(description = 'Read yuv data file, resize picture and show')
parser.add_argument('-i', '--input_file', help = 'input yuv file',
default = 'E:/YUV/1920x1080/Park_1920X1080.yuv')
parser.add_argument('-w', '--width', help = 'input yuv picture width',
default = 1920)
parser.add_argument('-he', '--height', help = 'input yuv picture height',
default = 1080)
parser.add_argument('-rw', '--resize_width', help = 'output yuv picture width',
default = 2560)
parser.add_argument('-rhe', '--resize_height', help = 'output yuv picture height',
default = 1080)
parser.add_argument('-n', '--picture_number', help = 'process picture number',
default = 1080)
parser.add_argument('-o', '--output_file', help = 'output resize yuv file',
default = 'E:/YUV/1920x1080/Park_resize_2560x1440.yuv')
class cyuv_rs:
def __init__(self, args):
self.input_file = args.input_file
self.output_file = args.output_file
self.width = args.width
self.height = args.height
self.picture_number = args.picture_number
self.resize_width = args.resize_width
self.resize_height = args.resize_height
self.input_file_handle = None
self.output_file_handle = None
#open file
try:
self.input_file_handle = open(self.input_file, ''rb')
except IOError:
self.input_file_handle = None
try:
self.output_file_handle = open(self.output_file, ''rb')
except IOError:
self.output_file_handle = None
#alloc numpy buffer for yuv data
self.input_y = np.empty([self.height, self.width], dtype = ctypes.c_ubyte) # if 10bit yuv, use c_ushort
self.input_u = np.empty([self.height >> 1, self.width >> 1], dtype = ctypes.c_ubyte)
self.input_v = np.empty([self.height >> 1, self.width >> 1], dtype = ctypes.c_ubyte)
self.output_y = np.empty([self.resize_height, self.resize_width], dtype = ctypes.c_ubyte) # if 10bit yuv, use c_ushort
self.output_u = np.empty([self.resize_height >> 1, self.resize_width >> 1], dtype = ctypes.c_ubyte)
self.output_v = np.empty([self.resize_height >> 1, self.resize_width >> 1], dtype = ctypes.c_ubyte)
def destroy(self):
if self.input_file_handle is not None:
self.input_file_handle.close()
if self.output_file_handle is not None:
self.output_file_handle.close()
del self.input_y, self.input_u, self.input_v
del self.output_y, self.output_u, self.output_v
def show_yuv_info(self):
print('input: %s' %(self.input_file))
print('input size: %dx%d' %(self.width,self.height))
print('output: %s' %(self.output_file))
print('output size: %dx%d' %(self.resize_width,self.resize_height))
print('test picture number: %d' %self.picture_number)
def read_input_yuv(self):
self.input_file_handle.readinto(self.input_y)
self.input_file_handle.readinto(self.input_u)
self.input_file_handle.readinto(self.input_v)
def save_output_picture(self):
if self.output_file_handle is None:
return
self.output_file_handle.write(self.output_y)
self.output_file_handle.write(self.output_u)
self.output_file_handle.write(self.output_v)
def resize_picture(self, interpolation):
# interpolation should be cv.INTER_LINEAR, cv.INTER_AREA, cv.INTER_CUBIC, cv.INTER_LANCZOS4
fx = 0
fy = 0
output_size = (self.resize_width, self.resize_height)
cv.resize(self.input_y, output_size, self.output_y, fx, fy, interpolation)
output_size = (self.resize_width >> 1, self.resize_height >> 1)
cv.resize(self.input_u, output_size, self.output_u, fx, fy, interpolation)
cv.resize(self.input_v, output_size, self.output_v, fx, fy, interpolation)
import sdl2
import numpy as np
import ctypes
import cv2 as cv
import argparse
import gc
# yuv resize class
# sdl interface
if __name__=='__main__':
parser = init_args()
args = parse.parse_args()
rsyuv = cyuv_rs(args)
rsyuv.show_yuv_info()
sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)
#init original picture window
org_window, org_render, org_texture = display_init(rsyuv.width, rsyuv.height, b"original picture")
rs_window, rs_render, rs_texture = display_init(rsyuv.width, rsyuv.height, b"resize picture")
print('press any key to continue')
i = 0
org_rect = sdl2.SDL_Rect(x=0, y=0, rsyuv.width, rsyuv.height)
rs_rect = sdl2.SDL_Rect(x=0, y=0, rsyuv.resize_width, rsyuv.resize_height)
event = sdl2.SDL_Event()
while i < args.picture_number:
rsyuv.read_input_yuv()
rsyuv.resize_picture(cv.INTER_LANCZOS4)
display_frame(org_render, org_texture, org_rect,
rsyuv.input_y, rsyuv.input_u, rsyuv.input_v,
rsyuv.width, rsyuv.width >> 1)
display_frame(rs_render, rs_texture, rs_rect,
rsyuv.input_y, rsyuv.input_u, rsyuv.input_v,
rsyuv.width, rsyuv.width >> 1)
rsyuv.save_output_picture()
i += 1
#wait for any key press
while True:
if sdl2.SDL_PollEvent(ctypes.byref(event)) != 0:
if event.type == sdl2.SDL_KEYDOWN:
break
elif event.type == sdl2.SDL_QUIT:
i += args.picture_number
destroy_frame(org_render, org_texture, org_window)
destroy_frame(rs_render, rs_texture, rs_window)
sdl2.SDL_Quit()
rsyuv.destroy()
gc.collect()
print('---------- test end ----------')
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。