基于PySide2实现调用本地摄像头抓拍并保存照片(Python版本)

因为横向课题需要,这是其中的一个小小的功能,单独拎出来作为一个小demo,方便后续学习使用

项目实现功能:
点击open按钮,摄像头开启,实时捕获周围图像并显示
点击capture按钮,保存摄像头照片,类似截图功能
点击close按钮,关闭摄像头

一、Qt页面设计

创建一个Main Window
在这里插入图片描述
所用到的控件主要有:一个Label、三个Push Button
在这里插入图片描述
我这里保存的名称为:capture.ui

二、创建项目

其实就用到一个文件就行
项目结构如下:
在这里插入图片描述
一个主函数文件main.py,一个ui界面capture.ui

三、导包

from PySide2.QtWidgets import QApplication
from PySide2.QtUiTools import QUiLoader
import cv2
from PySide2.QtWidgets import *
from PySide2.QtGui import QImage, QPixmap
from PySide2.QtCore import Qt, QTimer
import time

四、系统初始化

self.ui = QUiLoader().load('./capture.ui')
把设计好的UI界面加载进来

self.camera_timer = QTimer()
设置一个定时器

    def __init__(self):
        # 加载ui文件
        self.ui = QUiLoader().load('./capture.ui')

        self.output_size = 150
        self.camera_timer = QTimer()
        
        # 获取显示器分辨率信息
        self.desktop = QApplication.desktop()
        self.screenRect = self.desktop.screenGeometry()
        self.screenheight = self.screenRect.height()
        self.screenwidth = self.screenRect.width()

        print("Screen height {}".format(self.screenheight))
        print("Screen width {}".format(self.screenwidth))
        
        self.ui.setFixedSize(self.ui.width(), self.ui.height())

五、窗口初始化

对每个按钮绑定不同的事件

self.ui.pushButton.clicked.connect(self.open_camera)
pushButton对应的是open,与打开摄像头功能open_camera这个函数进行事件绑定
同理
self.ui.pushButton_2.clicked.connect(self.getcapture)
pushButton_2对应的是capture,与拍摄保存照片功能getcapture这个函数进行事件绑定
self.ui.pushButton_3.clicked.connect(self.close_camera)
pushButton_3对应的是close,与关闭摄像头功能close_camera这个函数进行事件绑定
self.camera_timer.timeout.connect(self.show_image)
定时器超时show_image函数进行事件绑定

self.i = i = 0;
这里的i用于捕获多张照片的时候命名不重复

    def window_init(self):
        self.ui.pushButton.clicked.connect(self.open_camera)
        self.ui.pushButton_2.clicked.connect(self.getcapture)
        self.ui.pushButton_3.clicked.connect(self.close_camera)
        self.camera_timer.timeout.connect(self.show_image)
        self.i = i = 0;

六、打开摄像头函数——open_camera实现

cv2.VideoCapture(0),调用本地摄像头
若是外设就把参数0改为1
若要播放某段视频就把参数0改为视频的路径即可,记得是字符串形式哈

self.camera_timer.start(40),每40ms读取一次,只要读取速度够快,人眼感觉不出来,看到的就是流畅的实时视频

 def open_camera(self):
        self.capture = cv2.VideoCapture(0)  # 摄像头
        self.camera_timer.start(40)  # 每40毫秒读取一次,即刷新率为25帧
        print("open_camera is successful")

七、关闭摄像头函数——close_camera实现

camera_timer.stop(),摄像头定时器关闭,停止读取
capture.release(),用于捕获摄像头的每帧图片,释放摄像头资源
ui.label.clear(),将显示图片的lable控件内容给清除
ui.label.setText("TextLabel"),在控件上显示点字符串

    def close_camera(self):  # 关闭摄像头
        self.camera_timer.stop()  # 停止读取
        self.capture.release()  # 释放摄像头
        self.ui.label.clear()  # 清除DisplayInterface组件上的图片
        self.ui.label.setText("TextLabel")  # 设置文字在界面上

八、定时器超时绑定事件函数——show_image实现

打开摄像头之后每隔40ms捕获读取一张,那么这之间的空窗期都干些啥由show_image函数进行控制

flag, self.image = self.capture.read() # 从视频流中读取图片
学过OpenCV的同学就应该知道,flag是个bool类型表示是否读取成功,image就是每一帧的图像

width, height, _ = self.image.shape
得到摄像头照片的宽高信息

self.image_show = cv2.flip(self.image, 1)
因为摄像头拍摄都是镜像,需要中心反转一下

self.image_show = cv2.cvtColor(self.image_show, cv2.COLOR_BGR2RGB)
OpenCV中图像时BGR,但是PySide2里面的图像是RGB,故需要转换一下

self.image_file = QImage(self.image_show.data, height, width, QImage.Format_RGB888)
固定格式,用于PySide里面的图像显示

self.ui.label.setPixmap(QPixmap.fromImage(self.image_file))
将图片image_file显示到label控件上

    def show_image(self):  # 显示图片
        flag, self.image = self.capture.read()  # 从视频流中读取图片

        width, height, _ = self.image.shape  # 行:宽,列:高
        self.image_show = cv2.flip(self.image, 1)  # 水平翻转,因为摄像头拍的是镜像的。

        self.image_show = cv2.cvtColor(self.image_show, cv2.COLOR_BGR2RGB)  # opencv读的通道是BGR,要转成RGB

        self.image_file = QImage(self.image_show.data, height, width, QImage.Format_RGB888)
        self.ui.label.setPixmap(QPixmap.fromImage(self.image_file))
        self.ui.label.setScaledContents(True)  # 让图片自适应 label 大小

九、捕获摄像头函数——getcapture实现

self.i = self.i + 1
每次捕获照片都要自加一下,为了防止名称重复

date_name = time.strftime("%Y%m%d")
获取当前的年月日

image = cv2.flip(self.image, 1)
因为image是摄像头捕获得到的图片,是镜像过的,故需要通过flip函数镜像转换一下

cv2.imwrite("./{}_capture_{}.jpg".format(str(date_name), self.i), image)
将图片保存到当前路径下,命名格式为当前年月日_capture_第几次

self.camera_timer.stop() ,停止读取
self.capture.release(),释放摄像头资源

    def getcapture(self):
        self.i = self.i + 1;
        date_name = time.strftime("%Y%m%d")
        print("getcapture")
        print(date_name)
        image = cv2.flip(self.image, 1)
        cv2.imwrite("./{}_capture_{}.jpg".format(str(date_name), self.i), image)

        self.camera_timer.stop()  # 停止读取
        self.capture.release()  # 释放摄像头

十、主函数入口

gui = Mainwindow()
我的这个类为Mainwindow,当然要根据实际情况定义声明即可

if __name__ == '__main__':
    app = QApplication([])
    gui = Mainwindow()  #初始化
    gui.window_init()
    gui.ui.show() #将窗口控件显示在屏幕上
    app.exit(app.exec_())

十一、完整代码

main.py

from PySide2.QtWidgets import QApplication
from PySide2.QtUiTools import QUiLoader
import cv2
from PySide2.QtWidgets import *
from PySide2.QtGui import QImage, QPixmap
from PySide2.QtCore import Qt, QTimer
import time


class Mainwindow(object):
    def __init__(self):
        # 加载ui文件
        self.ui = QUiLoader().load('./capture.ui')

        self.output_size = 150
        self.camera_timer = QTimer()
        # 获取显示器分辨率
        self.desktop = QApplication.desktop()
        self.screenRect = self.desktop.screenGeometry()
        self.screenheight = self.screenRect.height()
        self.screenwidth = self.screenRect.width()

        print("Screen height {}".format(self.screenheight))
        print("Screen width {}".format(self.screenwidth))
        self.ui.setFixedSize(self.ui.width(), self.ui.height())

    def window_init(self):
        self.ui.pushButton.clicked.connect(self.open_camera)
        self.ui.pushButton_2.clicked.connect(self.getcapture)
        self.ui.pushButton_3.clicked.connect(self.close_camera)
        self.camera_timer.timeout.connect(self.show_image)
        self.i = i = 0

    def getcapture(self):
        self.i = self.i + 1
        date_name = time.strftime("%Y%m%d")
        print("getcapture")
        print(date_name)
        image = cv2.flip(self.image, 1)
        cv2.imwrite("./{}_capture_{}.jpg".format(str(date_name), self.i), image)

        self.camera_timer.stop()  # 停止读取
        self.capture.release()  # 释放摄像头


    def open_camera(self):
        self.capture = cv2.VideoCapture(0)  # 摄像头
        self.camera_timer.start(40)  # 每40毫秒读取一次,即刷新率为25帧
        print("open_camera is successful")

    def close_camera(self):  # 关闭摄像头
        self.camera_timer.stop()  # 停止读取
        self.capture.release()  # 释放摄像头
        self.ui.label.clear()  # 清除DisplayInterface组件上的图片
        self.ui.label.setText("TextLabel")  # 设置文字在界面上

    def show_image(self):  # 显示图片
        flag, self.image = self.capture.read()  # 从视频流中读取图片

        width, height, _ = self.image.shape  # 行:宽,列:高
        self.image_show = cv2.flip(self.image, 1)  # 水平翻转,因为摄像头拍的是镜像的。

        self.image_show = cv2.cvtColor(self.image_show, cv2.COLOR_BGR2RGB)  # opencv读的通道是BGR,要转成RGB

        self.image_file = QImage(self.image_show.data, height, width, QImage.Format_RGB888)
        self.ui.label.setPixmap(QPixmap.fromImage(self.image_file))
        self.ui.label.setScaledContents(True)  # 让图片自适应 label 大小

if __name__ == '__main__':
    app = QApplication([])
    gui = Mainwindow()  #初始化
    gui.window_init()
    gui.ui.show() #将窗口控件显示在屏幕上
    app.exit(app.exec_())

十二、运行结果

在这里插入图片描述
目前项目下一张图片都没
在这里插入图片描述

open
在这里插入图片描述

capture
捕捉之后项目下会保存刚才抓拍的图片
在这里插入图片描述

close
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/446045.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Day6 java 常用API

文章目录 1、Calendar1.1 Calendar日历对象 2、JDK8 之后新增的时间类2.1 LocalDate、LocalTime 、LocalDateTime2.2 ZoneId 、ZoneIdTime2.3 Instant2.4 DateTimeFormatter2.5 Period2.6 Duration 1、Calendar 在了解calendar之前,先用SimpleDateFormat 写一个小例…

保持长期高效的七个法则(一)7 Rules for Staying Productive Long-Term(1)

Easily the best habit I’ve ever started was to use a productivity system.The idea is simple:organizing all the stuff you need to do (and how you’re going to do it) prevents a lot of internal struggle to get things done. 无疑,我曾经建立过的最好…

C++面试宝典一部分

今天整理书籍资料时,发现多年前打印的面试资料,拍照分享给大家。

ai+模型选择+过拟合和欠拟合

ai模型选择过拟合和欠拟合 1模型选择1训练误差和泛化误差2验证数据集和测试数据集3k-折交叉验证4总结 2过拟合和欠拟合1模型容量2估计模型容量3VC维4数据复杂度5总结 3代码 1模型选择 1训练误差和泛化误差 训练误差(Training Error)和泛化误差&#xff…

代码随想录刷题笔记-Day29

1. N皇后 51. N 皇后https://leetcode.cn/problems/n-queens/ 按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数…

LVS+Keepalived 高可用负载均衡集群

一. 高可用集群的相关知识 1.1 高可用(HA)集群和普通集群的比较 ① 普通集群 普通的群集的部署是通过一台度器控制调配多台节点服务器进行业务请求的处理,但是仅仅是一台调度器,就会存在极大的单点故障风险,当该调度…

20-Java备忘录模式 ( Memento Pattern )

Java备忘录模式 摘要实现范例 备忘录模式(Memento Pattern)保存一个对象的某个状态,以便在适当的时候恢复对象 备忘录模式属于行为型模式 摘要 1. 意图 在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对…

《时间贫困》

作者:【英】凯茜霍姆斯 深陷困境:时间贫困且精疲力竭 我们生活在生产力至上的文化中,忙碌已经成了一种身份的象征,也是个人价值的一种体现。然而,基于我个人的经历和研究,我发现这种忙碌的生活状态并不能…

通过Forms+Automate+Lists+审批,实现用车申请流程

因为Sham公司目前用的用车申请流程是使用的K2系统,用户申请后,我们还需要单独另行输入Excel来汇总申请记录,当然K2也能导出,但是需要每次导出也是很麻烦的,而且不灵活。 刚好最近发现Forms与Automate能联通&#xff0…

GCN 翻译 - 3

3 SEMI-SUPERVISED NODE CLASSIFICATION 这里简单引入一个例子,利用图上信息传播的方式的一个灵活的模型,我们来解决一个图上节点分类的半监督问题。正如在introduction里面提到的,我们应用数据X和图结构的邻接矩阵锁提出的模型f(X,A)在图结…

基于51单片机的定时器时钟设计[proteus仿真]

基于51单片机的定时器时钟设计[proteus仿真] 时钟设计检测系统这个题目算是课程设计和毕业设计中常见的题目了,本期是一个基于51单片机的定时器时钟设计 需要的源文件和程序的小伙伴可以关注公众号【阿目分享嵌入式】,赞赏任意文章 2¥&…

【LeetCode】升级打怪之路 Day 14:二叉树的遍历

今日题目: 144. 二叉树的前序遍历94. 二叉树的中序遍历145. 二叉树的后序遍历102. 二叉树的层序遍历107. 二叉树的层序遍历 II199. 二叉树的右视图637. 二叉树的层平均值429. N 叉树的层序遍历515. 在每个树行中找最大值116. 填充每个节点的下一个右侧节点指针117. …

采用 Amazon DocumentDB 和 Amazon Bedrock 上的 Claude 3 构建游戏行业产品推荐

前言 大语言模型(LLM)自面世以来即展示了其创新能力,但 LLM 面临着幻觉等挑战。如何通过整合外部数据库的知识,检索增强生成(RAG)已成为通用和可行的解决方案。这提高了模型的准确性和可信度,特…

6-DOF GraspNet: Variational Grasp Generation for Object Manipulation

总结: 使用变分自动编码器(VAE)对抓取进行采样,并使用基于点网的抓取评估器模型对采样的抓取进行评估和细化 摘要: 我们将抓取生成问题表述为 使用变分自编码器对一组抓取进行采样,并使用抓取评 估器模型对采样的抓取进行评估和…

2024年k8s最新版本使用教程

2024年k8s最新版本使用教程 3. YAML语言入门3.1 基本语法规则3.2 支持的数据结构3.3 其他语法 4 资源管理4.1 k8s资源查询4.2 资源操作命令4.3 资源操作方式4.3.1 命令行方式4.3.2 YAML文件方式 5 Namespace5.1 查看命名空间5.2 创建命名空间5.3 删除命名空间5.4 命名空间资源限…

Java websocket在SpringBoot中使用

Java websocket在SpringBoot中使用 导入坐标 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>3.2.3</version> </dependency>配置websocket 新…

Linux安装MeterSphere并结合内网穿透实现公网远程访问本地服务

文章目录 前言1. 安装MeterSphere2. 本地访问MeterSphere3. 安装 cpolar内网穿透软件4. 配置MeterSphere公网访问地址5. 公网远程访问MeterSphere6. 固定MeterSphere公网地址 前言 MeterSphere 是一站式开源持续测试平台, 涵盖测试跟踪、接口测试、UI 测试和性能测试等功能&am…

复制表

目录 复制表 将部门 30 的所有员工信息保存在 emp30 表中 将复杂查询结果创建为表 只将 emp 表的结构复制为 empnull 表 从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 复制表 严格来说&#xff0c;复制表不是复制操作&am…

AI大模型,掀起新一波智能浪潮!

AI大模型的出现&#xff0c;标志着人工智能技术迈入了一个新的阶段。这些巨大的模型不仅在规模上超越了以往任何其他人工智能系统&#xff0c;而且在性能上也取得了巨大的突破。由于其庞大的参数量和复杂的结构&#xff0c;AI大模型在各个领域展现出了强大的学习能力和推理能力…

力扣面试经典150 —— 11-15题

力扣面试经典150题在 VScode 中安装 LeetCode 插件即可使用 VScode 刷题&#xff0c;安装 Debug LeetCode 插件可以免费 debug本文使用 python 语言解题&#xff0c;文中 “数组” 通常指 python 列表&#xff1b;文中 “指针” 通常指 python 列表索引 文章目录 11. [中等] H指…