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图片: 源代码: # -*- 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数据库如下: 如上截图,使用MongoDB客户端工具DataGrip,在filter过滤框输入{ profiles.alias: 逆天子, profiles.channel: },即可实现昵称和渠道多个嵌套字段过滤查询。 现有业务需求:用Java代码来查询…...
Windows版本Node.js常见问题及操作解决方式(小白入门必备)
npm i时ERROR:reason: certificate has expired问题 https://blog.csdn.net/m0_73360677/article/details/135774500 # 1.取消ssl验证;npm config set strict-ssl false#这个方法一般可以直接解决问题,如不能请尝试第二种方法# 2.更换npm镜像源&#x…...
09.Elasticsearch应用(九)
Elasticsearch应用(九) 1.搜索结果处理包括什么 排序分页高亮返回指定字段 2.排序 介绍 Elasticsearch支持对搜索结果排序,默认是根据相关度算分来排序 支持排序的字段 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 ,Python ament_python pkg_name :创建功能包的名字 rclpy std_msgs sens…...
Linux之快速入门
一、Linux目录结构 从Windows转到Linux最不习惯的是什么: 目录结构 Windows会分盘,想怎么放东西就怎么放东西,好处自由,缺点容易乱 Linux有自己的目录结构,不能随随便便放东西 /:根目录/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的区别 简单案例:加法器设计界面——构建加法器界…...
Android App开发-简单控件(1)——文本显示
本章介绍了App开发常见的几类简单控件的用法,主要包括:显示文字的文本视图、容纳视图的常用布局、响应点击的按钮控件、显示图片的图像视图等。然后结合本章所涉及的知识,完成一个实战项目“简单计算器”的设计与实现。 1.1 文本显示 本节介绍…...
[GYCTF2020]Ezsqli1
打开环境,下面有个提交表单 提交1,2有正确的查询结果,3以后都显示Error Occured When Fetch Result. 题目是sql,应该考察的是sql注入 简单fuzz一下 发现information_schema被过滤了,猜测是盲注了。 测试发现只要有东…...
【npm包】如何发布自己的npm包
随着Node.js的普及,npm(Node Package Manager)已成为JavaScript开发者中不可或缺的一部分。发布自己的npm包,不仅可以将自己的项目分享给更多人,还可以为社区做出贡献。本文将详细介绍如何从零开始发布自己的npm包。 …...
《WebKit技术内幕》学习之十五(2):Web前端的未来
2 嵌入式应用模式 2.1 嵌入式模式 读者可能会奇怪本章重点表达的是Web应用和Web运行平台,为什么会介绍嵌入式模式(Embedded Mode)呢?这是因为很多Web运行平台是基于嵌入式模式的接口开发出来的,所以这里先解释一下什…...
【教学类-综合练习-11】20240116 大4班 最后一次
只有图片 加了两条链接 背景需求 年终了,清理库存,各种打印的题型纸都拿出来,当个别化学习材料 教学过程: 时间:2024年1月5日下午 班级:大4班(额外带班 真正的最后一次大班) 人…...
【阻塞队列】阻塞队列的模拟实现及在生产者和消费者模型上的应用
文章目录 📄前言一. 阻塞队列初了解🍆1. 什么是阻塞队列?🍅2. 为什么使用阻塞队列?🥦3. Java标准库中阻塞队列的实现 二. 阻塞队列的模拟实现🍚1. 实现普通队列🍥2. 实现队列的阻塞功…...
Cocos Creator使用VS Code调试代码配置
创建项目 首先我们先打开cocos创建一个项目 随便添加一个Cube和脚本,然后保存场景: 添加Chrome Debug配置 在Cocos 中选择添加Chrome Debug配置 然后再VS Code中就可以看到有一个cocos launch Chrome: 然后,就可以按快捷键F…...
【投稿优惠|EI优质会议】2024年材料化学与清洁能源国际学术会议(IACMCCE 2024)
【投稿优惠|优质会议】2024年材料化学与清洁能源国际学术会议(IACMCCE 2024) 2024 International Conference Environmental Engineering and Mechatronics Integration(ICEEMI 2024) 一、【会议简介】 随着全球能源需求的不断增长,清洁能源的研究与应用成为了国际…...
ubuntu设置右键打开terminator、code
前言: 这里介绍一种直接右键打开本地目录下的terminator和vscode的方法。 一:右键打开terminator 1.安装terminator sudo apt install terminator 2.安装nautilus-actions filemanager-actions sudo apt-get install nautilus-actions filemanager…...
PHP AES加解密:用代码为数据加上保护的盾牌
在网络世界里,数据的传输和存储是一个敏感而重要的问题。为了保护数据的安全性,加密算法是一项不可或缺的技术。而在PHP中,AES(Advanced Encryption Standard)加解密算法是一种常用的选择。本篇博客将深入解析PHP中的A…...
Socket实现服务器和客户端
Socket 编程是一种用于在网络上进行通信的编程方法,以下代码可以实现在不同主机之间传输数据。 Socket 编程中服务器端和客户端的基本步骤:服务器端步骤: 1.创建 Socket: int serverSocket socket(AF_INET, SOCK_STREAM, 0);…...
智能GPT图书管理系统(SpringBoot2+Vue2)、接入GPT接口,支持AI智能图书馆
☀️技术栈介绍 ☃️前端主要技术栈 技术作用版本Vue提供前端交互2.6.14Vue-Router路由式编程导航3.5.1Element-UI模块组件库,绘制界面2.4.5Axios发送ajax请求给后端请求数据1.2.1core-js兼容性更强,浏览器适配3.8.3swiper轮播图插件(快速实…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
在Ubuntu中设置开机自动运行(sudo)指令的指南
在Ubuntu系统中,有时需要在系统启动时自动执行某些命令,特别是需要 sudo权限的指令。为了实现这一功能,可以使用多种方法,包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法,并提供…...
【HTTP三个基础问题】
面试官您好!HTTP是超文本传输协议,是互联网上客户端和服务器之间传输超文本数据(比如文字、图片、音频、视频等)的核心协议,当前互联网应用最广泛的版本是HTTP1.1,它基于经典的C/S模型,也就是客…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...
【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...
