前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PySDL2学习

PySDL2学习

原创
作者头像
用户6132577
修改2020-01-13 12:26:22
1.2K0
修改2020-01-13 12:26:22
举报
文章被收录于专栏:zwh学习笔记

本文通过使用一个yuv图片放大和显示的例子,学习 opencv 的 resize 、SDL2显示yuv图片, argparse命令解析。其中涉及numpy数组的指针转换(调用 c 库时会有要求)

1. 安装PySDL2

(以下方法适用于无法连接网络的电脑;若电脑可以联网,可以使用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,图片正常秀出来,说明安装正确。或者输入以下代码,没有报错则说明安装正确。

代码语言:python
代码运行次数:0
复制
import sdl2
sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO)

2. 使用 PySDL2 显示 接口函数

2.1. 初始化SDL函数

初始化过程类似c/c++中的接口。

代码语言:python
代码运行次数:0
复制
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
                                                 

2.2 显示一帧yuv图片函数

代码语言:python
代码运行次数:0
复制
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)

2.3 释放SDL资源函数

代码语言:python
代码运行次数:0
复制
def destroy_frame(render, texture, window):
    sdl2.SDL_DestroyTexture(texture)
    sdl2.SDL_DestroyRenderer(render)
    sdl2.SDL_DestroyWindow(window)

3. argparse解析命令行参数

代码语言:python
代码运行次数:0
复制
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')

4. yuv resize 类

代码语言:python
代码运行次数:0
复制
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) 
                      

5. 主函数

代码语言:python
代码运行次数:0
复制
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 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 安装PySDL2
  • 2. 使用 PySDL2 显示 接口函数
    • 2.1. 初始化SDL函数
      • 2.2 显示一帧yuv图片函数
        • 2.3 释放SDL资源函数
        • 3. argparse解析命令行参数
        • 4. yuv resize 类
        • 5. 主函数
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档