用python实现相机包含各种功能

这是一个使用Python结合OpenCV和PyQt5实现的简单摄像头监控程序,具备截图、录像和调整分辨率的功能。用户可以通过UI界面选择是否显示灰度图,并在运行时动态调整分辨率。同时,程序能够捕获当前帧并将其保存为图片或录制为avi视频。
摘要由CSDN通过智能技术生成

暑假开始了解python了,记录一下最近实现的小相机,只有功能,没有qss😀,还参考了很多博主😂

貌似还有一个小问题,就是转成灰度图后转不回去了,我比较懒就不研究了🎈

import time
import cv2
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5 import QtGui
from PyQt5.QtWidgets import *
from qtpy import uic


class Win(QWidget):
    msg = pyqtSignal(bool)

    def __init__(self):
        super(Win, self).__init__()
        self.flag = True
        self.photoname = 1
        self.ui = uic.loadUi("ui/untitled.ui")  # 导入ui文件
        self.ui.setParent(self)  # 将ui文件设置父窗口,将它显示出来

        self.timeThread = Time()  # 创建一个自己写的Time类
        self.timeThread.start()
        self.resize(820, 600)  # 改变窗口大小
        self.timeThread.update.connect(self.update_time)  # 给信号设置槽函数

        self.cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)  # 打开内置摄像头,windows特有的,加上CAP_DSHOW,不加关闭程序摄像头不会关闭
        self.cap.set(3, 640)  # 设置相机窗口
        self.cap.set(4, 480)
        self.video = Video(self.cap)
        self._timer = QTimer(self)  # 创建定时器对象
        self._timer.timeout.connect(self.play)  # 连接timeout信号到槽函数
        self._timer.start(30)  # 多少时间间隔内执行一次

        self.ui.jietu.clicked.connect(self.cliek_jietu)  # 绑定槽函数
        self.ui.luxiang.clicked.connect(self.click_luxiang)

        fourcc = cv2.VideoWriter_fourcc(*'mp4v')  # 设置录像格式
        self.vm = cv2.VideoWriter('E:\opencvLZvideo\out007.avi', fourcc, 30, (640, 480))

        self.ui.fbl.currentIndexChanged.connect(self.click_fbl)
        self.ui.td.currentIndexChanged.connect(self.click_td)
        self.msg.connect(self.video.change)

    def click_td(self):
        self.ys = self.ui.fbl.currentText()  # 如果组合框改变内容
        if self.ys == '原':
            self.msg.emit(True)
        else:
            self.msg.emit(False)

    def click_fbl(self):
        self.hz = self.ui.fbl.currentText()  # 改变内容修改分辨率
        if self.hz == '1280*760':
            self.cap.set(3, 1280)
            self.cap.set(4, 760)
        elif self.hz == '640*480':
            self.cap.set(3, 640)
            self.cap.set(4, 480)
        else:
            self.cap.set(3, 640)
            self.cap.set(4, 360)

    def click_luxiang(self):

        while self.cap.isOpened():  # 当摄像头是打开的时候
            frame1 = cv2.cvtColor(self.video.currentFrame, cv2.COLOR_BGR2RGB)  # 获取当前帧并转为RGB
            self.vm.write(frame1)  # 写入vm
            if cv2.waitKey(30) == ord('q'):  # 退出按钮
                break

    def closeEvent(self, event: QtGui.QCloseEvent) -> None:  # 设置关闭事件
        print(event)
        self.cap.release()
        self.vm.release()
        print("closing...")

    def cliek_jietu(self):
        filename = str(self.photoname) + '.png'  # 设置图片名字
        Frame_ = cv2.cvtColor(self.video.currentFrame, cv2.COLOR_BGR2RGB)
        cv2.imwrite('sava/' + filename, Frame_)  # 写入当前路劲下的sava文件
        print(filename + '保存成功')
        self.photoname = self.photoname + 1

    def play(self):  # 定时器的槽函数
        self.video.captureNextFrame()  # 读取每一帧
        frame = self.video.convertFrame()  # 获取当前帧
        if frame:  # 获取到则放到label控件上展示
            self.ui.label.setPixmap(frame)

    def update_time(self, data):
        self.ui.time.setText(data)


class Time(QThread):  # 继承了QT特有的多线程
    update = pyqtSignal(str)  # 设置信号

    def run(self):
        while True:
            date = QDateTime.currentDateTime()  # 创建对象
            currrntTime = date.toString("yyyy-MM-dd hh:mm:ss")  # 设置格式
            self.update.emit(str(currrntTime))  # 发信号
            time.sleep(1)


class Video():  # 摄像机类
    def __init__(self, capture):
        self.capture = capture
        self.currentFrame = None
        self.flag = True

    def change(self, msg):
        if msg == True:
            self.flag = True
        else:
            self.flag = False

    def captureNextFrame(self):
        ret, readFrame = self.capture.read()
        if ret == True:
            if self.flag == False:  # 读为灰度图
                self.currentFrame = cv2.cvtColor(readFrame, cv2.COLOR_BGR2GRAY)
            else:  # 正常
                self.currentFrame = cv2.cvtColor(readFrame, cv2.COLOR_BGR2RGB)
            # return self.convertFrame()

    def convertFrame(self):
        try:  # 不建议写异常
            # height, width, _ = self.currentFrame.shape
            # img = QImage(self.currentFrame, width, height, QImage.Format_RGB888)
            img = self.cvToQImage(self.currentFrame)  # 转为QImage
            img = QPixmap.fromImage(img)  # 转为QPixmap
            return img
        except TypeError:
            print(22222)

    def cvToQImage(self, data):  # 找的一个博主的转的函数
        channels = 1  # 设置通道默认为1
        if len(data.shape) == 3:  # 3维则将通道改为3
            channels = 3
        if channels == 3:
            img = QImage(data.data, data.shape[1], data.shape[0], data.strides[0], QImage.Format_RGB888)
            return img
        elif channels == 1:
            img = QImage(data, data.shape[1], data.shape[0], data.strides[0], QImage.Format_Indexed8)
            return img
        else:
            qDebug("ERROR: numpy.ndarray could not be converted to QImage. Channels = %d" % data.shape[2])
            return QImage()


if __name__ == '__main__':
    app = QApplication([])
    win = Win()
    win.show()
    app.exec_()

UI长这个样子

UI文件长这样

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>821</width>
    <height>621</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <widget class="QLineEdit" name="time">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>20</y>
     <width>191</width>
     <height>31</height>
    </rect>
   </property>
   <property name="styleSheet">
    <string notr="true">#time{background-color:rgba(0,0,0,0);
border-width:0;border-style:outset}</string>
   </property>
  </widget>
  <widget class="QLabel" name="label">
   <property name="geometry">
    <rect>
     <x>30</x>
     <y>70</y>
     <width>791</width>
     <height>451</height>
    </rect>
   </property>
   <property name="frameShape">
    <enum>QFrame::NoFrame</enum>
   </property>
   <property name="text">
    <string/>
   </property>
  </widget>
  <widget class="QWidget" name="layoutWidget">
   <property name="geometry">
    <rect>
     <x>20</x>
     <y>540</y>
     <width>801</width>
     <height>61</height>
    </rect>
   </property>
   <layout class="QHBoxLayout" name="horizontalLayout">
    <item>
     <widget class="QPushButton" name="jietu">
      <property name="text">
       <string>截图</string>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QPushButton" name="luxiang">
      <property name="text">
       <string>录像</string>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QComboBox" name="fbl">
      <item>
       <property name="text">
        <string>640*480</string>
       </property>
      </item>
      <item>
       <property name="text">
        <string>1280*760</string>
       </property>
      </item>
      <item>
       <property name="text">
        <string>640*360</string>
       </property>
      </item>
     </widget>
    </item>
    <item>
     <widget class="QComboBox" name="td">
      <item>
       <property name="text">
        <string>原</string>
       </property>
      </item>
      <item>
       <property name="text">
        <string>灰</string>
       </property>
      </item>
     </widget>
    </item>
   </layout>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
MATLAB 和 Python 都是广泛用于计算机视觉和图像处理的工具,其中相机标定是一个关键步骤,用于确定相机内参数(如焦距、像素大小等)和外参数(如相机中心和旋转矩阵),以便于后期进行三维重建或目标检测。 在 MATLAB 中,你可以使用 `cameraCalibrate` 函数来进行单目相机标定。这个函数会利用一组已知特征点(比如棋盘格)从图像中提取出来,然后计算相机参数。步骤大致包括: 1. **创建样本数据**:拍摄包含棋盘格图案的照片作为校准样本。 2. **特征检测**:在每个图像上运行特征检测算法,例如 Shi-Tomasi 或 SURF。 3. **匹配对应点**:基于特征点找到不同照片中的对应点。 4. **调用 calibration 函数**:输入对应的二维和三维点对,计算并保存相机参数。 在 Python 中,常用的库如 OpenCV 提供了丰富的相机标定功能。一个常见的做法是使用 `cv2.calibrateCamera` 函数,结合 `findChessboardCorners` 和 `goodFeaturesToTrack` 来完成: 1. **读取图像**:使用 `cv2.imread` 获取含有棋盘格的图片。 2. **角点检测**:`findChessboardCorners` 查找并标记棋盘格的角点。 3. **特征跟踪**:确认角点是否在不同帧间稳定。 4. **执行标定**:将所有帧的信息传递给 `calibrateCamera`,得到相机参数。 下面是简单的步骤总结: - **导入所需库**:`import cv2, numpy as np` - **初始化参数**:`criteria`, `objpoints`, `imgpoints` - **遍历图像序列**:寻找棋盘格并记录其坐标 - **标定相机**:`ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, frame_size, None, None)` - **保存参数**:`np.savez('camera_params.npz', mtx=mtx, dist=dist)`
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值