前几篇博客分享搭建人脸识别与情绪判断的环境和源码,但是没有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. 解析 Javascript - this

    在函数中 this 到底取何值,是在函数真正被调用执行的时候确定下来的,函数定义的时候确定不了.  因为 this 的取值是执行上下文环境的一部分,每次调用函数,都会产生一个新的执行上下文环境.当你在 ...

  2. angular-单页面应用程序

    我们都知道angularjs是单一页面应用程序,那什么是单一页面应用程序呢?单一页面应用程序到底有什么好处呢? 下面我们来看一下: 首先我觉得可以把页面的响应模式分成这样大概3个阶段: 1. 最传统的 ...

  3. 机器学习技法:15 Matrix Factorization

    Roadmap Linear Network Hypothesis Basic Matrix Factorization Stochastic Gradient Descent Summary of ...

  4. [Codeforces 864D]Make a Permutation!

    Description Ivan has an array consisting of n elements. Each of the elements is an integer from 1 to ...

  5. bzoj 2212: [Poi2011]Tree Rotations

    Description Byteasar the gardener is growing a rare tree called Rotatus Informatikus. It has some in ...

  6. 【NOIP2013】华容道 广搜+spfa

    题目描述 [问题描述] 小 B 最近迷上了华容道,可是他总是要花很长的时间才能完成一次.于是,他想到用编程来完成华容道:给定一种局面, 华容道是否根本就无法完成,如果能完成, 最少需要多少时间. 小 ...

  7. [bzoj5016][Snoi2017]一个简单的询问

    来自FallDream的博客,未经允许,请勿转载,谢谢. 给你一个长度为N的序列ai,1≤i≤N和q组询问,每组询问读入l1,r1,l2,r2,需输出   get(l,r,x)表示计算区间[l,r]中 ...

  8. hdu5601 BestCoder Round #67 (div.2)

    N*M bulbs  Accepts: 94  Submissions: 717  Time Limit: 10000/5000 MS (Java/Others)  Memory Limit: 655 ...

  9. JS按照指定的周期来调用函数方法

    setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式. setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭.由 s ...

  10. git日常使用经验积累

    1 git merge origin/develop 将远程分支合并到本地,一般先执行合并,解决冲突,然后再git commit合入新建的分支,推送到远程分支里面,最后码云上找pl pull requ ...