welding_exam_detect.py 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. import cv2
  2. import torch
  3. from shapely.geometry import box, Polygon
  4. import threading
  5. from datetime import datetime
  6. from ultralytics import YOLO
  7. from config import WELDING_MODEL_PATHS,WELDING_VIDEO_SOURCES
  8. from utils.tool import IoU
  9. from globals import stop_event,redis_client,lock
  10. from config import WELDING_CH1_RTSP,WELDING_CH2_RTSP,WELDING_CH3_RTSP,WELDING_CH4_RTSP,WELDING_CH5_RTSP
  11. from config import SAVE_IMG_PATH,POST_IMG_PATH2,WELDING_REGION1,WELDING_REGION2,WELDING_REGION3
  12. from globals import steps
  13. from globals import oil_barrel,main_switch,grounding_wire,welding_machine_switch,welding_components,mask,welding,gloves,sweep,sweep_detect_num,welding_detect_num
  14. def init_welding_detection():
  15. global steps
  16. steps = [False] * 13
  17. redis_client.delete("welding_post_path")
  18. def start_welding_detection(start_events):
  19. threads = []
  20. for model_path, video_source in zip(WELDING_MODEL_PATHS, WELDING_VIDEO_SOURCES):
  21. event = threading.Event()
  22. start_events.append(event)
  23. thread = threading.Thread(target=process_video, args=(model_path, video_source,event))
  24. threads.append(thread)
  25. thread.daemon=True
  26. thread.start()
  27. # Wait for all threads to complete
  28. for thread in threads:
  29. thread.join()
  30. print("焊接子线程运行结束")
  31. # Function to process video with YOLO model
  32. def process_video(model_path, video_source,start_event):
  33. # Load YOLO model
  34. model = YOLO(model_path)
  35. cap = cv2.VideoCapture(video_source)
  36. while cap.isOpened():
  37. if stop_event.is_set():#控制停止推理
  38. #del model
  39. break
  40. # Read a frame from the video
  41. success, frame = cap.read()
  42. if success:
  43. # Run YOLOv8 inference on the frame
  44. if cap.get(cv2.CAP_PROP_POS_FRAMES) % 25 != 0:
  45. continue
  46. if video_source == WELDING_CH2_RTSP or video_source == WELDING_CH4_RTSP:#这两个视频流用的分类模型,因为分类模型预处理较慢,需要手动resize
  47. frame=cv2.resize(frame,(640,640))
  48. results = model.predict(frame,verbose=False,conf=0.4)
  49. global steps
  50. global oil_barrel,main_switch,grounding_wire,welding_machine_switch,welding_components,mask,welding,gloves,sweep
  51. global sweep_detect_num,welding_detect_num
  52. for r in results:
  53. if video_source == WELDING_CH2_RTSP:#焊台
  54. if r.probs.top1conf>0.8:
  55. label=model.names[r.probs.top1]
  56. if label=='component':
  57. welding_components='in_position'#在焊台上
  58. if label=='empty':
  59. welding_components='not_in_position'#不在焊台上
  60. if label=='welding':
  61. if welding_detect_num<3:
  62. welding_detect_num+=1
  63. else:
  64. welding=True#表示有焊接
  65. if label=='sweep':
  66. if sweep_detect_num<3:
  67. sweep_detect_num+=1
  68. else:
  69. sweep=True#表示有打扫
  70. else:
  71. continue
  72. #if video_source == WELDING_CH3_RTSP:#油桶
  73. if video_source == WELDING_CH4_RTSP:#总开关
  74. if r.probs.top1conf>0.8:
  75. label=model.names[r.probs.top1]#获取最大概率的类别的label
  76. main_switch = "open" if label == "open" else "close"
  77. else:
  78. continue
  79. if video_source == WELDING_CH1_RTSP or video_source==WELDING_CH3_RTSP or video_source==WELDING_CH5_RTSP:#焊接操作,进行目标检测
  80. ##下面这些都是tensor类型
  81. boxes = r.boxes.xyxy # 提取所有检测到的边界框坐标
  82. confidences = r.boxes.conf # 提取所有检测到的置信度
  83. classes = r.boxes.cls # 提取所有检测到的类别索引
  84. # if video_source==WELDING_CH5_RTSP:
  85. # grounding_wire=="disconnect"##单独每次设置为false,是为了防止没有检测到
  86. #welding_components=False
  87. if video_source==WELDING_CH3_RTSP:#当画面没有油桶时,给个初值为安全
  88. oil_barrel="safe"
  89. for i in range(len(boxes)):
  90. x1, y1, x2, y2 = boxes[i].tolist()
  91. confidence = confidences[i].item()
  92. cls = int(classes[i].item())
  93. label = model.names[cls]
  94. if label=="dump":#检测油桶
  95. x_center = (x1 + x2) / 2
  96. y_center = (y1 + y2) / 2
  97. center_point = (int(x_center), int(y_center))
  98. is_inside = cv2.pointPolygonTest(WELDING_REGION2.reshape((-1, 1, 2)), center_point, False)
  99. #print(is_inside)
  100. if is_inside>=0 :
  101. oil_barrel='danger' #表示油桶在危险区域
  102. else:
  103. oil_barrel='safe'
  104. if label== "open" or "close":#检测焊机开关
  105. welding_machine_switch = label
  106. if label=="grounding_wire" :
  107. if confidence<0.6:
  108. continue
  109. rect_shapely = box(x1,y1, x2, y2)#使用shapely库创建的矩形
  110. WELDING_REGION3_shapely = Polygon(WELDING_REGION3.tolist()) #shapely计算矩形检测框和多边形的iou使用
  111. intersection = rect_shapely.intersection(WELDING_REGION3_shapely)
  112. # 计算并集
  113. union = rect_shapely.union(WELDING_REGION3_shapely)
  114. # 计算 IoU
  115. iou = intersection.area / union.area
  116. grounding_wire="connect" if iou>0 else "disconnect" #表示搭铁线连接在焊台上
  117. # if label=="welding_components" :
  118. # welding_components_xyxy=boxes[i].tolist()#实时检测焊件的位置
  119. # # 计算检测框的中心点
  120. # x_center = (x1 + x2) / 2
  121. # y_center = (y1 + y2) / 2
  122. # center_point = (int(x_center), int(y_center))
  123. # # 检查中心点是否在多边形内
  124. # is_inside = cv2.pointPolygonTest(REGION4.reshape((-1, 1, 2)), center_point, False)
  125. # welding_components=True if is_inside>=0 else False #表示在焊料在焊台上
  126. if label=="mask":
  127. #mask=True #表示戴面罩
  128. iou=IoU(boxes[i].tolist(),WELDING_REGION1)
  129. mask=True if iou>0 else False #表示戴面罩
  130. if label=="gloves":
  131. #gloves_xyxy=boxes[i].tolist()#实时检测手套的位置
  132. if confidence>0.5:
  133. gloves=True#表示戴手套
  134. else:
  135. gloves=False
  136. # if label=="welding" :
  137. # iou1=IoU(gloves_xyxy,boxes[i].tolist())#自定义的矩形iou方法,焊枪跟手套进行iou计算
  138. # iou2=IoU(welding_components_xyxy,boxes[i].tolist())#自定义的矩形iou方法,焊枪跟焊件进行iou计算
  139. # if iou1>0 and iou2>0:
  140. # gloves=True#表示有手套焊接
  141. # if iou1<=0 and iou2>0:
  142. # welding=True#表示无手套焊接
  143. # if label=="sweep" :
  144. # # 计算检测框的中心点
  145. # x_center = (x1 + x2) / 2
  146. # y_center = (y1 + y2) / 2
  147. # center_point = (int(x_center), int(y_center))
  148. # # 检查中心点是否在多边形内
  149. # is_inside = cv2.pointPolygonTest(REGION4.reshape((-1, 1, 2)), center_point, False)
  150. # sweep=True if is_inside>=0 else False #表示是否打扫
  151. if video_source ==WELDING_CH3_RTSP:
  152. if oil_barrel=="safe" and steps[0]==False:#排除危险源
  153. steps[0]=True
  154. save_time=datetime.now().strftime('%Y%m%d_%H%M')
  155. #save_time=datetime.now().strftime('%Y%m%d_%H')
  156. img_path = f"{SAVE_IMG_PATH}/step1_{save_time}.jpg"
  157. post_path = f"{POST_IMG_PATH2}/step1_{save_time}.jpg"
  158. redis_client.rpush("welding_post_path",post_path)
  159. annotated_frame = results[0].plot()
  160. cv2.imwrite(img_path, annotated_frame)
  161. print("step1完成")
  162. #post("1",post_path)
  163. if video_source==WELDING_CH4_RTSP:
  164. if main_switch=="open" and steps[1]==False:
  165. steps[1]=True
  166. save_time=datetime.now().strftime('%Y%m%d_%H%M')
  167. #save_time=datetime.now().strftime('%Y%m%d_%H')
  168. img_path = f"{SAVE_IMG_PATH}/step2_{save_time}.jpg"
  169. post_path = f"{POST_IMG_PATH2}/step2_{save_time}.jpg"
  170. redis_client.rpush("welding_post_path",post_path)
  171. annotated_frame = results[0].plot()
  172. cv2.imwrite(img_path, annotated_frame)
  173. print("step2完成")
  174. #post("2",post_path)
  175. if main_switch=="close" and steps[12]==False and steps[1]:
  176. steps[12]=True
  177. save_time=datetime.now().strftime('%Y%m%d_%H%M')
  178. #save_time=datetime.now().strftime('%Y%m%d_%H')
  179. img_path = f"{SAVE_IMG_PATH}/step13_{save_time}.jpg"
  180. post_path = f"{POST_IMG_PATH2}/step13_{save_time}.jpg"
  181. redis_client.rpush("welding_post_path",post_path)
  182. annotated_frame = results[0].plot()
  183. cv2.imwrite(img_path, annotated_frame)
  184. print("step13完成")
  185. #post("13",post_path)
  186. if video_source==WELDING_CH1_RTSP:
  187. if welding_machine_switch=="open" and steps[4]==False:
  188. steps[4]=True
  189. save_time=datetime.now().strftime('%Y%m%d_%H%M')
  190. #save_time=datetime.now().strftime('%Y%m%d_%H')
  191. img_path = f"{SAVE_IMG_PATH}/step5_{save_time}.jpg"
  192. post_path = f"{POST_IMG_PATH2}/step5_{save_time}.jpg"
  193. redis_client.rpush("welding_post_path",post_path)
  194. annotated_frame = results[0].plot()
  195. cv2.imwrite(img_path, annotated_frame)
  196. print("step5完成")
  197. #post("5",post_path)
  198. if welding_machine_switch=="close" and steps[8]==False and steps[4]:
  199. steps[8]=True
  200. save_time=datetime.now().strftime('%Y%m%d_%H%M')
  201. #save_time=datetime.now().strftime('%Y%m%d_%H')
  202. img_path = f"{SAVE_IMG_PATH}/step9_{save_time}.jpg"
  203. post_path = f"{POST_IMG_PATH2}/step9_{save_time}.jpg"
  204. redis_client.rpush("welding_post_path",post_path)
  205. annotated_frame = results[0].plot()
  206. cv2.imwrite(img_path, annotated_frame)
  207. print("step9完成")
  208. #post("9",post_path)
  209. if video_source==WELDING_CH2_RTSP:
  210. if sweep==True and steps[11]==False:#打扫
  211. steps[11]=True
  212. save_time=datetime.now().strftime('%Y%m%d_%H%M')
  213. #save_time=datetime.now().strftime('%Y%m%d_%H')
  214. img_path = f"{SAVE_IMG_PATH}/step12_{save_time}.jpg"
  215. post_path = f"{POST_IMG_PATH2}/step12_{save_time}.jpg"
  216. redis_client.rpush("welding_post_path",post_path)
  217. annotated_frame = results[0].plot()
  218. cv2.imwrite(img_path, annotated_frame)
  219. print("step12完成")
  220. #post("12",post_path)
  221. if welding_components=='in_position' and steps[3]==False:
  222. steps[3]=True
  223. save_time=datetime.now().strftime('%Y%m%d_%H%M')
  224. #save_time=datetime.now().strftime('%Y%m%d_%H')
  225. img_path = f"{SAVE_IMG_PATH}/step4_{save_time}.jpg"
  226. post_path = f"{POST_IMG_PATH2}/step4_{save_time}.jpg"
  227. redis_client.rpush("welding_post_path",post_path)
  228. annotated_frame = results[0].plot()
  229. cv2.imwrite(img_path, annotated_frame)
  230. print("step4完成")
  231. #post("4",post_path)
  232. if welding_components=='not_in_position' and steps[10]==False and steps[3]:
  233. steps[10]=True
  234. save_time=datetime.now().strftime('%Y%m%d_%H%M')
  235. #save_time=datetime.now().strftime('%Y%m%d_%H')
  236. img_path = f"{SAVE_IMG_PATH}/step11_{save_time}.jpg"
  237. post_path = f"{POST_IMG_PATH2}/step11_{save_time}.jpg"
  238. redis_client.rpush("welding_post_path",post_path)
  239. annotated_frame = results[0].plot()
  240. cv2.imwrite(img_path, annotated_frame)
  241. print("step11完成")
  242. #post("11",post_path)
  243. if welding==True and steps[6]==False:
  244. steps[6]=True
  245. save_time=datetime.now().strftime('%Y%m%d_%H%M')
  246. #save_time=datetime.now().strftime('%Y%m%d_%H')
  247. img_path = f"{SAVE_IMG_PATH}/step7_{save_time}.jpg"
  248. post_path = f"{POST_IMG_PATH2}/step7_{save_time}.jpg"
  249. redis_client.rpush("welding_post_path",post_path)
  250. annotated_frame = results[0].plot()
  251. cv2.imwrite(img_path, annotated_frame)
  252. print("step7完成")
  253. #post("8",post_path)
  254. if video_source==WELDING_CH5_RTSP:
  255. if gloves==True and steps[7]==False:
  256. steps[7]=True
  257. save_time=datetime.now().strftime('%Y%m%d_%H%M')
  258. #save_time=datetime.now().strftime('%Y%m%d_%H')
  259. img_path = f"{SAVE_IMG_PATH}/step8_{save_time}.jpg"
  260. post_path = f"{POST_IMG_PATH2}/step8_{save_time}.jpg"
  261. redis_client.rpush("welding_post_path",post_path)
  262. annotated_frame = results[0].plot()
  263. cv2.imwrite(img_path, annotated_frame)
  264. print("step8完成")
  265. #post("7",post_path)
  266. if grounding_wire=="connect" and steps[2]==False:
  267. steps[2]=True
  268. save_time=datetime.now().strftime('%Y%m%d_%H%M')
  269. #save_time=datetime.now().strftime('%Y%m%d_%H')
  270. img_path = f"{SAVE_IMG_PATH}/step3_{save_time}.jpg"
  271. post_path = f"{POST_IMG_PATH2}/step3_{save_time}.jpg"
  272. redis_client.rpush("welding_post_path",post_path)
  273. annotated_frame = results[0].plot()
  274. cv2.imwrite(img_path, annotated_frame)
  275. print("step3完成")
  276. #post("3",post_path)
  277. if grounding_wire=="disconnect" and steps[9]==False and steps[2]:
  278. steps[9]=True
  279. save_time=datetime.now().strftime('%Y%m%d_%H%M')
  280. #save_time=datetime.now().strftime('%Y%m%d_%H')
  281. img_path = f"{SAVE_IMG_PATH}/step10_{save_time}.jpg"
  282. post_path = f"{POST_IMG_PATH2}/step10_{save_time}.jpg"
  283. redis_client.rpush("welding_post_path",post_path)
  284. annotated_frame = results[0].plot()
  285. cv2.imwrite(img_path, annotated_frame)
  286. print("step10完成")
  287. #post("10",post_path)
  288. if mask==True and steps[5]==False:
  289. steps[5]=True
  290. save_time=datetime.now().strftime('%Y%m%d_%H%M')
  291. #save_time=datetime.now().strftime('%Y%m%d_%H')
  292. img_path = f"{SAVE_IMG_PATH}/step6_{save_time}.jpg"
  293. post_path = f"{POST_IMG_PATH2}/step6_{save_time}.jpg"
  294. redis_client.rpush("welding_post_path",post_path)
  295. annotated_frame = results[0].plot()
  296. cv2.imwrite(img_path, annotated_frame)
  297. print("step6完成")
  298. #post("6",post_path)
  299. start_event.set()
  300. # Display the annotated frame
  301. # cv2.imshow("YOLOv8 Inference", results[0].plot())
  302. # # Break the loop if 'q' is pressed
  303. # if cv2.waitKey(1) & 0xFF == ord("q"):
  304. # break
  305. else:
  306. # Break the loop if the end of the video is reached
  307. break
  308. # Release the video capture object and close the display window
  309. cap.release()
  310. if torch.cuda.is_available():
  311. torch.cuda.empty_cache()
  312. del model