一、imageio读取视频
最近需要用到imagio按照不同帧读取视频,然后发现了网上很多资料都不完整,查阅了很多版本才成功实现,我为了方便后面使用把视频解码后提取的信息存放在了两个不同列表中,便于通过tkinter去调节帧数。
import pylab
import imageio
import skimage
import numpy as np
# 视频的路径
filename = 'rdata/SI_Video_2.mp4'
# 可以选择解码工具
vid = imageio.get_reader(filename, 'ffmpeg')
nums=[]
ims=[]
for num, im in enumerate(vid):
# image的类型是mageio.core.util.Image可用下面这一注释行转换为arrary
#print(im.mean())
#num代表的是视频中的帧数,im是代表该帧图像的一组向量
nums.append(num)
ims.append(im)
#通过将信息存放在nums、ims列表中,可以读取指定帧的图像,0表示第一帧
image = skimage.img_as_float(ims[0]).astype(np.float64)
fig = pylab.figure()
fig.suptitle('image #{}'.format(nums[0]), fontsize=20)
pylab.imshow(ims[0])
pylab.show()
二、tkinter部分
Tkinter是python内置的标准库,常用于图形化界面(GUI)设计,即通过鼠标对菜单、按钮等图形化元素触发指令,并从标签、对话框等图型化显示容器中获取人机对话信息。实质上是一种流行的面向对象的GUI工具包TK的Python编程接口,提供了快速便利地创建GUI应用程序的方法。其图像化编程的基本步骤通常包括:
根窗体是图像化应用程序的根控制器,是tkinter的底层控件的实例。当导入tkinter模块后,调用 Tk()方法可初始化一个根窗体实例 root ,用 title() 方法可设置其标题文字,用geometry()方法可以设置窗体的大小(以像素为单位)。将其置于主循环中,除非用户关闭,否则程序始终处于运行状态。执行该程序,一个窗体就呈现出来了。在这个主循环的根窗体中,可持续呈现中的其他可视化控件实例,监测事件的发生并执行相应的处理程序。下面是具体代码及关于设置按钮的简单说明:
from tkinter import *
from tkinter import messagebox
root= Tk()
#窗口名设置
root.title('我的第一个Python窗体')
root.geometry('240x240')
#通过设置变量可以达到在窗口设置的文字变化的效果
var=StringVar()
#如果不需要变量直接,lab=Label(root, text='文本内容')就行
# 当然还有长宽、字体颜色、类型一系列的可改变的
#--------根窗体名,这里是root,--变量设置
lab=Label(root, textvariable=var)
#给变量var设置内容
var.set("hello")
#给标签定位
lab.pack()
def command1():
#单击按钮会发生的事情
# 弹出消息框-----------弹出框名--框内内容
messagebox.showinfo("显示框","hello!")
var.set('hi')
#按钮设置----根窗体名------按钮名------------------------------与按钮链接的命令,写入函数名即可
b1 = Button(root, text="butto", width=15, height=2, command=command1)
b1.pack()
#进入事件循环,即开始运行窗口
root.mainloop()
代码运行的效果:
三、通过imageio、tkinter创建读取视频帧图像的简易界面
from tkinter import * #导入包
from tkinter import messagebox # 弹出消息框
import pylab
import imageio
import skimage
import numpy as np
from gabor import gabor_pro
from PIL import Image
nums=[]
ims=[]
n=0
def video_setting():
# 视频的绝对路径
filename = 'rdata/SI_Video_2.mp4'
# 可以选择解码工具
vid = imageio.get_reader(filename, 'ffmpeg')
for num, im in enumerate(vid):
# image的类型是mageio.core.util.Image可用下面这一注释行转换为arrary
#print(im.mean())
nums.append(num)
ims.append(im)
#创建顶层窗口对象,并设置相关数据
def windows_setting():
root =Tk() #创建一个主窗口,所有的控件都是放在这里面的
root.title("纹理分析") # 标题
root.geometry("600x600+200+100") #控制主窗口的大小和位置(宽x高+距左边位置+据上边位置)
#将label显示内容用一个变量表示便于更新
var=StringVar()
lab=Label(root, textvariable=var)
#改变变量的值
var.set("第{}帧".format(nums[n]))
lab.pack()
#下一帧
def next():
global n
n=n+1
#变量值随着按钮按下变化
var.set("第{}帧".format(nums[n]))
#上一帧
def back():
global n
n=n-1
var.set("第{}帧".format(nums[n]))
#显示图像
def show():
'''单击按钮会发生的事情'''
messagebox.showinfo("图像显示","显示视频第{}帧图像".format(nums[n]))
image = skimage.img_as_float(ims[n]).astype(np.float64)
fig = pylab.figure()
fig.suptitle('image{}'.format(nums[n]), fontsize=20)
pylab.imshow(ims[n])
pylab.show()
#保存图片
def img_save():
data = np.asarray(ims[n], dtype=np.uint8)
image = Image.fromarray(data)
#填入自己需要保存图片的路径
image.save(r'image/image{}.jpg'.format(nums[n]))
b1 = Button(root, text="下一帧", width=15, height=2, command=next)
b2 = Button(root, text="上一帧", width=15, height=2, command=back)
b3 = Button(root, text="显示当前帧图像", width=15, height=2, command=show)
b4 = Button(root, text="保存当前帧图像", width=15, height=2, command=img_save)
b1.pack()
b2.pack()
b3.pack()
b4.pack()
root.mainloop()
video_setting()
windows_setting()
运行结果:
四、总结
图片保存的时候,我用的是imageio.imwrite(),限制了要为uint8,所以精度更高的视频在被按帧数保存后,可能会产生降精度的情况,但是如果只是按帧数查看视频,并无影响。另外,由于最近在学习关于图像纹理特征处理方面的东西,但是一直没有找到很好的资料,关于图像纹理特征被提取后,如何进一步处理,通过分类还是其他方法,我想到可以用直方图等图形来反应图形的边缘特征,不过还未实践。有思路或者见解的同学,欢迎留言或者私信分享哈。