当前位置: 首页 > news >正文

python+Qt5 UOS 摄相头+麦克风测试,摄相头自动解析照片二维条码,麦克风解析音频文件

UI图片:

源代码:

# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'CameraTestFrm.ui'
#
# Created by: PyQt5 UI code generator 5.15.2
#
# 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.import time
import sys
import cv2
from PyQt5.QtCore import QTimer, pyqtSlot, Qt
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QLabel
#pip install opencv-python PyQt5
from PyQt5 import QtWidgets
from PyQt5 import QtGui
from PyQt5 import QtCore
import logging
import os
import json
import configparser
from PyQt5.QtCore import pyqtSignal
#sudo apt-get update
#sudo apt-get install libzbar0
#pip install opencv-python pyzbar解析二维条码
from pyzbar import pyzbar#解析二维条码
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
import pyaudio
import wave
import threading
#录音测试及解析音频文件库
#pip install PyAudio
#pip install SpeechRecognition
#pip install matplotlibfrom queue import Queue
from threading import Thread
import librosa
from scipy.fftpack import fft
from scipy import signal
#pip install scipy
import shutil
import platform
import subprocessclass Ui_CameraTestFrm(QWidget):update_waveform_signal = pyqtSignal(np.ndarray, np.ndarray)  # 新增信号,用于更新波形显示def __init__(self):super().__init__()self.config=configparser.ConfigParser()#创建对象self.itemName=''#项目名称self.testArgs=[]#测试参数信息self.testStandardArgs = ''  # 测试准标参数self.Err=''#错误信息self.isTestCamera=False #是否测试摄相头状态self.isTestRecord=False #是否测试麦克风self.lock = threading.Lock()  # 添加线程锁self.sn=''#sn信息#配置读取信息self.frequency_Tolerance=0#音频频率容差self.Image_Info='test'#解析照片内容self.CameraImagePath=''#摄相头采集照片上传服务器路径self.Recorded_AudioPath=''#麦克风测试采集文件上传服务器路径self.user=''#共享目录帐号self.pwd=''#共享目录密码#测试状况self.isCameraTestPass=False#摄头测试是否PASSself.isRecordTestPass=False#麦克风测试是否PASSself.cameraTestValues=''#摄相头采集的数据self.recordTestValues=0#麦克风采集的值# 生成日志信息self.logger = logging.getLogger('my_logger')  # 步骤1 创建日志记录器self.logger.setLevel(logging.DEBUG)  # 步骤2 将指定日志级别self.file_handler = logging.FileHandler('./log/log.txt')  # 步骤3 创建文件处理器self.formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')  # 步骤4 创建格式化器self.file_handler.setFormatter(self.formatter)  # 步骤4 将格式化器添加到处理器self.logger.addHandler(self.file_handler)  # 步骤5 将处理器添加到日志记录器# 读取配置self.config.read('./Conf/config.conf', encoding='utf-8')  # 读取配置文件,如果配置文件不存在则创建self.ReadJsonSnInfo('./Conf/OrderInfo.json', 'SN')#读取订单信息中SN条码信息# 读取测试配置self.itemName = self.config.get('TestItemNameArrays', 'CameraTest')self.itemFailSleepExit = int(self.config.get('TestItemWinFrmSleepExit', 'CameraTest'))  # 项目测试Fail延时退出self.testArgs = self.ReadJsonInfo('./Conf/TestArgs.json')  # 读取测试参数信息self.frequency_Tolerance=int(self.config.get('CameraTest','Frequency_Tolerance'))#采集音频频率容差self.Image_Info=self.config.get('CameraTest','Image_Info')#采集图片解析的内容self.CameraImagePath=self.config.get('CameraTest','CameraImagePath')#照片文件上传服务器路径self.Recorded_AudioPath=self.config.get('CameraTest','Recorded_AudioPath')#音频文件上传服务器路径self.user =self.config.get('CameraTest','user')#服务器共享目录帐号self.pwd=self.config.get('CameraTest','password')#服务器共享目录密码self.setupUi()  # 绘制UIif self.ReadJsonTestArgs(self.itemName)==True:#获取标准参数self.lbl_CurrentSwTest.setText('测试参数获取中..')testArgs=[]#测试参数testArgs=self.testStandardArgs.split('|')if 'True' in testArgs[0][testArgs[0].find('=')+1:]:self.isTestCamera=Trueself.label_8.setText('True')else:self.isTestCamera=Falseself.label_8.setText('False')if 'True' in testArgs[1][testArgs[1].find('=')+1:]:self.isTestRecord=Trueself.label_11.setText('True')else:self.isTestRecord=Falseself.label_11.setText('False')#判断是否测试摄相头if self.isTestCamera:self.lbl_CurrentSwTest.setText('开始摄相头测试..')self.initCamera()if self.isTestRecord:self.lbl_CurrentSwTest.setText('开始麦克风测试..')self.update_waveform_signal.connect(self.update_waveform)self.audio_queue = Queue()  # 创建一个队列用于存储录音数据self.is_recording = False  # 设置一个标志,用于控制录音线程self.running = True# ...其余初始化代码...self.audio_data_buffer = None  # 用于存储最新的音频数据self.update_timer = QTimer(self)  # 创建定时器self.update_timer.timeout.connect(self.update_waveform_on_timer)  # 连接定时器信号self.update_timer.start(100)  # 设置定时器间隔,例如100msself.start_realtime_audio_processing()  # 启动实时音频处理#判断最终测试结果时钟# 创建一个定时器来检查视频是否播放结束self.testReuslttimer = QTimer(self)self.testReuslttimer.setInterval(1000)  # 每秒检查一次self.testReuslttimer.timeout.connect(self.check_Test)self.testReuslttimer.start()def initCamera(self):# 初始化摄像头self.capture = cv2.VideoCapture(0)if not self.capture.isOpened():self.ShowLog("无法启动摄像头", False)self.label_6.setText('FAIL')self.label_6.setStyleSheet("color: red;")else:# 设置定时器更新摄像头画面self.timer = QTimer(self)self.timer.timeout.connect(self.updateFrame)self.timer.start(20)# 创建用于定期捕获和解析图像的定时器self.captureTimer = QTimer(self)self.captureTimer.timeout.connect(self.captureAndDecodeImage)self.captureTimer.start(1000)  # 设置为1秒@pyqtSlot()def updateFrame(self):ret, self.image = self.capture.read()self.image = cv2.flip(self.image, 1)self.displayImage(self.image, 1)def displayImage(self, img, window=1):qformat = QImage.Format_Indexed8if len(img.shape) == 3:  # 如果是彩色图像if img.shape[2] == 4:  # 如果是4通道(RGBA)qformat = QImage.Format_RGBA8888else:  # 如果是3通道(RGB)qformat = QImage.Format_RGB888outImage = QImage(img, img.shape[1], img.shape[0], img.strides[0], qformat)outImage = outImage.rgbSwapped()  # 对于RGB图像进行颜色转换if window == 1:self.image_label.setPixmap(QPixmap.fromImage(outImage))self.image_label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter)#照片采集def captureImage(self):flag, frame = self.capture.read()frame = cv2.flip(frame, 1)cv2.imwrite('captured_image.jpg', frame)self.ShowLog("图形采集中..", False)#print("Image saved!")def update_waveform_on_timer(self):"""定时器回调函数,用于更新波形图"""if self.audio_data_buffer is not None:signal = np.frombuffer(self.audio_data_buffer, dtype='int16')framerate = 44100time = np.linspace(0., len(signal) / framerate, num=len(signal))self.update_waveform(time, signal)self.audio_data_buffer = None  # 重置音频数据缓冲区def update_waveform(self, time_array, signal_array):"""更新音频波形显示。:param time_array: NumPy数组,表示时间点。:param signal_array: NumPy数组,表示信号强度。"""# 首先清除布局中的所有旧子项while self.QVB_LyRecord.count():child = self.QVB_LyRecord.takeAt(0)if child.widget():child.widget().deleteLater()# 生成波形图fig, ax = plt.subplots()ax.plot(time_array, signal_array)ax.set_xlabel('Time [s]')ax.set_ylabel('Amplitude')# 将波形图添加到UI布局中canvas = FigureCanvas(fig)self.QVB_LyRecord.addWidget(canvas)def update_waveform_realtime(self):with self.lock:framerate = 44100target_frequency = 500  # 目标频率(Hz)accumulated_frames = []  # 用于累积音频帧的列表while self.is_recording:if not self.audio_queue.empty():data = self.audio_queue.get()accumulated_frames.append(np.frombuffer(data, dtype='int16'))if len(accumulated_frames) * len(data) >= framerate:  # 如果累积的音频数据达到或超过1秒signal = np.concatenate(accumulated_frames)  # 合并所有音频帧accumulated_frames = []  # 清空累积的帧# 计算时间数组,确保其长度与 signal 相同time_array = np.linspace(0., len(signal) / framerate, num=len(signal))fft_spectrum = fft(signal)magnitude = np.abs(fft_spectrum)freq = np.fft.fftfreq(len(signal), 1.0 / framerate)left_frequency = freq[:int(len(freq) / 2)]left_magnitude = magnitude[:int(len(magnitude) / 2)]max_magnitude = np.argmax(left_magnitude)peak_freq = left_frequency[max_magnitude]print('max_magnitude',max_magnitude,'peak_freq',peak_freq,'abs(peak_freq - target_frequency)',abs(peak_freq - target_frequency))# 检查是否有接近目标频率的频率成分#if abs(peak_freq - target_frequency) < 10:  # 可以根据需求调整频率容差if abs(peak_freq - target_frequency) <= self.frequency_Tolerance:  # 可以根据需求调整频率容差print(f"Detected target frequency: {peak_freq} Hz")self.recordTestValues=peak_freqself.is_recording = Falseself.isRecordTestPass = Trueself.label_9.setText('PASS')self.label_9.setStyleSheet("color: green;")self.update_waveform_signal.emit(time_array, signal)if self.isTestCamera==True:self.lbl_CurrentSwTest.setText("请开始测试摄相头..")else:self.lbl_CurrentSwTest.setText("麦克风测试通过!!")breakelse:#print("No frequency component found near 500Hz")self.update_waveform_signal.emit(time_array, signal)time.sleep(1)  # 暂停一会儿def record_audio_realtime(self):self.label_12.setText("开始录音...")  # 添加的确认信息chunk = 1024format = pyaudio.paInt16channels = 1rate = 44100p = pyaudio.PyAudio()# 打开流stream = p.open(format=format, channels=channels, rate=rate, input=True, frames_per_buffer=chunk)self.is_recording = Trueframes = []  # 存储音频帧的列表while self.is_recording:data = stream.read(chunk)frames.append(data)  # 将音频帧添加到列表self.audio_queue.put(data)# 停止和关闭流stream.stop_stream()stream.close()p.terminate()if os.path.exists("recorded_audio.wav"):#删除文件os.remove("recorded_audio.wav")# 保存音频数据到文件output_filename = "recorded_audio.wav"try:wf = wave.open(output_filename, 'wb')wf.setnchannels(channels)wf.setsampwidth(p.get_sample_size(format))wf.setframerate(rate)wf.writeframes(b''.join(frames))wf.close()#print(f"录音完成,文件保存为: {output_filename}")self.label_12.setText(f"录音完成,文件保存为: {output_filename}")except Exception as e:#print(f"保存音频文件时出错: {e}")self.label_12.setText(f"保存音频文件时出错: {e}")def stop_recording(self):self.is_recording = Falsedef start_realtime_audio_processing(self):if not self.is_recording:self.is_recording = Trueaudio_thread = Thread(target=self.record_audio_realtime)audio_thread.start()waveform_thread = Thread(target=self.update_waveform_realtime)waveform_thread.start()# 新增方法:在主线程中更新音频波形def update_audio_waveform(self, audio_filename):"""更新音频波形显示"""try:fig = self.display_audio_waveform(audio_filename)canvas = FigureCanvas(fig)self.QVB_LyRecord.addWidget(canvas)self.label_12.setText("波形图已生成")  # 更新提示信息QApplication.processEvents()except Exception as e:self.label_12.setText("波形图生成失败: " + str(e))  # 更新错误信息QApplication.processEvents()def display_audio_waveform(self, audio_filename="output.wav"):"""显示音频波形"""with wave.open(audio_filename, 'r') as wf:signal = wf.readframes(-1)signal = np.frombuffer(signal, dtype='int16')framerate = wf.getframerate()time = np.linspace(0., len(signal) / framerate, num=len(signal))fig, ax = plt.subplots()ax.plot(time, signal)ax.set_xlabel('Time [s]')ax.set_ylabel('Amplitude')return figdef captureAndDecodeImage(self):ret, frame = self.capture.read()if ret:frame = cv2.flip(frame, 1)cv2.imwrite('captured_image.jpg', frame)decodedObjects = pyzbar.decode(frame)for obj in decodedObjects:data = obj.data.decode("utf-8")#print("Data", data)self.ShowLog("图像采集和解析中..", True)#if data == "test":if data==self.Image_Info:self.cameraTestValues=data#解析图片的内容self.captureTimer.stop()self.isCameraTestPass=Trueself.label_6.setText('PASS')self.label_6.setStyleSheet("color: green;")self.lbl_CurrentSwTest.setStyleSheet("background-color: rgb(85, 255, 127);color:green;")if self.isTestRecord==True:self.lbl_CurrentSwTest.setText("开始启动麦克风测试..")else:self.lbl_CurrentSwTest.setText("摄相头测试通过..")break#判断最终测试结果def check_Test(self):if self.isTestCamera and self.isTestRecord:if self.isCameraTestPass and self.isRecordTestPass:self.UpdateJsonTestArgs(self.itemName,f'Carmera={self.cameraTestValues}|Record={self.recordTestValues}','PASS')#写入日志self.copy_file_to_shared_directory('captured_image.jpg', self.CameraImagePath,self.user, self.pwd,'.jpg')  # 上传照片文件self.copy_file_to_shared_directory('recorded_audio.wav', self.Recorded_AudioPath,self.user, self.pwd,'.wav')  # 上传音频文件sys.exit(0)elif self.isTestCamera:if self.isCameraTestPass:self.UpdateJsonTestArgs(self.itemName,f'Carmera={self.cameraTestValues}','PASS')  # 写入日志self.copy_file_to_shared_directory('captured_image.jpg', self.CameraImagePath,self.user, self.pwd,'.jpg')  # 上传照片文件sys.exit(0)elif self.isTestRecord:if self.isRecordTestPass:self.UpdateJsonTestArgs(self.itemName, f'Record={self.recordTestValues}', 'PASS')  # 写入日志self.copy_file_to_shared_directory('recorded_audio.wav', self.Recorded_AudioPath,self.user, self.pwd,'.wav')  # 上传音频文件sys.exit(0)# 更新测试参数json,itemName:项目名称,readValue:读取值,testResult:测试结果def UpdateJsonTestArgs(self, itemName, readValue, testResult):try:updateTestArgs = []  # 更新的测试参数self.testArgs = self.ReadJsonInfo('./Conf/TestArgs.json')for js in self.testArgs:if itemName in js['ItemName']:js['Read'] = readValue  # 读取的值js['TestResult'] = testResult  # 测试结果updateTestArgs.append(js)else:updateTestArgs.append(js)with open("./Conf/TestArgs.json", "w") as write_file:json.dump(updateTestArgs, write_file)return Trueexcept Exception as e:self.ShowLog("Read TestArgs.json ItemName:" + itemName + " Info Err:" + str(e), False)sys.exit(1)#上传文件至服务器#source_path:拷贝的文件名称,shared_directory_path:服务器共享目录,username:用户名,password:密码def copy_file_to_shared_directory(self,source_path, shared_directory_path, username, password,extension):# 获取操作系统类型os_type = platform.system()# 如果是在Windows环境下,使用原始字符串处理路径if os_type == "Windows":shared_directory_path = shared_directory_path.replace('/', '\\')# 连接共享目录connect_command = f"net use {shared_directory_path} /user:{username} {password}"subprocess.run(connect_command, shell=True, check=True)elif os_type == "Linux" or os_type == "Darwin":# 对于Linux和MacOS,将Windows风格的共享路径转换为Unix风格的路径shared_directory_path = shared_directory_path.replace('\\', '/')if shared_directory_path.startswith('\\\\'):shared_directory_path = shared_directory_path.replace('\\\\', '/mnt/', 1)# 连接共享目录mount_command = f'mount {shared_directory_path} /mnt -o username="{username}",password="{password}"'subprocess.run(mount_command, shell=True, check=True)else:raise Exception("不支持的操作系统")# 使用os.path.join确保路径在不同操作系统中正确拼接#file_name = os.path.basename(f'{self.sn}{extension}')#destination_path = os.path.join(shared_directory_path, file_name)# 复制文件os.rename(source_path, f'{self.sn}{extension}')shutil.copy2(f'{self.sn}{extension}', '/mnt')#print(f"文件已成功复制到 {destination_path}")self.label_12.setText(f"{self.sn}{extension}'文件上传至服务器:{shared_directory_path} 成功!!")# 使用示例#source_file = '/path/to/your/source/file.txt'  # 本地源文件路径#shared_dir = '\\\\10.2.2.163\\Data\\LOG\\Microphone'  # Windows网络共享目录路径#copy_file_to_shared_directory(source_file, shared_dir)#读取json信息中MAC信息def ReadJsonSnInfo(self,fileName,KeyName):try:testArgs=self.ReadJsonInfo(fileName)for tss in testArgs:if KeyName in tss:self.sn=tss[KeyName]return Trueexcept Exception as e:self.ShowLog("Read OrderInfo.json ItemName:" + KeyName + " Info Err:" + str(e), False)def setupUi(self):self.setObjectName("CameraTestFrm")self.resize(1207, 895)icon = QtGui.QIcon()icon.addPixmap(QtGui.QPixmap("IMAGE/Subtract.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)self.setWindowIcon(icon)self.gridLayout = QtWidgets.QGridLayout(self)self.gridLayout.setObjectName("gridLayout")self.verticalLayout = QtWidgets.QVBoxLayout()self.verticalLayout.setObjectName("verticalLayout")self.horizontalLayout = QtWidgets.QHBoxLayout()self.horizontalLayout.setObjectName("horizontalLayout")self.verticalLayout_3 = QtWidgets.QVBoxLayout()self.verticalLayout_3.setObjectName("verticalLayout_3")self.horizontalLayout_3 = QtWidgets.QHBoxLayout()self.horizontalLayout_3.setObjectName("horizontalLayout_3")self.label_3 = QtWidgets.QLabel(self)self.label_3.setText("")self.label_3.setPixmap(QtGui.QPixmap("IMAGE/logo.jpg"))self.label_3.setAlignment(QtCore.Qt.AlignCenter)self.label_3.setObjectName("label_3")self.horizontalLayout_3.addWidget(self.label_3)self.label_2 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(14)self.label_2.setFont(font)self.label_2.setStyleSheet("background-color: rgb(170, 170, 127);\n"
"color: rgb(255, 255, 255);")self.label_2.setAlignment(QtCore.Qt.AlignCenter)self.label_2.setObjectName("label_2")self.horizontalLayout_3.addWidget(self.label_2)self.verticalLayout_3.addLayout(self.horizontalLayout_3)self.lbl_CurrentSwTest = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(14)self.lbl_CurrentSwTest.setFont(font)self.lbl_CurrentSwTest.setStyleSheet("background-color: rgb(85, 255, 127);")self.lbl_CurrentSwTest.setAlignment(QtCore.Qt.AlignCenter)self.lbl_CurrentSwTest.setObjectName("lbl_CurrentSwTest")self.verticalLayout_3.addWidget(self.lbl_CurrentSwTest)self.horizontalLayout.addLayout(self.verticalLayout_3)self.verticalLayout_4 = QtWidgets.QVBoxLayout()self.verticalLayout_4.setObjectName("verticalLayout_4")self.horizontalLayout_4 = QtWidgets.QHBoxLayout()self.horizontalLayout_4.setObjectName("horizontalLayout_4")self.verticalLayout_8 = QtWidgets.QVBoxLayout()self.verticalLayout_8.setObjectName("verticalLayout_8")self.label = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(12)self.label.setFont(font)self.label.setStyleSheet("background-color: rgb(255, 170, 127);\n"
"color: rgb(255, 255, 255);")self.label.setAlignment(QtCore.Qt.AlignCenter)self.label.setObjectName("label")self.verticalLayout_8.addWidget(self.label)self.label_5 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(12)self.label_5.setFont(font)self.label_5.setAlignment(QtCore.Qt.AlignCenter)self.label_5.setObjectName("label_5")self.verticalLayout_8.addWidget(self.label_5)self.label_4 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(12)self.label_4.setFont(font)self.label_4.setAlignment(QtCore.Qt.AlignCenter)self.label_4.setObjectName("label_4")self.verticalLayout_8.addWidget(self.label_4)self.horizontalLayout_4.addLayout(self.verticalLayout_8)self.verticalLayout_9 = QtWidgets.QVBoxLayout()self.verticalLayout_9.setObjectName("verticalLayout_9")self.label_7 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(12)self.label_7.setFont(font)self.label_7.setStyleSheet("background-color: rgb(255, 170, 127);\n"
"color: rgb(255, 255, 255);")self.label_7.setAlignment(QtCore.Qt.AlignCenter)self.label_7.setObjectName("label_7")self.verticalLayout_9.addWidget(self.label_7)self.label_8 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(12)self.label_8.setFont(font)self.label_8.setAlignment(QtCore.Qt.AlignCenter)self.label_8.setObjectName("label_8")self.verticalLayout_9.addWidget(self.label_8)self.label_6 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(12)self.label_6.setFont(font)self.label_6.setAlignment(QtCore.Qt.AlignCenter)self.label_6.setObjectName("label_6")self.verticalLayout_9.addWidget(self.label_6)self.horizontalLayout_4.addLayout(self.verticalLayout_9)self.verticalLayout_7 = QtWidgets.QVBoxLayout()self.verticalLayout_7.setObjectName("verticalLayout_7")self.label_10 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(12)self.label_10.setFont(font)self.label_10.setStyleSheet("background-color: rgb(255, 170, 127);\n"
"color: rgb(255, 255, 255);")self.label_10.setAlignment(QtCore.Qt.AlignCenter)self.label_10.setObjectName("label_10")self.verticalLayout_7.addWidget(self.label_10)self.label_11 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(12)self.label_11.setFont(font)self.label_11.setAlignment(QtCore.Qt.AlignCenter)self.label_11.setObjectName("label_11")self.verticalLayout_7.addWidget(self.label_11)self.label_9 = QtWidgets.QLabel(self)font = QtGui.QFont()font.setPointSize(12)self.label_9.setFont(font)self.label_9.setAlignment(QtCore.Qt.AlignCenter)self.label_9.setObjectName("label_9")self.verticalLayout_7.addWidget(self.label_9)self.horizontalLayout_4.addLayout(self.verticalLayout_7)self.verticalLayout_4.addLayout(self.horizontalLayout_4)self.horizontalLayout.addLayout(self.verticalLayout_4)self.verticalLayout.addLayout(self.horizontalLayout)self.horizontalLayout_2 = QtWidgets.QHBoxLayout()#self.horizontalLayout_2 = QtWidgets.QVBoxLayout()self.horizontalLayout_2.setObjectName("horizontalLayout_2")self.QVB_LyCamera = QtWidgets.QVBoxLayout()self.QVB_LyCamera.setObjectName("QVB_LyCamera")self.horizontalLayout_2.addLayout(self.QVB_LyCamera, 1)  # 指定比例为1# 创建显示摄像头画面的 QLabelself.image_label = QLabel(self)self.QVB_LyCamera.addWidget(self.image_label)self.QVB_LyRecord = QtWidgets.QVBoxLayout()self.QVB_LyRecord.setObjectName("QVB_LyRecord")self.horizontalLayout_2.addLayout(self.QVB_LyRecord, 1)  # 指定比例为1self.verticalLayout.addLayout(self.horizontalLayout_2)self.verticalLayout_2 = QtWidgets.QVBoxLayout()self.verticalLayout_2.setObjectName("verticalLayout_2")self.groupBox = QtWidgets.QGroupBox(self)font = QtGui.QFont()font.setPointSize(13)font.setBold(True)font.setWeight(75)self.groupBox.setFont(font)self.groupBox.setStyleSheet("color: rgb(255, 255, 255);\n"
"background-color: rgb(170, 170, 127);")self.groupBox.setAlignment(QtCore.Qt.AlignCenter)self.groupBox.setObjectName("groupBox")self.gridLayout_2 = QtWidgets.QGridLayout(self.groupBox)self.gridLayout_2.setObjectName("gridLayout_2")self.label_12 = QtWidgets.QLabel(self.groupBox)font = QtGui.QFont()font.setPointSize(12)self.label_12.setFont(font)self.label_12.setStyleSheet("background-color: rgb(0, 0, 0);\n"
"color: rgb(255, 255, 127);")self.label_12.setAlignment(QtCore.Qt.AlignCenter)self.label_12.setObjectName("label_12")self.gridLayout_2.addWidget(self.label_12, 0, 0, 1, 1)self.verticalLayout_2.addWidget(self.groupBox)self.verticalLayout.addLayout(self.verticalLayout_2)self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1)self.retranslateUi()QtCore.QMetaObject.connectSlotsByName(self)self.setWindowFlags(QtCore.Qt.WindowMinimizeButtonHint | QtCore.Qt.WindowCloseButtonHint)  # 只显示最小化按钮和关闭按钮def retranslateUi(self):_translate = QtCore.QCoreApplication.translateself.setWindowTitle(_translate("CameraTestFrm", "CameraTestFrm"))self.label_2.setText(_translate("CameraTestFrm", "控制过程"))self.lbl_CurrentSwTest.setText(_translate("CameraTestFrm", "Wait.."))self.label.setText(_translate("CameraTestFrm", "测试项目名称"))self.label_5.setText(_translate("CameraTestFrm", "配置参数"))self.label_4.setText(_translate("CameraTestFrm", "测试结果"))self.label_7.setText(_translate("CameraTestFrm", "摄相头"))self.label_8.setText(_translate("CameraTestFrm", "N/A"))self.label_6.setText(_translate("CameraTestFrm", "N/A"))self.label_10.setText(_translate("CameraTestFrm", "麦克风"))self.label_11.setText(_translate("CameraTestFrm", "N/A"))self.label_9.setText(_translate("CameraTestFrm", "N/A"))self.groupBox.setTitle(_translate("CameraTestFrm", "人机交互提示"))self.label_12.setText(_translate("CameraTestFrm", "摄相头测试,请将测试治具,二维条码字样对准摄相头!!"))# 读取json信息def ReadJsonInfo(self, fileName):try:if os.path.exists(fileName):f = open(fileName, 'r', encoding='utf-8')return json.loads(f.read())except Exception as e:self.ShowLog("Read " + fileName + " Err:" + str(e), False)sys.exit(1)# 读取项目参数信息,itemName:项目名称def ReadJsonTestArgs(self, itemName):try:self.testArgs = self.ReadJsonInfo('./Conf/TestArgs.json')for js in self.testArgs:if itemName in js['ItemName']:self.testStandardArgs = js['Standard']return Trueself.ShowLog('Read TestArgs.json ItemName:' + itemName + ' Info Is Empty!!', False)sys.exit(1)except Exception as e:self.ShowLog("Read TestArgs.json ItemName:" + itemName + " Info Err:" + str(e), False)sys.exit(1)# 打印的信息def ShowLog(self, log, isPass):try:if isPass == True:self.lbl_CurrentSwTest.setStyleSheet("background-color: rgb(85, 255, 127);color:green;")self.logger.info(str(log))self.lbl_CurrentSwTest.setText("TEST PASS")else:self.lbl_CurrentSwTest.setStyleSheet("background-color: rgb(85, 255, 127);color: red;")self.logger.error(str(log))self.lbl_CurrentSwTest.setText(log)except Exception as e:print("\033[1;31m" + str(e) + " \033[0m")sys.exit(1)# 启动线重脚本def TestThread(self):pass# self.t_autoplay=Thread(target=self.Test)# self.t_autoplay.start()#手动关闭窗口def closeEvent(self, event):# 告知线程停止运行self.running = False# 等待线程结束if self.microphone_test_thread is not None:self.microphone_test_thread.join()# 其他关闭操作if self.capture.isOpened():self.capture.release()event.accept()sys.exit(1)# 定义一个函数使得函数窗口居中显示def Center(self):# 获取屏幕尺寸screen_geometry = app.desktop().availableGeometry()# 计算窗口居中位置x = (screen_geometry.width() - self.width()) // 2y = (screen_geometry.height() - self.height()) // 2# 设置窗口位置self.move(x, y)if __name__=='__main__':app=QApplication(sys.argv)win=Ui_CameraTestFrm()win.Center()  # 居中win.show()#win.start_realtime_audio_processing()  # 启动实时音频处理sys.exit(app.exec_())

相关文章:

python+Qt5 UOS 摄相头+麦克风测试,摄相头自动解析照片二维条码,麦克风解析音频文件

UI图片&#xff1a; 源代码&#xff1a; # -*- coding: utf-8 -*-# Form implementation generated from reading ui file CameraTestFrm.ui # # Created by: PyQt5 UI code generator 5.15.2 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is…...

MongoDB日期存储与查询、@Query、嵌套字段查询实战总结

缘由 MongoDB数据库如下&#xff1a; 如上截图&#xff0c;使用MongoDB客户端工具DataGrip&#xff0c;在filter过滤框输入{ profiles.alias: 逆天子, profiles.channel: }&#xff0c;即可实现昵称和渠道多个嵌套字段过滤查询。 现有业务需求&#xff1a;用Java代码来查询…...

Windows版本Node.js常见问题及操作解决方式(小白入门必备)

npm i时ERROR:reason: certificate has expired问题 https://blog.csdn.net/m0_73360677/article/details/135774500 # 1.取消ssl验证&#xff1b;npm config set strict-ssl false#这个方法一般可以直接解决问题&#xff0c;如不能请尝试第二种方法# 2.更换npm镜像源&#x…...

09.Elasticsearch应用(九)

Elasticsearch应用&#xff08;九&#xff09; 1.搜索结果处理包括什么 排序分页高亮返回指定字段 2.排序 介绍 Elasticsearch支持对搜索结果排序&#xff0c;默认是根据相关度算分来排序 支持排序的字段 keyword数值地理坐标日期类型 排序语法 GET /[索引名称]/_sear…...

ROS2常用命令工具

ROS2常用命令工具 包管理工具ros2 pkg ros2 pkg create ros2 pkg create --build-type ament_python pkg_name rclpy std_msgs sensor_msgs –build-type : C或者C ament_cmake &#xff0c;Python ament_python pkg_name &#xff1a;创建功能包的名字 rclpy std_msgs sens…...

Linux之快速入门

一、Linux目录结构 从Windows转到Linux最不习惯的是什么&#xff1a; 目录结构 Windows会分盘&#xff0c;想怎么放东西就怎么放东西&#xff0c;好处自由&#xff0c;缺点容易乱 Linux有自己的目录结构&#xff0c;不能随随便便放东西 /&#xff1a;根目录/bin:二进制文件&…...

C语言——操作符详解1

目录 1. 操作符的分类2. 二进制和进制转换2.1 二进制的概念2.2 二进制转十进制2.3 十进制转二进制2.4 二进制转八进制和十六进制2.4.1 二进制转八进制二进制转十六进制 3. 原码、反码和补码4. 移位操作符4.1 左移操作符4.2 右移操作符 5. 位操作符5.1 &5.2 |5.3 ^5.4 ~ 1. …...

C++学习| QT快速入门

QT简单入门 QT Creater创建QT项目选择项目类型——不同项目类型的区别输入项目名字和路径选择合适的构建系统——不同构建系统的却别选择合适的类——QT基本类之间的关系Translation File选择构建套件——MinGW和MSVC的区别 简单案例&#xff1a;加法器设计界面——构建加法器界…...

Android App开发-简单控件(1)——文本显示

本章介绍了App开发常见的几类简单控件的用法&#xff0c;主要包括&#xff1a;显示文字的文本视图、容纳视图的常用布局、响应点击的按钮控件、显示图片的图像视图等。然后结合本章所涉及的知识&#xff0c;完成一个实战项目“简单计算器”的设计与实现。 1.1 文本显示 本节介绍…...

[GYCTF2020]Ezsqli1

打开环境&#xff0c;下面有个提交表单 提交1&#xff0c;2有正确的查询结果&#xff0c;3以后都显示Error Occured When Fetch Result. 题目是sql&#xff0c;应该考察的是sql注入 简单fuzz一下 发现information_schema被过滤了&#xff0c;猜测是盲注了。 测试发现只要有东…...

【npm包】如何发布自己的npm包

随着Node.js的普及&#xff0c;npm&#xff08;Node Package Manager&#xff09;已成为JavaScript开发者中不可或缺的一部分。发布自己的npm包&#xff0c;不仅可以将自己的项目分享给更多人&#xff0c;还可以为社区做出贡献。本文将详细介绍如何从零开始发布自己的npm包。 …...

《WebKit技术内幕》学习之十五(2):Web前端的未来

2 嵌入式应用模式 2.1 嵌入式模式 读者可能会奇怪本章重点表达的是Web应用和Web运行平台&#xff0c;为什么会介绍嵌入式模式&#xff08;Embedded Mode&#xff09;呢&#xff1f;这是因为很多Web运行平台是基于嵌入式模式的接口开发出来的&#xff0c;所以这里先解释一下什…...

【教学类-综合练习-11】20240116 大4班 最后一次

只有图片 加了两条链接 背景需求 年终了&#xff0c;清理库存&#xff0c;各种打印的题型纸都拿出来&#xff0c;当个别化学习材料 教学过程&#xff1a; 时间&#xff1a;2024年1月5日下午 班级&#xff1a;大4班&#xff08;额外带班 真正的最后一次大班&#xff09; 人…...

【阻塞队列】阻塞队列的模拟实现及在生产者和消费者模型上的应用

文章目录 &#x1f4c4;前言一. 阻塞队列初了解&#x1f346;1. 什么是阻塞队列&#xff1f;&#x1f345;2. 为什么使用阻塞队列&#xff1f;&#x1f966;3. Java标准库中阻塞队列的实现 二. 阻塞队列的模拟实现&#x1f35a;1. 实现普通队列&#x1f365;2. 实现队列的阻塞功…...

Cocos Creator使用VS Code调试代码配置

创建项目 首先我们先打开cocos创建一个项目 随便添加一个Cube和脚本&#xff0c;然后保存场景&#xff1a; 添加Chrome Debug配置 在Cocos 中选择添加Chrome Debug配置 然后再VS Code中就可以看到有一个cocos launch Chrome&#xff1a; 然后&#xff0c;就可以按快捷键F…...

【投稿优惠|EI优质会议】2024年材料化学与清洁能源国际学术会议(IACMCCE 2024)

【投稿优惠|优质会议】2024年材料化学与清洁能源国际学术会议(IACMCCE 2024) 2024 International Conference Environmental Engineering and Mechatronics Integration(ICEEMI 2024) 一、【会议简介】 随着全球能源需求的不断增长&#xff0c;清洁能源的研究与应用成为了国际…...

ubuntu设置右键打开terminator、code

前言&#xff1a; 这里介绍一种直接右键打开本地目录下的terminator和vscode的方法。 一&#xff1a;右键打开terminator 1.安装terminator sudo apt install terminator 2.安装nautilus-actions filemanager-actions sudo apt-get install nautilus-actions filemanager…...

PHP AES加解密:用代码为数据加上保护的盾牌

在网络世界里&#xff0c;数据的传输和存储是一个敏感而重要的问题。为了保护数据的安全性&#xff0c;加密算法是一项不可或缺的技术。而在PHP中&#xff0c;AES&#xff08;Advanced Encryption Standard&#xff09;加解密算法是一种常用的选择。本篇博客将深入解析PHP中的A…...

Socket实现服务器和客户端

Socket 编程是一种用于在网络上进行通信的编程方法&#xff0c;以下代码可以实现在不同主机之间传输数据。 Socket 编程中服务器端和客户端的基本步骤&#xff1a;服务器端步骤&#xff1a; 1.创建 Socket&#xff1a; int serverSocket socket(AF_INET, SOCK_STREAM, 0);…...

智能GPT图书管理系统(SpringBoot2+Vue2)、接入GPT接口,支持AI智能图书馆

☀️技术栈介绍 ☃️前端主要技术栈 技术作用版本Vue提供前端交互2.6.14Vue-Router路由式编程导航3.5.1Element-UI模块组件库&#xff0c;绘制界面2.4.5Axios发送ajax请求给后端请求数据1.2.1core-js兼容性更强&#xff0c;浏览器适配3.8.3swiper轮播图插件&#xff08;快速实…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

windows系统MySQL安装文档

概览&#xff1a;本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容&#xff0c;为学习者提供全面的操作指导。关键要点包括&#xff1a; 解压 &#xff1a;下载完成后解压压缩包&#xff0c;得到MySQL 8.…...

uniapp 实现腾讯云IM群文件上传下载功能

UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中&#xff0c;群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS&#xff0c;在uniapp中实现&#xff1a; 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...

【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?

FTP&#xff08;File Transfer Protocol&#xff09;本身是一个基于 TCP 的协议&#xff0c;理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况&#xff0c;主要原因包括&#xff1a; ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...

QT开发技术【ffmpeg + QAudioOutput】音乐播放器

一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下&#xff0c;音视频内容犹如璀璨繁星&#xff0c;点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频&#xff0c;到在线课堂中知识渊博的专家授课&#xff0c;再到影视平台上扣人心弦的高清大片&#xff0c;音…...

【HarmonyOS 5】鸿蒙中Stage模型与FA模型详解

一、前言 在HarmonyOS 5的应用开发模型中&#xff0c;featureAbility是旧版FA模型&#xff08;Feature Ability&#xff09;的用法&#xff0c;Stage模型已采用全新的应用架构&#xff0c;推荐使用组件化的上下文获取方式&#xff0c;而非依赖featureAbility。 FA大概是API7之…...

yaml读取写入常见错误 (‘cannot represent an object‘, 117)

错误一&#xff1a;yaml.representer.RepresenterError: (‘cannot represent an object’, 117) 出现这个问题一直没找到原因&#xff0c;后面把yaml.safe_dump直接替换成yaml.dump&#xff0c;确实能保存&#xff0c;但出现乱码&#xff1a; 放弃yaml.dump&#xff0c;又切…...

js 设置3秒后执行

如何在JavaScript中延迟3秒执行操作 在JavaScript中&#xff0c;要设置一个操作在指定延迟后&#xff08;例如3秒&#xff09;执行&#xff0c;可以使用 setTimeout 函数。setTimeout 是JavaScript的核心计时器方法&#xff0c;它接受两个参数&#xff1a; 要执行的函数&…...

运行vue项目报错 errors and 0 warnings potentially fixable with the `--fix` option.

报错 找到package.json文件 找到这个修改成 "lint": "eslint --fix --ext .js,.vue src" 为elsint有配置结尾换行符&#xff0c;最后运行&#xff1a;npm run lint --fix...