持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情
之前的博客中制作了一款录屏软件,但是只能录制全屏,然而市面上许多录屏软件还能选择区域进行录制,感觉两者差不多,难度相差也不大,于是更新一下之前的代码,让这款录屏软件既可以全屏录制,也可以自由选择区域进行录制。
首先,界面相比于之前肯定要做一下调整,调整后的界面如下。
界面文件如下
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'screenCapture.ui'
#
# Created by: PyQt5 UI code generator 5.15.6
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(231, 210)
self.horizontalLayoutWidget = QtWidgets.QWidget(Form)
self.horizontalLayoutWidget.setGeometry(QtCore.QRect(10, 10, 211, 81))
self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.horizontalLayoutWidget)
self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
self.horizontalLayout.setObjectName("horizontalLayout")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
self.pushButton = QtWidgets.QPushButton(self.horizontalLayoutWidget)
self.pushButton.setObjectName("pushButton")
self.verticalLayout.addWidget(self.pushButton)
self.pushButton_2 = QtWidgets.QPushButton(self.horizontalLayoutWidget)
self.pushButton_2.setObjectName("pushButton_2")
self.verticalLayout.addWidget(self.pushButton_2)
self.label = QtWidgets.QLabel(self.horizontalLayoutWidget)
self.label.setLayoutDirection(QtCore.Qt.LeftToRight)
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setObjectName("label")
self.verticalLayout.addWidget(self.label)
self.horizontalLayout.addLayout(self.verticalLayout)
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.pushButton_3 = QtWidgets.QPushButton(self.horizontalLayoutWidget)
self.pushButton_3.setObjectName("pushButton_3")
self.verticalLayout_2.addWidget(self.pushButton_3)
self.pushButton_4 = QtWidgets.QPushButton(self.horizontalLayoutWidget)
self.pushButton_4.setObjectName("pushButton_4")
self.verticalLayout_2.addWidget(self.pushButton_4)
self.label_3 = QtWidgets.QLabel(self.horizontalLayoutWidget)
self.label_3.setLayoutDirection(QtCore.Qt.LeftToRight)
self.label_3.setAlignment(QtCore.Qt.AlignCenter)
self.label_3.setObjectName("label_3")
self.verticalLayout_2.addWidget(self.label_3)
self.horizontalLayout.addLayout(self.verticalLayout_2)
self.verticalLayoutWidget_3 = QtWidgets.QWidget(Form)
self.verticalLayoutWidget_3.setGeometry(QtCore.QRect(10, 90, 211, 91))
self.verticalLayoutWidget_3.setObjectName("verticalLayoutWidget_3")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.verticalLayoutWidget_3)
self.verticalLayout_3.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.label_2 = QtWidgets.QLabel(self.verticalLayoutWidget_3)
self.label_2.setText("")
self.label_2.setObjectName("label_2")
self.verticalLayout_3.addWidget(self.label_2)
self.retranslateUi(Form)
self.pushButton.clicked.connect(Form.startCapture) # type: ignore
self.pushButton_2.clicked.connect(Form.stopCapture) # type: ignore
self.pushButton_3.clicked.connect(Form.startROICapture) # type: ignore
self.pushButton_4.clicked.connect(Form.stopROICapture) # type: ignore
QtCore.QMetaObject.connectSlotsByName(Form)
def retranslateUi(self, Form):
_translate = QtCore.QCoreApplication.translate
Form.setWindowTitle(_translate("Form", "Form"))
self.pushButton.setText(_translate("Form", "全屏录制"))
self.pushButton_2.setText(_translate("Form", "结束录制"))
self.label.setText(_translate("Form", "录制时自动隐藏窗口"))
self.pushButton_3.setText(_translate("Form", "选择区域录制"))
self.pushButton_4.setText(_translate("Form", "结束区域录制"))
self.label_3.setText(_translate("Form", "有问题评论区留言"))
界面简洁,本身功能就比较单一,没必要花里胡哨
然后是主函数代码
from screenCapture import Ui_Form
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys
import cv2
from PIL import ImageGrab
import numpy as np
import time
from datetime import datetime
global img
global point1, point2
class MainWindow(QMainWindow, Ui_Form):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent=parent)
self.setupUi(self)
self.MyTimer = QTimer()
self.MyTimer1 = QTimer()
self.name = None
self.ROIname = None
def startCapture(self):
self.countSave = 0
self.fps = 13
self.flag = False
self.count = 1
self.name = datetime.now().strftime('%Y-%m-%d %H-%M-%S')
self.screen = ImageGrab.grab()
self.width, self.high = self.screen.size
self.fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')
self.video = cv2.VideoWriter('%s.avi' % self.name, self.fourcc, self.fps, (self.width, self.high))
print('开始录制!')
self.label_2.setText("录制中!")
self.start_time = time.time()
self.showMinimized()
self.MyTimer.start(30)
self.MyTimer.timeout.connect(self.video_record)
def video_record(self): # 录入视频
if self.flag:
print("录制结束!")
self.final_time = time.time()
self.video.release()
if self.count == 1:
self.label_2.setText("录制中.")
elif self.count == 2:
self.label_2.setText("录制中..")
else:
self.label_2.setText("录制中...")
self.count += 1
self.count = self.count % 4
self.im = ImageGrab.grab()
frame = cv2.cvtColor(np.array(self.im), cv2.COLOR_RGB2BGR)
self.video.write(frame)
def stopCapture(self):
if self.MyTimer.isActive():
self.MyTimer.stop()
self.label_2.setText("录制结束\n录制文件名:{}".format(self.name))
if self.name is None:
self.label_2.setText("视频还未录制!")
else:
self.flag = True
def startROICapture(self):
curScreen = ImageGrab.grab() # 获取屏幕对象
point1, point2 = select_roi(curScreen)
self.showMinimized()
self.min_x = min(point1[0], point2[0])
self.min_y = min(point1[1], point2[1])
self.max_x = max(point1[0], point2[0])
self.max_y = max(point1[1], point2[1])
height, width = self.max_y - self.min_y, self.max_x - self.min_x
print(height, width)
fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')
self.ROIname = datetime.now().strftime('%Y-%m-%d %H-%M-%S') + ".avi"
self.video1 = cv2.VideoWriter(self.ROIname, fourcc, 13, (width, height))
self.label_2.setText("录制中...")
self.MyTimer1.start(30)
self.MyTimer1.timeout.connect(self.ROIRect)
def ROIRect(self):
captureImage = ImageGrab.grab() # 抓取屏幕
frame = cv2.cvtColor(np.array(captureImage), cv2.COLOR_RGB2BGR)
frame = frame[self.min_y:self.max_y, self.min_x:self.max_x, :]
self.video1.write(frame)
def stopROICapture(self):
if self.MyTimer1.isActive():
self.MyTimer1.stop()
self.label_2.setText("录制结束\n录制文件名:{}".format(self.ROIname))
if self.ROIname is None:
self.label_2.setText("视频还未录制!")
# 鼠标事件
def on_mouse(event, x, y, flags, key):
global img, point1, point2
img2 = img.copy()
if event == cv2.EVENT_LBUTTONDOWN: # 左键点击
point1 = (x, y)
cv2.circle(img2, point1, 10, (0, 255, 0), thickness=2)
cv2.imshow('image', img2)
elif event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_LBUTTON): # 按住左键拖曳
cv2.rectangle(img2, point1, (x, y), (255, 0, 0), thickness=2)
cv2.imshow('image', img2)
elif event == cv2.EVENT_LBUTTONUP: # 左键释放
point2 = (x, y)
cv2.rectangle(img2, point1, point2, (0, 0, 255), thickness=2)
cv2.imshow('image', img2)
# 选择ROI区域
def select_roi(frame):
global img, point1, point2
img = cv2.cvtColor(np.array(frame), cv2.COLOR_RGB2BGR)
winname = 'image'
cv2.namedWindow(winname, cv2.WINDOW_NORMAL)
cv2.setWindowProperty(winname, cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)
cv2.setMouseCallback(winname, on_mouse)
cv2.imshow(winname, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
return point1, point2
if __name__ == "__main__":
app = QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec_())
最后的结果跟录制全屏的结果一样,都是录制结束后输出录制文件名称,结果如下
最后就是使用下面命令打包成exe文件了,可以随时使用
pyinstaller -F -w 文件名