前几篇博客分享搭建人脸识别与情绪判断的环境和源码,但是没有UI,界面很难看,一打开就是opencv弹出的一个视屏框。处女座的我看着非常难受,于是决定做一个UI,稍微规矩好看一点,再怎么说,这样的话也算是一个小软件,不再是运行源码了。

上网到处查了一圈之后,发现这是一个空缺,好像没有人在做这个,看到的唯一一个有点相似的是用wxpython制作一个视屏播放器。和这个显示opencv的实时视屏还是有点差距的,但是也有指导作用。

使用版本:python-3.6.3(anaconda)   opencv-3.4.1    wxpython-4.0.1

运行流程:

1、运行程序时,先显示封面页

2、用户点击【start】后开始opencv读取视屏,dlib开始处理,并进行情绪判断

3、用户点击【close】后,结束视屏,回到封面页。等待再次点击开始

一、实例化frame、添加控件

    def __init__(self,parent,title):
wx.Frame.__init__(self,parent,title=title,size=(600,600))
self.panel = wx.Panel(self)
self.Center() # 封面图片
self.image_cover = wx.Image(COVER, wx.BITMAP_TYPE_ANY).Scale(350,300)
# 显示图片在panel上
self.bmp = wx.StaticBitmap(self.panel, -1, wx.Bitmap(self.image_cover)) start_button = wx.Button(self.panel,label='Start')
close_button = wx.Button(self.panel,label='Close') self.Bind(wx.EVT_BUTTON,self.learning_face,start_button)
self.Bind(wx.EVT_BUTTON,self.close_face,close_button)

这段初始化的程序,就添加了一个图片,两个按钮,并为按钮绑定了各自的动作函数。这里使用wx.Image方法读取一个任意格式的照片,交给staticbitmap,开始在panel面板上显示这个图片。

二、基于GridBagSizer的界面布局

界面布局有很多方法可以使用,这里使用gridbagsizer进行界面布局。

它把一个面板抽象成一个网格,我们可以想象在excel中的样子,格子的大小比例根据自己的设置进行放大缩小。但是总面积不变。        # 基于GridBagSizer的界面布局

        # 先实例一个对象
self.grid_bag_sizer = wx.GridBagSizer(hgap=5,vgap=5)
# 注意pos里面是先纵坐标后横坐标
self.grid_bag_sizer.Add(self.bmp, pos=(0, 0), flag=wx.ALL | wx.EXPAND, span=(4, 4), border=5)
self.grid_bag_sizer.Add(start_button, pos=(4, 1), flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, span=(1, 1), border=5)
self.grid_bag_sizer.Add(close_button, pos=(4, 2), flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, span=(1, 1), border=5) self.grid_bag_sizer.AddGrowableCol(0,1)
self.grid_bag_sizer.AddGrowableRow(0,1)
self.panel.SetSizer(self.grid_bag_sizer)
# 界面自动调整窗口适应内容
self.grid_bag_sizer.Fit(self)

使用Add方法把控件添加到网格中,pos是坐标,span是这个控件需要跨越的行列数,这两个参数基本上就可以确定一个控件的位置和大小了。

下面的fit方法就是确保这个控件会随着面板的拖大拖小而进行相应的比例移动。

三、按钮动作

既然控件的位置格式都摆放整齐了,下面就是他们的动作绑定了。

点击开始,会开始opencv读取视屏,然后把每一帧图片交给dlib进行人脸识别与特征点的标定,然后在进行显示。

原来是调用opencv的imshow方法来进行显示的,具体这句话为:cv2.imshow("camera", im_rd),那么我们想让这一帧显示在wxpython的框架内怎办呢?

把刚才的封面页换成opencv的每一帧不就可以了吗!

cv2.imshow("camera", im_rd),是循环显示它的每一帧图片,只是换了个方法而已,其实原理都是一样 的。循环显示每一帧图片,就成了视屏;

所以归根结底,这个问题就是显示一个图片的问题。

好像还是有点不对。我们显示图片的格式是JPG图片,那么这个 im_rd 是什么格式呢?

还记得这一段码:

            # cap.read()
# 返回两个值:
# 一个布尔值true/false,用来判断读取视频是否成功/是否到视频末尾
# 图像对象,图像的三维矩阵
flag, im_rd = self.cap.read()

他是一个三维的矩阵。

这时,我们需要用下面的方法对这一帧的数据进行转化,显示、

            # 现将opencv截取的一帧图片BGR转换为RGB,然后将图片显示在UI的框架中
height,width = im_rd.shape[:2]
image1 = cv2.cvtColor(im_rd, cv2.COLOR_BGR2RGB)
pic = wx.Bitmap.FromBuffer(width,height,image1)
# 显示图片在panel上
self.bmp.SetBitmap(pic)
self.grid_bag_sizer.Fit(self)

这样就可以将视屏的每一帧数据显示在wxpython的panel面板上面。

四、简单多线程

在我能够点击start开始在框架内部显示视屏的时候,我想拖动一下这个框架,但是程序竟然卡死了!无响应???what??

查了资料才知道,我们的程序只有一个线程,这时程序正在while死循环里面进行视屏显示,占用了这唯一的一个线程,如果我们进行UI操作的话,程序就会被崩溃。

解决办法就是,创建一个新的线程,让按钮的动作函数在这个新的子线程中执行,主线程我们进行UI的操作,比如框架的拖动,放大缩小。

    def learning_face(self,event):
"""使用多线程,子线程运行后台的程序,主线程更新前台的UI,这样不会互相影响"""
import _thread
# 创建子线程,按钮调用这个方法,
_thread.start_new_thread(self._learning_face, (event,))

这时,我们点击按钮start后,开始执行这个方法,先创建一个子线程,然后在这个方法中调用之前那个方法。就是对之前的那个方法进行了进一步的封装。

这样就不会出现卡死的现象了。

完整程序代码:https://gitee.com/Andrew_Qian/codes/acm80fr6ekjwgpz27bthd35

opencv视屏流嵌入wxpython框架的更多相关文章

  1. OpenCV视屏跟踪

    #include <stdio.h> #include <iostream> #include "opencv2/imgproc/imgproc.hpp" ...

  2. opencv读取并播放avi视屏

    视屏的本质是一些静态的图像的集合,opencv可以不断读取视屏中的图片,显示,就产生了类似电影的效果. 这样也就可以通过opencv对实时的视屏流进行处理了. #include "stdaf ...

  3. iOS:简易的音视屏播放框架XYQPlayer

    一.前缀 一直都想好好学学音视频这方面的知识,抽了几个周末参考一些资料,尝试着写了一个简易的音视频播放框架,支持音视频播放.视频截图.音乐缓存,其实吧,也就是尽可能的封装罢了,方便以后自己使用.目前只 ...

  4. 【学习笔记】兄弟连LINUX视屏教程(沈超 李明)

    发现自己的linux水平楞个瓜皮,找个视屏教程学习一哈 1 linux系统简介 1.1 UNIX和Linux发展史 unix发展历史:1969年,美国贝尔实验室的肯.汤普森开发出unix系统,1971 ...

  5. MPEG-1视屏压缩标准

    MPEG-1标准包括5个部分 图像的四种类型: I帧: B帧:双向帧间预测 P帧: D帧:只含有16分量,为快放设计 压缩前需要帧重排 视屏码流结构 I帧压缩 p帧压缩 b帧压缩 其他压缩算法 MPE ...

  6. FFmpeg + php 视屏转换

    什么是FFmpeg? FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件).它提供了录制.转换以及流化音视频的完整解决方案.它包含了非常先进 ...

  7. 原创:Equinox OSGi应用嵌入Jersey框架搭建REST服务

    一.环境 eclipse版本:eclipse-luna 4.4 jre版本:1.8 二.Equinox OSGi应用嵌入Jersey框架搭建REST服务 1.新建插件工程HelloWebOSGI a. ...

  8. session失效后,登录页面嵌入iframe框架

    在登录页面的onload方法中加入以下代码解决: //防止登录页面嵌入iframe框架 if (top.location != self.location){ top.location=self.lo ...

  9. wndows程序设计之书籍知识与代码摘录-获取视屏显示器像素等参数GetsystemMetrics

    以下的代码段用于获取视屏显示器的高度宽度,以像素为单位. int sxScreen, cyScreen; cxScreen = GetSystemMetrics (SM_CXSCREEN); cySc ...

随机推荐

  1. Lua编写wireshark插件初探——解析Websocket上的MQTT协议

    一.背景 最近在做物联网流量分析时发现, App在使用MQTT协议时往往通过SSL+WebSocket+MQTT这种方式与服务器通信,在使用SSL中间人截获数据后,Wireshark不能自动解析出MQ ...

  2. tornada模板学习笔记

    import tornado.web import tornado.httpserver import tornado.ioloop import tornado.options import os. ...

  3. vue2与vue1的区别

    在前面的学习过程中我们已经对vue1有了一定的了解,下面我们来学习一下vue2,看一下vue1与vue2有什么区别. 区别1: 在vue2中使用v-for指令时它可以添加重复的内容,就像可以添加相同的 ...

  4. ZOJ-1586 QS Network---最小生成树Prim

    题目链接: https://vjudge.net/problem/ZOJ-1586 题目大意: 首先给一个t,代表t个测试样例,再给一个n,表示有n个QS装置,接下来一行是n个QS装置的成本.接下来是 ...

  5. 解决VS2017编译后的EXE文件不能在其他电脑上运行的问题

    笔者昨天写了个超简单画图程序,很是激动啊,立马给同学分享了自己写的程序,结果发现无法运行 错误是这样的 解决方法如下: 1.将Debug改为Release 2.进入[项目]-[**属性] 3.[C/C ...

  6. SQL Server 2014 HADR_DATABASE_WAIT_FOR_TRANSITION_TO_VERSIONING 等待

    最近有发现SAP 的MES系统上了AlwaysOn后辅助节点发现无法查询的情况,例如在辅助节点上执行: SELECT TOP 0 * FROM TABLE1; 语句执行正常SELECT TOP 1* ...

  7. spring boot / cloud (二十) 相同服务,发布不同版本,支撑并行的业务需求

    spring boot / cloud (二十) 相同服务,发布不同版本,支撑并行的业务需求 有半年多没有更新了,按照常规剧本,应该会说项目很忙,工作很忙,没空更新,吧啦吧啦,相关的话吧, 但是细想想 ...

  8. python 函数“四剑客”的使用和介绍

    python函数四剑客:lambda.map.filter和reduce. 一.lambda(匿名函数) 1. 学习lambda要注意一下几点: lambda语句被用来创建新的函数对象,并且在运行的时 ...

  9. java基本数据类型的包装类

    基本类型对应的包装类 byte(Byte).short(Short).int(Integer).long(Long).float(Float).double(Double).char(Characte ...

  10. [LeetCode] Degree of an Array 数组的度

    Given a non-empty array of non-negative integers nums, the degree of this array is defined as the ma ...