basket_cleaning_detect.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. import cv2
  2. import torch
  3. from shapely.geometry import box, Polygon
  4. import threading
  5. import numpy as np
  6. from datetime import datetime
  7. from ultralytics import YOLO
  8. from utils.tool import IoU
  9. from globals import stop_event,redis_client
  10. from config import SAVE_IMG_PATH,POST_IMG_PATH5,BASKET_CLEANING_VIDEO_SOURCES,BASKET_CLEANING_MODEL_SOURCES
  11. from config import BASKET_SUSPENSION_REGION,BASKET_STEEL_WIRE_REGION,BASKET_PLATFORM_REGION,BASKET_LIFTING_REGION,BASKET_ELECTRICAL_SYSTEM_REGION,BASKET_SAFETY_LOCK_REGION,BASKET_EMPTY_LOAD_REGION,BASKET_CLEANING_OPERATION_REGION
  12. from globals import basket_suspension_flag,basket_warning_zone_flag,basket_steel_wire_flag,basket_platform_flag,basket_person_flag
  13. from globals import basket_electrical_system_flag,basket_lifting_flag,basket_safety_lock_flag,basket_safety_belt_flag,basket_empty_load_flag,basket_cleaning_operation_flag,basket_cleaning_up_flag
  14. def init_basket_cleaning_detection():
  15. global basket_suspension_flag,basket_warning_zone_flag,basket_steel_wire_flag,basket_platform_flag,basket_electrical_system_flag,basket_lifting_flag,basket_safety_lock_flag,basket_safety_belt_flag,basket_cleaning_up_flag,basket_cleaning_operation_flag,basket_empty_load_flag,basket_person_flag
  16. basket_suspension_flag=False
  17. basket_warning_zone_flag=False
  18. basket_steel_wire_flag=False
  19. basket_platform_flag=False
  20. basket_electrical_system_flag=False
  21. basket_lifting_flag=False
  22. basket_safety_lock_flag=False
  23. basket_safety_belt_flag=False
  24. basket_cleaning_up_flag=False
  25. basket_cleaning_operation_flag=False
  26. basket_empty_load_flag=False
  27. basket_person_flag=False
  28. for i in range(1, 12):
  29. redis_client.delete(f"basket_step_{i}")
  30. redis_client.delete("basket_cleaning_order")
  31. pass
  32. def start_basket_cleaning_detection(start_events):
  33. threads = []
  34. for model_path, video_source in zip(BASKET_CLEANING_MODEL_SOURCES,BASKET_CLEANING_VIDEO_SOURCES):
  35. event = threading.Event()
  36. start_events.append(event)
  37. thread = threading.Thread(target=process_video, args=(model_path, video_source,event))
  38. threads.append(thread)
  39. thread.daemon=True
  40. thread.start()
  41. print("吊篮清洗子线程运行中")
  42. # Wait for any threads to complete
  43. for thread in threads:
  44. thread.join()
  45. print("吊篮清洗子线程运行结束")
  46. def point_in_region(point, region):#判断点是否在多边形内
  47. is_inside = cv2.pointPolygonTest(region.reshape((-1, 1, 2)), point, False)
  48. return is_inside >= 0
  49. def save_image_and_redis(redis_client, results, step_name, save_path, post_path):
  50. save_time = datetime.now().strftime('%Y%m%d_%H%M')
  51. imgpath = f"{save_path}/{step_name}_{save_time}.jpg"
  52. annotated_frame = results[0].plot()
  53. if step_name == "basket_step_2":
  54. annotated_frame = cv2.polylines(annotated_frame, [region.reshape(-1, 1, 2) for region in BASKET_SUSPENSION_REGION], isClosed=True, color=(0, 255, 0), thickness=4)
  55. elif step_name == "basket_step_3":
  56. annotated_frame = cv2.polylines(annotated_frame, [region.reshape(-1, 1, 2) for region in BASKET_STEEL_WIRE_REGION], isClosed=True, color=(0, 255, 0), thickness=4)
  57. elif step_name == "basket_step_4":
  58. annotated_frame = cv2.polylines(annotated_frame, [BASKET_PLATFORM_REGION.reshape(-1, 1, 2)], isClosed=True, color=(0, 255, 0), thickness=4)
  59. #cv2.fillPoly(annotated_frame, [BASKET_PLATFORM_REGION], (0, 255, 0))#填充区域
  60. elif step_name == "basket_step_5":
  61. annotated_frame = cv2.polylines(annotated_frame, [region.reshape(-1, 1, 2) for region in BASKET_LIFTING_REGION], isClosed=True, color=(0, 255, 0), thickness=4)
  62. elif step_name == "basket_step_6":
  63. annotated_frame = cv2.polylines(annotated_frame, [region.reshape(-1, 1, 2) for region in BASKET_SAFETY_LOCK_REGION], isClosed=True, color=(0, 255, 0), thickness=4)
  64. elif step_name == "basket_step_7":
  65. annotated_frame = cv2.polylines(annotated_frame, [BASKET_ELECTRICAL_SYSTEM_REGION.reshape(-1, 1, 2)], isClosed=True, color=(0, 255, 0), thickness=4)
  66. cv2.imwrite(imgpath, annotated_frame)
  67. redis_client.set(step_name, post_path)
  68. redis_client.rpush("basket_cleaning_order", step_name)
  69. def get_region_mean_color(regions_security_lock_and_work_area, img):
  70. for region in regions_security_lock_and_work_area:
  71. points = np.array(region, dtype=np.int32)
  72. mask = np.zeros(img.shape[:2], dtype=np.uint8)
  73. cv2.fillPoly(mask, [points], 255)
  74. roi = cv2.bitwise_and(img, img, mask=mask)
  75. mean_color = cv2.mean(roi)
  76. # 将BGR颜色均值再平均
  77. average_color_value = sum(mean_color[:3]) / 3
  78. # 判断平均值是否大于0.30
  79. if average_color_value < 0.30:
  80. return True
  81. else:
  82. return False
  83. def process_video(model_path, video_source,start_event):
  84. model = YOLO(model_path)
  85. cap = cv2.VideoCapture(video_source)
  86. #cap.set(cv2.CAP_PROP_BUFFERSIZE, 100) # 设置缓冲区大小为 10 帧
  87. while cap.isOpened():
  88. if stop_event.is_set():#控制停止推理
  89. break
  90. success, frame = cap.read()
  91. if success:
  92. # Run YOLOv8 inference on the frame
  93. if cap.get(cv2.CAP_PROP_POS_FRAMES) % 25 != 0:
  94. continue
  95. results = model.predict(frame,conf=0.2,verbose=False)
  96. global basket_suspension_flag,basket_warning_zone_flag,basket_steel_wire_flag,basket_platform_flag,basket_electrical_system_flag,basket_lifting_flag,basket_safety_lock_flag,basket_safety_belt_flag,basket_cleaning_up_flag,basket_cleaning_operation_flag,basket_empty_load_flag,basket_person_flag
  97. global BASKET_PLATFORM_REGION,BASKET_LIFTING_REGION,BASKET_ELECTRICAL_SYSTEM_REGION
  98. for r in results:
  99. if model_path==BASKET_CLEANING_MODEL_SOURCES[0] and not basket_suspension_flag:#D4悬挂机构
  100. boxes=r.boxes.xyxy#人体的检测框
  101. keypoints = r.keypoints.xy
  102. confidences = r.keypoints.conf
  103. for i in range(len(boxes)):
  104. left_wrist, right_wrist = keypoints[i][9:11].tolist()#获取左右手腕和左右肘的坐标
  105. points = [left_wrist, right_wrist]
  106. is_inside1 = any(point_in_region(point, BASKET_SUSPENSION_REGION[0]) for point in points)
  107. is_inside2 = any(point_in_region(point, BASKET_SUSPENSION_REGION[1]) for point in points)
  108. is_inside3 = any(point_in_region(point, BASKET_SUSPENSION_REGION[2]) for point in points)
  109. is_inside4 = any(point_in_region(point, BASKET_SUSPENSION_REGION[3]) for point in points)
  110. if is_inside1 or is_inside2 or is_inside3 or is_inside4:
  111. basket_suspension_flag=True#悬挂机构
  112. print("悬挂机构")
  113. # elif model_path==BASKET_CLEANING_MODEL_SOURCES[1]:#D5吊篮悬挂
  114. # boxes = r.boxes.xyxy
  115. # confidences = r.boxes.conf
  116. # classes = r.boxes.cls
  117. # basket_warning_zone_flag=False#当检测不到则为False
  118. # basket_cleaning_up_flag=False
  119. # for i in range(len(boxes)):
  120. # x1, y1, x2, y2 = boxes[i].tolist()
  121. # confidence = confidences[i].item()
  122. # cls = int(classes[i].item())
  123. # label = model.names[cls]
  124. # if label=='warning_zone':
  125. # basket_warning_zone_flag=True
  126. # elif label=='brush':
  127. # basket_cleaning_up_flag=True
  128. # elif label=='person':
  129. elif model_path==BASKET_CLEANING_MODEL_SOURCES[1]:#D6,pose
  130. boxes=r.boxes.xyxy#人体的检测框
  131. keypoints = r.keypoints.xy
  132. confidences = r.keypoints.conf
  133. basket_person_flag=False#当检测不到则为False
  134. for i in range(len(boxes)):
  135. #当有检测框,则说明有人
  136. basket_person_flag=True
  137. left_wrist, right_wrist = keypoints[i][9:11].tolist()#获取左右手腕和左右肘的坐标
  138. points = [left_wrist, right_wrist]
  139. if not basket_steel_wire_flag:
  140. is_inside1 = any(point_in_region(point, BASKET_STEEL_WIRE_REGION[0]) for point in points)
  141. is_inside2 = any(point_in_region(point, BASKET_STEEL_WIRE_REGION[1]) for point in points)
  142. #is_inside3 = any(point_in_region(point, BASKET_STEEL_WIRE_REGION[2]) for point in points)
  143. #is_inside4 = any(point_in_region(point, BASKET_STEEL_WIRE_REGION[3]) for point in points)
  144. if is_inside1 or is_inside2:
  145. basket_steel_wire_flag=True#钢丝绳
  146. print("钢丝绳")
  147. if not basket_platform_flag:
  148. is_inside = any(point_in_region(point, BASKET_PLATFORM_REGION) for point in points)
  149. if is_inside:
  150. basket_platform_flag=True
  151. print("平台")
  152. if not basket_lifting_flag:
  153. is_inside = any(point_in_region(point, BASKET_LIFTING_REGION) for point in points)
  154. if is_inside:
  155. basket_lifting_flag=True
  156. print("提升机")
  157. if not basket_electrical_system_flag:
  158. is_inside = any(point_in_region(point, BASKET_ELECTRICAL_SYSTEM_REGION) for point in points)
  159. if is_inside:
  160. basket_electrical_system_flag=True
  161. print("电气系统")
  162. if not basket_safety_lock_flag:
  163. is_inside1 = any(point_in_region(point, BASKET_SAFETY_LOCK_REGION[0]) for point in points)
  164. is_inside2 = any(point_in_region(point, BASKET_SAFETY_LOCK_REGION[1]) for point in points)
  165. if is_inside1 or is_inside2:
  166. basket_safety_lock_flag=True
  167. print("安全锁")
  168. #print(point_in_region([709,1017],BASKET_PLATFORM_REGION))
  169. if not basket_person_flag and point_in_region([709,1017],BASKET_PLATFORM_REGION):
  170. basket_empty_load_flag=True
  171. elif model_path==BASKET_CLEANING_MODEL_SOURCES[2]:#d6目标检测
  172. boxes = r.boxes.xyxy
  173. confidences = r.boxes.conf
  174. classes = r.boxes.cls
  175. #basket_safety_lock_flag=False#当检测不到则为False
  176. for i in range(len(boxes)):
  177. x1, y1, x2, y2 = boxes[i].tolist()
  178. confidence = confidences[i].item()
  179. cls = int(classes[i].item())
  180. label = model.names[cls]
  181. if label=='safety_belt':
  182. basket_safety_belt_flag=True
  183. elif label=='brush':
  184. #is_inside = any(point_in_region([(x1+x2)/2,(y1+y2)/2],BASKET_CLEANING_OPERATION_REGION) for point in points)
  185. is_inside = point_in_region([(x1+x2)/2,(y1+y2)/2],BASKET_CLEANING_OPERATION_REGION)
  186. if is_inside:
  187. basket_cleaning_operation_flag=True
  188. elif label=='warning_zone':
  189. basket_warning_zone_flag=True
  190. # print("警戒区")
  191. elif model_path==BASKET_CLEANING_MODEL_SOURCES[3]:#d6分割
  192. boxes = r.boxes.xyxy
  193. masks = r.masks.xy
  194. classes = r.boxes.cls
  195. hoist=[]
  196. for i in range(len(boxes)):
  197. x1, y1, x2, y2 = boxes[i].tolist()
  198. cls = int(classes[i].item())
  199. label = model.names[cls]
  200. if label=="basket":
  201. BASKET_PLATFORM_REGION = np.array(masks[i].tolist(), np.int32)
  202. elif label=="hoist":
  203. #hoist.append(masks[i].tolist())
  204. #hoist.append(np.array(masks[i].tolist(), np.int32))
  205. # print(masks[i].tolist())
  206. BASKET_LIFTING_REGION = np.array(masks[i].tolist(),np.int32)
  207. #pass
  208. #TODO
  209. elif label=="electricalSystem":
  210. BASKET_ELECTRICAL_SYSTEM_REGION = np.array(masks[i].tolist(), np.int32)
  211. # 检查是否所有hoist masks具有相同形状
  212. # if all(h.shape == hoist[0].shape for h in hoist):
  213. # BASKET_LIFTING_REGION = np.vstack(hoist) # 堆叠成二维数组
  214. # else:
  215. # # 如果形状不同,可以手动处理,比如补齐/裁剪
  216. # # 这里假设你想补齐到最大的形状
  217. # max_shape = max(h.shape for h in hoist)
  218. # padded_hoist = [np.pad(h, ((0, max_shape[0] - h.shape[0]), (0, max_shape[1] - h.shape[1])), mode='constant') for h in hoist]
  219. # BASKET_LIFTING_REGION = np.array(padded_hoist)
  220. #BASKET_LIFTING_REGION = np.array(hoist,np.int32)
  221. #print("hoist",hoist.shape)
  222. if model_path==BASKET_CLEANING_MODEL_SOURCES[0] and not redis_client.exists("basket_step_2") and basket_suspension_flag:#D4悬挂机构
  223. save_image_and_redis(redis_client, results, "basket_step_2", SAVE_IMG_PATH, POST_IMG_PATH5)
  224. elif model_path==BASKET_CLEANING_MODEL_SOURCES[2]:
  225. if basket_warning_zone_flag and not redis_client.exists("basket_step_1"):#警戒区
  226. save_image_and_redis(redis_client, results, "basket_step_1", SAVE_IMG_PATH, POST_IMG_PATH5)
  227. print("警戒区")
  228. elif redis_client.exists("basket_step_12") and not redis_client.exists("basket_step_11"):
  229. save_image_and_redis(redis_client, results, "basket_step_11", SAVE_IMG_PATH, POST_IMG_PATH5)
  230. print("清理现场")
  231. elif not basket_warning_zone_flag and redis_client.exists("basket_step_1") and not redis_client.exists("basket_step_12"):
  232. save_image_and_redis(redis_client, results, "basket_step_12", SAVE_IMG_PATH, POST_IMG_PATH5)
  233. print("警戒区消失")
  234. elif basket_safety_belt_flag and not redis_client.exists("basket_step_9"):
  235. save_image_and_redis(redis_client, results, "basket_step_9", SAVE_IMG_PATH, POST_IMG_PATH5)
  236. elif basket_cleaning_operation_flag and not redis_client.exists("basket_step_10"):
  237. save_image_and_redis(redis_client, results, "basket_step_10", SAVE_IMG_PATH, POST_IMG_PATH5)
  238. print("清洗作业")
  239. elif model_path==BASKET_CLEANING_MODEL_SOURCES[1]:#D6,pose
  240. if basket_steel_wire_flag and not redis_client.exists("basket_step_3"):
  241. save_image_and_redis(redis_client, results, "basket_step_3", SAVE_IMG_PATH, POST_IMG_PATH5)
  242. elif basket_platform_flag and not redis_client.exists("basket_step_4"):
  243. save_image_and_redis(redis_client, results, "basket_step_4", SAVE_IMG_PATH, POST_IMG_PATH5)
  244. elif basket_lifting_flag and not redis_client.exists("basket_step_5"):
  245. save_image_and_redis(redis_client, results, "basket_step_5", SAVE_IMG_PATH, POST_IMG_PATH5)
  246. elif basket_electrical_system_flag and not redis_client.exists("basket_step_7"):
  247. save_image_and_redis(redis_client, results, "basket_step_7", SAVE_IMG_PATH, POST_IMG_PATH5)
  248. elif basket_safety_lock_flag and not redis_client.exists("basket_step_6"):
  249. save_image_and_redis(redis_client, results, "basket_step_6", SAVE_IMG_PATH, POST_IMG_PATH5)
  250. elif basket_empty_load_flag and not redis_client.exists("basket_step_8"):
  251. save_image_and_redis(redis_client, results, "basket_step_8", SAVE_IMG_PATH, POST_IMG_PATH5)
  252. print("空载")
  253. #else:#d6目标检测
  254. start_event.set()
  255. else:
  256. # Break the loop if the end of the video is reached
  257. break
  258. # Release the video capture object and close the display window
  259. cap.release()
  260. if torch.cuda.is_available():
  261. torch.cuda.empty_cache()
  262. del model