welding_reset_detect.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. import cv2
  2. import torch
  3. import threading
  4. from shapely.geometry import box, Polygon
  5. from datetime import datetime
  6. from ultralytics import YOLO
  7. from config import WELDING_MODEL_PATHS,WELDING_VIDEO_SOURCES
  8. from config import WELDING_CH1_RTSP,WELDING_CH2_RTSP,WELDING_CH3_RTSP,WELDING_CH4_RTSP,WELDING_CH5_RTSP
  9. from config import SAVE_IMG_PATH,POST_IMG_PATH2,WELDING_REGION2,WELDING_REGION3
  10. from globals import oil_barrel_flag,main_switch_flag,ground_wire_flag,welding_components_flag,welding_machine_switch_flag
  11. from globals import lock,redis_client,stop_event
  12. def init_rest_detection():
  13. redis_client.delete("welding_reset_post_path")#删除该列表welding_reset_post_path
  14. redis_client.set("welding_main_switch_save_img",'False')
  15. redis_client.set("welding_oil_barrel_save_img",'False')
  16. redis_client.set("welding_ground_wire_save_img",'False')
  17. redis_client.set("welding_components_save_img",'False')
  18. redis_client.set("welding_machine_switch_save_img",'False')
  19. def start_reset_detection(start_events):
  20. # Create threads for each video stream and model
  21. threads = []
  22. for model_path, video_source in zip(WELDING_MODEL_PATHS, WELDING_VIDEO_SOURCES):
  23. event = threading.Event()
  24. start_events.append(event)
  25. thread = threading.Thread(target=process_video, args=(model_path, video_source,event))
  26. threads.append(thread)
  27. thread.daemon=True
  28. thread.start()
  29. # Wait for all threads to complete
  30. for thread in threads:
  31. thread.join()
  32. print("复位检测子线程结束")
  33. # Function to process video with YOLO model
  34. def process_video(model_path, video_source, start_event):
  35. # Load YOLO model
  36. model = YOLO(model_path)
  37. #results = model.predict(video_source,stream=True,verbose=False,conf=0.4,device='0')#这里的results是一个生成器
  38. cap = cv2.VideoCapture(video_source)
  39. # Loop through the video frames
  40. while cap.isOpened():
  41. if stop_event.is_set():#控制停止推理
  42. break
  43. # Read a frame from the video
  44. success, frame = cap.read()
  45. if success:
  46. if cap.get(cv2.CAP_PROP_POS_FRAMES) % 25 != 0:#跳帧检测,
  47. continue
  48. if video_source == WELDING_CH2_RTSP or video_source == WELDING_CH4_RTSP:#这两个视频流用的分类模型,因为分类模型预处理较慢,需要手动resize
  49. frame=cv2.resize(frame,(640,640))
  50. # Run YOLOv8 inference on the frame
  51. results = model.predict(frame,verbose=False,conf=0.4)
  52. global oil_barrel_flag,main_switch_flag,ground_wire_flag,welding_components_flag,welding_machine_switch_flag
  53. #with lock:
  54. for r in results:
  55. #因为搭铁线不好识别,所以当没有检测到时,ground_wire_flag=False
  56. if video_source == WELDING_CH2_RTSP:
  57. # annotated_frame = results[0].plot()
  58. # cv2.namedWindow('main_switch', cv2.WINDOW_NORMAL)
  59. # cv2.imshow('main_switch', annotated_frame)
  60. # if cv2.waitKey(1) & 0xFF == ord("q"):
  61. # break
  62. if r.probs.top1conf>0.6:
  63. label=model.names[r.probs.top1]
  64. welding_components_flag=True if label == "component" else False
  65. else:
  66. continue
  67. if video_source == WELDING_CH4_RTSP:
  68. if r.probs.top1conf>0.6:
  69. label=model.names[r.probs.top1]#获取最大概率的类别的label
  70. main_switch_flag = True if label == "open" else False
  71. else:
  72. continue
  73. if video_source == WELDING_CH5_RTSP or video_source == WELDING_CH3_RTSP or video_source == WELDING_CH1_RTSP:
  74. ##下面这些都是tensor类型
  75. boxes = r.boxes.xyxy # 提取所有检测到的边界框坐标
  76. confidences = r.boxes.conf # 提取所有检测到的置信度
  77. classes = r.boxes.cls # 提取所有检测到的类别索引
  78. if video_source == WELDING_CH5_RTSP:
  79. ground_wire_flag=False
  80. #welding_components_flag=False
  81. if video_source == WELDING_CH3_RTSP:
  82. oil_barrel_flag=True
  83. for i in range(len(boxes)):
  84. x1, y1, x2, y2 = boxes[i].tolist()
  85. confidence = confidences[i].item()
  86. cls = int(classes[i].item())
  87. label = model.names[cls]
  88. if label=="dump":#检测油桶
  89. x_center = (x1 + x2) / 2
  90. y_center = (y1 + y2) / 2
  91. center_point = (int(x_center), int(y_center))
  92. is_inside = cv2.pointPolygonTest(WELDING_REGION2.reshape((-1, 1, 2)), center_point, False)
  93. #print(is_inside)
  94. if is_inside>=0 :
  95. oil_barrel_flag=False #表示油桶在危险区域
  96. else:
  97. oil_barrel_flag=True
  98. if label== "open":#检测焊机开关
  99. welding_machine_switch_flag = True
  100. if label=="close":#检测焊机开关
  101. welding_machine_switch_flag = False
  102. if label=="grounding_wire" :
  103. rect_shapely = box(x1,y1, x2, y2)#使用shapely库创建的矩形
  104. WELDING_REGION3_shapely = Polygon(WELDING_REGION3.tolist()) #shapely计算矩形检测框和多边形的iou使用
  105. intersection = rect_shapely.intersection(WELDING_REGION3_shapely)
  106. # 计算并集
  107. union = rect_shapely.union(WELDING_REGION3_shapely)
  108. # 计算 IoU
  109. iou = intersection.area / union.area
  110. if iou>0 :
  111. ground_wire_flag=True #表示搭铁线连接在焊台上
  112. else:
  113. ground_wire_flag=False #表示未连接上
  114. flag_count = sum([oil_barrel_flag, main_switch_flag, ground_wire_flag, welding_components_flag, welding_machine_switch_flag])
  115. redis_client.set("welding_reset_flag",flag_count)
  116. #print("主开关",main_switch_flag)
  117. if video_source == WELDING_CH4_RTSP :#检测到总开关
  118. if main_switch_flag and redis_client.get("welding_main_switch_save_img")=='False':
  119. print("当前总开关没有复位")##焊前检查只保存一次
  120. redis_client.set("welding_main_switch_save_img",'True')
  121. #save_time=datetime.now().strftime('%Y%m%d_%H%M')
  122. save_time=datetime.now().strftime('%Y%m%d_%H')
  123. imgpath = f"{SAVE_IMG_PATH}/welding_resetStep2_{save_time}.jpg"
  124. post_path = f"{POST_IMG_PATH2}/welding_resetStep2_{save_time}.jpg"
  125. redis_client.rpush("welding_reset_post_path",post_path)#welding_reset_post_path为一个列表,存储需要发送的图片路径,rpush为从右侧加入
  126. annotated_frame = results[0].plot()
  127. cv2.imwrite(imgpath, annotated_frame)
  128. if video_source == WELDING_CH3_RTSP :##检测油桶{0: 'dump'},在安全区域时保存图片一张
  129. if oil_barrel_flag and redis_client.get("welding_oil_barrel_save_img")=='False':
  130. print("当前油桶没有复位")
  131. redis_client.set("welding_oil_barrel_save_img",'True')
  132. #save_time=datetime.now().strftime('%Y%m%d_%H%M')
  133. save_time=datetime.now().strftime('%Y%m%d_%H')
  134. imgpath = f"{SAVE_IMG_PATH}/welding_resetStep1_{save_time}.jpg"
  135. post_path = f"{POST_IMG_PATH2}/welding_resetStep1_{save_time}.jpg"
  136. redis_client.rpush("welding_reset_post_path",post_path)
  137. annotated_frame = results[0].plot()
  138. cv2.imwrite(imgpath, annotated_frame)
  139. #reset_post(welding_resetStep='1',path=post_path)
  140. #post(step='2',path=post_path)
  141. if video_source == WELDING_CH1_RTSP:#检测到焊机开关
  142. if welding_machine_switch_flag and redis_client.get("welding_machine_switch_save_img")=='False':
  143. print("当前焊机开关没有复位")##焊前检查只保存一次
  144. redis_client.set("welding_machine_switch_save_img",'True')
  145. #save_time=datetime.now().strftime('%Y%m%d_%H%M')
  146. save_time=datetime.now().strftime('%Y%m%d_%H')
  147. imgpath = f"{SAVE_IMG_PATH}/welding_resetStep5_{save_time}.jpg"
  148. post_path = f"{POST_IMG_PATH2}/welding_resetStep5_{save_time}.jpg"
  149. redis_client.rpush("welding_reset_post_path",post_path)
  150. #cv2.imwrite(imgpath, annotator.result())
  151. annotated_frame = results[0].plot()
  152. cv2.imwrite(imgpath, annotated_frame)
  153. #reset_post(welding_resetStep='5',path=post_path)
  154. #post(step='2',path=post_path)
  155. if video_source == WELDING_CH5_RTSP:
  156. if ground_wire_flag and redis_client.get("welding_ground_wire_save_img")=='False':
  157. print("搭铁线没有复位")
  158. redis_client.set("welding_ground_wire_save_img",'True')
  159. #save_time=datetime.now().strftime('%Y%m%d_%H%M')
  160. save_time=datetime.now().strftime('%Y%m%d_%H')
  161. imgpath = f"{SAVE_IMG_PATH}/welding_resetStep3_{save_time}.jpg"
  162. post_path = f"{POST_IMG_PATH2}/welding_resetStep3_{save_time}.jpg"
  163. redis_client.rpush("welding_reset_post_path",post_path)
  164. # result_image = annotator.result()
  165. # cv2.polylines(result_image, [WELDING_REGION3.reshape(-1, 1, 2)], isClosed=True, color=(0, 255, 0), thickness=4)
  166. # cv2.imwrite(imgpath, result_image)
  167. annotated_frame = results[0].plot()
  168. cv2.imwrite(imgpath, annotated_frame)
  169. #reset_post(welding_resetStep="3",path=post_path)
  170. #time.sleep(1)
  171. #post(step='4',path=post_path)
  172. if video_source == WELDING_CH2_RTSP:
  173. if welding_components_flag and redis_client.get("welding_components_save_img")=='False':
  174. print("焊件没有复位")
  175. redis_client.set("welding_components_save_img",'True')
  176. #save_time=datetime.now().strftime('%Y%m%d_%H%M')
  177. save_time=datetime.now().strftime('%Y%m%d_%H')
  178. imgpath = f"{SAVE_IMG_PATH}/welding_resetStep4_{save_time}.jpg"
  179. post_path = f"{POST_IMG_PATH2}/welding_resetStep4_{save_time}.jpg"
  180. redis_client.rpush("welding_reset_post_path",post_path)
  181. # result_image = annotator.result()
  182. # cv2.polylines(result_image, [REGION4.reshape(-1, 1, 2)], isClosed=True, color=(0, 255, 0), thickness=4)
  183. # cv2.imwrite(imgpath, result_image)
  184. annotated_frame = results[0].plot()
  185. cv2.imwrite(imgpath, annotated_frame)
  186. #reset_post(welding_resetStep='4',path=post_path)
  187. #post(step='4',path=post_path)
  188. #运行到这里表示一个线程检测完毕
  189. start_event.set()
  190. else:
  191. # Break the loop if the end of the video is reached
  192. break
  193. # Release the video capture object and close the display window
  194. cap.release()
  195. # 释放模型资源(如果使用GPU)
  196. if torch.cuda.is_available():
  197. torch.cuda.empty_cache()
  198. del model
  199. #cv2.destroyAllWindows()