首页 > 其他分享 >使用Axis监控监视窑炉溢流口翻板动作 Pyhon实例

使用Axis监控监视窑炉溢流口翻板动作 Pyhon实例

时间:2024-12-11 17:13:40浏览次数:6  
标签:layout Pyhon self 翻板 zoom time input image Axis

  1 import sys
  2 from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QGridLayout, QPushButton, QLabel, QLineEdit, QTextEdit
  3 from PyQt5.QtGui import QImage, QPixmap, QPainter, QPen, QColor, QPalette
  4 from PyQt5.QtMultimedia import QSound
  5 from PyQt5.QtCore import Qt, QThread, pyqtSignal, pyqtSlot, QTimer,QMetaObject, QMetaMethod
  6 import cv2
  7 import time
  8 import cProfile
  9 from datetime import datetime
 10 import numpy as np
 11 
 12 class VideoThread(QThread):
 13     change_pixmap_signal = pyqtSignal(QImage)
 14     change_zoom_signal = pyqtSignal(QImage)
 15     change_fps_signal = pyqtSignal(str)
 16     change_process_time_signal = pyqtSignal(float)
 17     motion_detected_signal = pyqtSignal(bool, np.ndarray)
 18     error_signal = pyqtSignal(str)
 19     connection_status_signal = pyqtSignal(bool)  # 定义新的信号
 20     
 21 
 22     def __init__(self, get_coordinates, get_zoom_factor,get_address):
 23         super().__init__()
 24         self.get_coordinates = get_coordinates
 25         self.get_zoom_factor = get_zoom_factor
 26         self.get_address=get_address
 27         self.fgbg = cv2.createBackgroundSubtractorMOG2()
 28         self.motion_detected = False
 29         self.stream_connected = False  # 新增标志,表示视频流是否已经连接
 30         self.prev_frame = None  # 新增变量,用于保存前一帧
 31 
 32 
 33     def run(self):
 34         frame_counter = 0  # 新增帧计数器
 35         max_retries = 5  # 最大重试次数
 36         retry_delay = 1  # 重试延迟,单位为秒
 37         retries = 0  # 当前的重试次数
 38         while True:
 39            
 40             cap = cv2.VideoCapture(self.get_address())
 41 
 42         
 43             if not cap.isOpened():
 44                 if retries < max_retries:
 45                     time.sleep(retry_delay)  # 等待一段时间再尝试重新连接
 46                     retries += 1
 47                     continue
 48                 else:
 49                     print('Failed to connect to video stream after %s retries.' % retries)
 50                     self.error_signal.emit('重连 %s 次失败.' % retries)
 51                     return
 52             self.video_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
 53             self.video_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
 54             prev_time = time.time()
 55 
 56             while True:
 57                 
 58                 if cap.get(cv2.CAP_PROP_FPS) == 0:  # 如果获取帧率失败,表示视频流已经中断
 59                     if self.stream_connected:
 60                         self.connection_status_signal.emit(False)
 61                     self.stream_connected = False
 62                     break
 63 
 64                 start_time = time.time()  # 开始处理的时间
 65                 ret, frame = cap.read()
 66                 
 67                 if not ret:
 68                     if self.stream_connected:  # 如果之前的状态是已连接
 69                         self.connection_status_signal.emit(False)  # 发出连接状态改变的信号
 70                     self.stream_connected = False  # 如果读取帧失败,设置视频流未连接
 71                     break
 72                 
 73                 if not self.stream_connected:  # 如果之前的状态是未连接
 74                     self.connection_status_signal.emit(True)  # 发出连接状态改变的信号    
 75                 self.stream_connected = True  # 如果读取帧成功,设置视频流已连接
 76                 
 77                 
 78                 
 79                 
 80                 
 81                 frame_counter += 1  # 每处理一帧视频,帧计数器就加1
 82                 
 83                 if frame_counter % 3 != 0:  # 如果帧计数器不是5的倍数,跳过这一帧
 84                     continue
 85                 rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
 86                 h, w, ch = rgb_image.shape
 87                 bytes_per_line = ch * w
 88                 convert_to_Qt_format = QImage(rgb_image.data, w, h, bytes_per_line, QImage.Format_RGB888)
 89                 p = convert_to_Qt_format.scaled(270, 480, Qt.KeepAspectRatio)
 90                 self.change_pixmap_signal.emit(p)
 91 
 92                 x, y, width, height = self.get_coordinates()
 93                 zoom_image = rgb_image[y:y+height, x:x+width]
 94                 zoom_image = cv2.GaussianBlur(zoom_image, (7, 7), 1)
 95                 #锐化边缘
 96                 laplacian = cv2.Laplacian(zoom_image, cv2.CV_64F)
 97                 zoom_image = cv2.convertScaleAbs(zoom_image - laplacian)
 98 
 99                   #--------------------------------
100                 fgmask = self.fgbg.apply(zoom_image)
101                 contours, _ = cv2.findContours(fgmask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
102                 
103 
104 
105                 motion_detected = False
106                 for contour in contours:
107                     if cv2.contourArea(contour) > 300:
108                         x, y, w, h = cv2.boundingRect(contour)
109                         cv2.rectangle(zoom_image, (x, y), (x+w, y+h), (0, 255, 0), 2)
110                         motion_detected = True
111 
112                 self.motion_detected = motion_detected
113                 self.motion_detected_signal.emit(motion_detected,zoom_image)
114                 # 使用帧差法检测运动
115                #--------------------------------
116                 # gray = cv2.cvtColor(zoom_image, cv2.COLOR_BGR2GRAY)
117 
118                 # if self.prev_frame is not None:
119                 #     frame_diff = cv2.absdiff(self.prev_frame, gray)
120                 #     _, fgmask = cv2.threshold(frame_diff, 25, 255, cv2.THRESH_BINARY)
121                 #     contours, _ = cv2.findContours(fgmask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
122                     
123                 #     motion_detected = False
124                 #     for contour in contours:
125                 #         if cv2.contourArea(contour) > 300:
126                 #             x, y, w, h = cv2.boundingRect(contour)
127                 #             cv2.rectangle(zoom_image, (x, y), (x+w, y+h), (0, 255, 0), 2)
128                 #             motion_detected = True
129 
130                 #     self.motion_detected = motion_detected
131                 #     self.motion_detected_signal.emit(motion_detected, zoom_image)
132                 
133                 # self.prev_frame = gray  # 保存当前帧,以便下一次循环使用
134                   #--------------------------------
135 
136 
137  
138 
139 
140                  #--------------------------------
141 
142 
143 
144                 zoom_factor = self.get_zoom_factor()
145                 zoom_image = cv2.resize(zoom_image, None, fx=zoom_factor, fy=zoom_factor)
146                 h, w, ch = zoom_image.shape
147                 bytes_per_line = ch * w
148                 convert_to_Qt_format = QImage(zoom_image.data, w, h, bytes_per_line, QImage.Format_RGB888)
149                 self.change_zoom_signal.emit(convert_to_Qt_format)
150                 end_time = time.time()  # 结束处理的时间
151                 self.change_process_time_signal.emit(end_time - start_time)  # 发送处理时间
152 
153                 curr_time = time.time()
154                 fps = 1 / (curr_time - prev_time)
155                 prev_time = curr_time
156                 self.change_fps_signal.emit('FPS 帧率: %s' % str(int(fps)))
157             cap.release()  # 释放VideoCapture对象
158           
159 
160 class App(QWidget):
161     def __init__(self):
162         super().__init__()
163         self.setWindowTitle("Glass Flow Monitor ver0.0")
164         self.disply_width = 270
165         self.display_height = 480
166         self.image_label = QLabel(self)
167         self.image_label.resize(self.disply_width, self.display_height)
168         self.zoom_label = QLabel(self)
169         self.fps_label = QLabel(self)
170         self.process_time_label = QLabel(self)
171         self.alarm_delay_input = QLineEdit(self)
172         self.alarm_delay_input.setText('10')
173         self.alarm_countdown_label = QLabel(self)
174         self.alarm_text = QTextEdit(self)
175         self.alarm_text.setReadOnly(True)
176         self.x_input = QLineEdit(self)
177         self.x_input.setText('320')
178         self.y_input = QLineEdit(self)
179         self.y_input.setText('490')
180         self.width_input = QLineEdit(self)
181         self.width_input.setText('100')
182         self.height_input = QLineEdit(self)
183         self.height_input.setText('150')
184         self.zoom_input = QLineEdit(self)
185         self.zoom_input.setText('2')
186         self.ip_address_input=QLineEdit(self)
187         self.ip_address_input.setText('192.168.1.1')
188         self.ip_address_input.textChanged.connect(self.change_address)
189         
190   
191         self.thread = self.create_video_thread()  # 使用新的方法创建 VideoThread
192 
193         self.layout = QHBoxLayout()
194         self.setLayout(self.layout)
195 
196         self.left_layout = QVBoxLayout()
197         self.left_layout.addWidget(self.image_label)
198 
199         self.input_layout = QGridLayout()
200 
201         self.input_layout.addWidget(QLabel('检测区X坐标:'), 0, 0)
202         self.input_layout.addWidget(self.x_input, 0, 1)
203         self.input_layout.addWidget(QLabel('检测区Y坐标:'), 1, 0)
204         self.input_layout.addWidget(self.y_input, 1, 1)
205         self.input_layout.addWidget(QLabel('检测区宽 Width:'), 2, 0)
206         self.input_layout.addWidget(self.width_input, 2, 1)
207         self.input_layout.addWidget(QLabel('检测区高 Height:'), 3, 0)
208         self.input_layout.addWidget(self.height_input, 3, 1)
209         self.input_layout.addWidget(QLabel('缩放 Zoom:'), 4, 0)
210         self.input_layout.addWidget(self.zoom_input, 4, 1)
211         self.left_layout.addLayout(self.input_layout)
212 
213         self.input_layout.addWidget(QLabel('IP:'), 5, 0)
214         self.input_layout.addWidget(self.ip_address_input, 5, 1)
215         self.left_layout.addLayout(self.input_layout)
216 
217         self.layout.addLayout(self.left_layout)
218 
219         self.middle_layout = QVBoxLayout()
220         self.middle_layout.addWidget(self.zoom_label)
221         self.middle_layout.addWidget(self.fps_label)
222         self.middle_layout.addWidget(self.process_time_label)
223         self.middle_layout.addWidget(QLabel('Alarm Delay 报警阈值(S):'))
224         self.middle_layout.addWidget(self.alarm_delay_input)
225        
226         self.middle_layout.addWidget(self.alarm_countdown_label)
227         self.middle_layout.addWidget(self.alarm_text)
228         self.middle_layout.addStretch()
229 
230         self.layout.addLayout(self.middle_layout)
231 
232 
233         self.password_input = QLineEdit(self)
234         self.password_input.setEchoMode(QLineEdit.Password)  # 设置为密码输入框
235         self.login_button = QPushButton('Login 登录', self)
236         self.login_button.clicked.connect(self.login)
237         self.middle_layout.addWidget(QLabel('Password 密码:'))
238         self.middle_layout.addWidget(self.password_input)
239         self.middle_layout.addWidget(self.login_button)
240 
241         self.logout_timer = QTimer(self)
242         self.logout_timer.timeout.connect(self.logout)
243         self.logout_timer.start(30000)  # 设置定时器超时时间为1分钟
244         
245 
246 
247 
248         
249 
250         self.btn_quit = QPushButton('Quit 关闭', self)
251         self.btn_quit.clicked.connect(self.close)
252         self.middle_layout.addWidget(self.btn_quit)
253 
254         self.alarm_timer = QTimer(self)
255         self.alarm_timer.timeout.connect(self.on_alarm_timeout)
256         self.alarm_time = None
257         self.alarm_timer.start(1000)
258         self.alarm_generated = False  # 新增标志,表示是否已经生成了报警信息
259 
260         self.alarm_sound = QSound('alarm.wav')  # 报警音,需要一个.wav文件
261         self.alarm_sound.setLoops(-1)  # 设置无限循环
262         self.alarm_playing = False  # 新增标志位,表示是否正在播放报警音
263         self.acknowledge_button = QPushButton('Acknowledge Alarm 确认报警', self)  # 新增确认按钮
264         self.acknowledge_button.clicked.connect(self.acknowledge_alarm)
265         self.middle_layout.addWidget(self.acknowledge_button)
266 
267         self.enable_controls(False)  # 初始化时禁用所有的控件
268         self.thread.error_signal.connect(self.update_alarm_text)
269 
270 
271         self.alarm_image_saved = False  # 新增标志位,表示是否已经保存过报警图片
272 
273 
274 
275         
276 
277     def acknowledge_alarm(self):
278         self.alarm_playing = False  # 复位标志位
279         self.alarm_sound.stop()  # 停止播放报警音
280 
281     def login(self):
282         password = self.password_input.text()
283         if password == '8888':  # 这里替换为你的密码
284             self.enable_controls(True)
285             self.reset_logout_timer()
286     
287     def logout(self):
288         self.enable_controls(False)
289     
290     def reset_logout_timer(self):
291         self.logout_timer.start(30000)  # 重置定时器
292     
293 
294     def enable_controls(self, enabled):
295         self.x_input.setEnabled(enabled)
296         self.y_input.setEnabled(enabled)
297         self.width_input.setEnabled(enabled)
298         self.height_input.setEnabled(enabled)
299         self.zoom_input.setEnabled(enabled)
300         self.alarm_delay_input.setEnabled(enabled)
301         self.btn_quit.setEnabled(enabled)
302         self.acknowledge_button.setEnabled(True)  # 报警确认按钮总是可用
303 
304 
305     def create_video_thread(self):
306         # 创建一个新的 VideoThread
307         thread = VideoThread(self.get_coordinates, self.get_zoom_factor, self.get_address)
308         thread.change_pixmap_signal.connect(self.update_image)
309         thread.change_zoom_signal.connect(self.update_zoom)
310         thread.change_fps_signal.connect(self.update_fps)
311         thread.change_process_time_signal.connect(self.update_process_time)
312         thread.motion_detected_signal.connect(self.on_motion_detected)
313         thread.start()
314         return thread
315 
316     def change_address(self):
317         # 停止当前的 VideoThread
318         self.thread.terminate()
319         # 创建一个新的 VideoThread
320         self.thread = self.create_video_thread()   
321 
322 
323 
324     @pyqtSlot(QImage)
325     def update_image(self, qt_image):
326         x = int(self.x_input.text())
327         y = int(self.y_input.text())
328         width = int(self.width_input.text())
329         height = int(self.height_input.text())
330         x_scaled = int(x * 270 / self.thread.video_width)
331         y_scaled = int(y * 480 / self.thread.video_height)
332         width_scaled = int(width * 270 / self.thread.video_width)
333         height_scaled = int(height * 480 / self.thread.video_height)
334         painter_instance = QPainter(qt_image)
335         painter_instance.setPen(QPen(Qt.blue, 3))
336         painter_instance.drawRect(x_scaled, y_scaled, width_scaled, height_scaled)
337         self.image_label.setPixmap(QPixmap.fromImage(qt_image))
338 
339     @pyqtSlot(QImage)
340     def update_zoom(self, qt_image):
341         self.zoom_label.setPixmap(QPixmap.fromImage(qt_image))
342 
343     @pyqtSlot(str)
344     def update_fps(self, fps):
345         self.fps_label.setText(fps)
346 
347     @pyqtSlot(float)
348     def update_process_time(self, process_time):
349         self.process_time_label.setText('Process time 处理时间: %.1f ms' % (process_time * 1000))
350 
351     @pyqtSlot(bool, np.ndarray)
352     def on_motion_detected(self, motion_detected, image):
353         if motion_detected and self.thread.stream_connected:
354             self.alarm_time = time.time()
355             self.alarm_image = image  # 保存截取的图像,以便在需要时保存为文件
356 
357     @pyqtSlot(str)
358     def update_alarm_text(self, text):
359         self.alarm_text.append(text)
360 
361 
362     @pyqtSlot(bool)
363     def update_connection_status(self, connected):
364         if connected:
365             self.connection_status_light.setStyleSheet('background-color: green; border-radius: 10px;')  # 设置标签的背景颜色为绿色
366             self.connection_status_text.setText('Connected')
367         else:
368             self.connection_status_light.setStyleSheet('background-color: red; border-radius: 10px;')  # 设置标签的背景颜色为红色
369             self.connection_status_text.setText('Disconnected')
370         
371     @pyqtSlot()
372     def on_alarm_timeout(self):
373         if self.alarm_time is not None  and self.thread.stream_connected:  # 如果视频流已经连接:
374             countdown = int(self.alarm_delay_input.text()) - int(time.time() - self.alarm_time)
375             if countdown <= 0:
376                 if not self.alarm_generated:  # 如果还没有生成报警信息
377                     timestamp = datetime.now().strftime('%Y-%m-%d %H-%M-%S')
378                     self.alarm_text.append('%s Alarm: 未检测到移动玻璃液 %s seconds.' % (timestamp, self.alarm_delay_input.text()))
379                     self.alarm_generated = True  # 设置标志,表示已经生成了报警信息
380                     self.alarm_playing = True  # 设置标志,表示应该播放报警音
381                     self.alarm_sound.play()  # 开始播放报警音
382                     if not self.alarm_image_saved:  # 如果还没有保存过报警图片
383                         bgr_image = cv2.cvtColor(self.alarm_image, cv2.COLOR_RGB2BGR)  # 将图像从 RGB 格式转换为 BGR 格式
384                         try:
385                             cv2.imwrite('alarm_%s.png' % timestamp, bgr_image)  # 保存报警图片
386                         except Exception as e:
387                             print('Failed to save alarm image:', e)
388                         cv2.imwrite('alarm_%s.png' % timestamp, bgr_image)  # 保存报警图片
389                         self.alarm_image_saved = True  # 设置标志,表示已经保存过报警图片
390 
391                 palette = self.palette()
392                 if palette.color(QPalette.Background) == Qt.red:
393                     palette.setColor(QPalette.Background, Qt.yellow)
394                 else:
395                     palette.setColor(QPalette.Background, Qt.red)
396                 self.setPalette(palette)
397             else:
398                 self.alarm_generated = False  # 重置标志,因为报警已经结束
399                 self.alarm_image_saved = False  # 重置标志,因为报警已经结束
400                 self.acknowledge_alarm()  # 停止播放报警音
401                 palette = self.palette()
402                 palette.setColor(QPalette.Background, Qt.white)
403                 self.setPalette(palette)
404             self.alarm_countdown_label.setText('Alarm Countdown 倒计时(s): %s s' % countdown)
405         else:
406             palette = self.palette()
407             palette.setColor(QPalette.Background, Qt.white)
408             self.setPalette(palette)
409             self.alarm_countdown_label.setText('Alarm Countdown 倒计时(s):: no motion detected')
410             self.acknowledge_alarm()  # 停止播放报警音
411 
412     def closeEvent(self, event):
413         self.thread.terminate()
414 
415     def get_coordinates(self):
416         return int(self.x_input.text()), int(self.y_input.text()), int(self.width_input.text()), int(self.height_input.text())
417 
418     def get_zoom_factor(self):
419         return float(self.zoom_input.text())
420     
421     def get_address(self):
422         PATH='rtsp://root:root@'+str(self.ip_address_input.text())+':554/axis-media/media.amp'
423         print(PATH)
424         return PATH
425 
426 def main():
427     start_time = time.time()
428     app = QApplication(sys.argv)
429     ex = App()
430     ex.show()
431     sys.exit(app.exec_())
432     print("Total execution time: %.2f ms" % ((time.time() - start_time) * 1000))
433 
434 if __name__ == '__main__':
435     cProfile.run('main()')

 

标签:layout,Pyhon,self,翻板,zoom,time,input,image,Axis
From: https://www.cnblogs.com/AutomationDoge/p/18600011

相关文章

  • Pyhon的继承
    1继承中的__init__初始化函数1.1子类没有定义自己的初始化函数,父类的初始化函数会被默认调用:#定义父类:ParentclassParent(object):def__init__(self,name):self.name=nameprint("createaninstanceof:",self.__class__.__name__)pr......
  • XGMII2AXIS
    目录@[TOC](目录)一、问题描述二、XGMII2AXIS仿真结果备注一、问题描述项目中遇到万兆以太网的使用,想将xgmii转成axis使用,目前思路就两种,一种是计数器,一种是状态机,于是用三段式状态机编写代码,并编写tb用于逻辑验证。二、XGMII2AXIS仿真结果需要考虑的也就是tkeep......
  • Araxis Merge Professional Edition Crack
    AraxisMergeProfessionalEditionCrackKeyFeaturesofAraxisMerge:Ithastheabilitytoprovideacross-platformlicensetotheusersanddevelopersandpermitstheusertousetheWindowsaswellastheMacOSversioninordertomerge.......
  • 基于Axis 1.4的Web Service入门
    最近有个客户使用的是Axis1.4创建的WebService,很久没用了,所以整理下这块的知识。基于JDK1.8和EclipseMars开发一个简单的HelloworldWebServicepublicinterfaceHelloService{ Stringhello(Stringname);}publicclassHelloServiceImplimplementsHelloService{......
  • axis参数讲解
    axis在python使用中非常常见,比如numpy、pandas等使用情景。但是笔者几乎每次都会忘记axis=0和axis=1各自对应的是行还是列,最终决定写下笔记以防再次忘记。axis的作用:指明以行为单位进行处理数据,还是以列为单位处理数据。下图就已经很清晰地展示了axis=0和axis=1,一图胜......
  • Python-PLAXIS自动化建模技术与典型岩土工程
    原文链接:Python-PLAXIS自动化建模技术与典型岩土工程https://blog.csdn.net/2301_78164062/article/details/140607885?spm=1001.2014.3001.5501一:Plaxis软件及PlaxisPythonAPI环境搭建1、Plaxis2D\Plaxis3D软件2、面向对象编程语言Python及其开发环境Spyder3、Plaxis输......
  • 更改 pyplot 中 xaxis 标签的格式
    我正在尝试重新格式化x轴,但我所做的一切都不起作用当我使用:importpandasaspdimportmatplotlib.pyplotaspltz=pd.DataFrame([[2000,1,2],[2001,2,3],[2004,5,6]])z=z.set_index(0)z.plot()plt.show()x轴标签格式为2,000.0到2,000.0如何让它简单地显......
  • Pandas运行报错分析:ValueError: Length mismatch: Expected axis has 0 elements, new
    ✨✨欢迎大家来到景天科技苑✨✨......
  • 【例0808】create daxis using face 使用面创建基准轴
    文章作者:里海来源网站:NX二次开发官方案例专栏简介《createdaxisusingface根据代码内容,翻译“createdaxisusingface”为“使用面创建基准轴”》这是一个NX二次开发官方小例子,下面是代码和解析。相较于混乱、未经验证的代码,官方案例能够确保开发者获得准确的开发......
  • height_scale = scales[2] IndexError: index 2 is out of bounds for axis 0 with si
    1.yolov5网络层优化在yolov5训练之前最好是改一下网络层,要不会报这个错。Traceback(mostrecentcalllast): File"convertCaffe.py",line159,in<module>   convertToCaffe(graph,prototxt_path,caffemodel_path,exis_focus=True,focus_concat_name="Concat_40",......