Bladeren bron

Merge pull request #4 from dongxuecheng/dxc/basic_frame

Dxc/basic frame
Xuecheng Dong 7 maanden geleden
bovenliggende
commit
4c729dea42
4 gewijzigde bestanden met toevoegingen van 215 en 0 verwijderingen
  1. 99 0
      app.py
  2. 20 0
      config.py
  3. 27 0
      globals.py
  4. 69 0
      welding_wearing_detect.py

+ 99 - 0
app.py

@@ -0,0 +1,99 @@
+import threading
+import time
+from flask import Flask, jsonify,send_from_directory
+from globals import inference_thread, stop_event,lock,redis_client
+
+#焊接考核的穿戴
+app = Flask(__name__)
+
+
+# Define the /wearing_detection endpoint
+@app.route('/compressed_oxygen_detection', methods=['GET'])
+def compressed_oxygen_detection():
+    global inference_thread#当全局变量需要重新赋值时,需要用global关键字声明
+
+    if inference_thread is None or not inference_thread.is_alive():
+        stop_event.clear()#stop_event不用global声明,因为不需要重新赋值,他只是调用了其方法,并没有重新赋值
+        
+        start_events = []#给每个线程一个事件,让我知道某个线程是否开始检测
+        inference_thread = threading.Thread(target=start_compressed_oxygen_detection,args=(start_events,))
+        inference_thread.start()
+        init_compressed_oxygen_detection()
+
+        # 等待所有YOLO线程开始检测,两个线程检测完毕时,才返回SUCCESS
+        for event in start_events:
+            event.wait()
+
+        app.logger.info('start_compressed_oxygen_detection')
+        return jsonify({"status": "SUCCESS"}), 200
+    
+    else:
+        app.logger.info("start_compressed_oxygen_detection already running")   
+        return jsonify({"status": "ALREADY_RUNNING"}), 200
+    
+
+
+@app.route('/compressed_oxygen_status', methods=['GET']) 
+def compressed_oxygen_status():#开始登录时,检测是否需要复位,若需要,则发送复位信息,否则开始焊接检测
+    #global inference_thread
+    with lock:   
+        #TODO 若出现异常再发送FAIL.
+        redis_client.set("welding_wearing_detection_img_flag",'True')
+        time.sleep(1)
+        if not redis_client.exists("welding_wearing_items_nums") or not redis_client.exists("welding_wearing_detection_img"):
+            return jsonify({"status": "NONE"}), 200##表示穿戴检测线程还未检测完
+        
+        wearing_items_nums = redis_client.lrange("welding_wearing_items_nums", 0, -1)
+        wearing_items_list = ['pants', 'jacket', 'helmet', 'gloves', 'shoes']
+        json_array = []
+        for num, item in zip(wearing_items_nums, wearing_items_list):
+            json_object = {"name": item, "number": num}
+            json_array.append(json_object)
+
+        app.logger.info(json_array)
+        image=redis_client.get("welding_wearing_detection_img")
+        app.logger.info(image)
+
+        return jsonify({"status": "SUCCESS","data":json_array,"image":image}), 200
+
+               
+@app.route('/end_compressed_oxygen_detection', methods=['GET'])
+def end_wearing_exam():
+    init_compressed_oxygen_detection()
+    return jsonify({"status": "SUCCESS"}), 200
+
+    
+
+def stop_inference_internal():
+    global inference_thread
+    if inference_thread is not None and inference_thread.is_alive():
+        stop_event.set()  # 设置停止事件标志,通知推理线程停止运行
+        inference_thread.join()  # 等待推理线程结束
+        inference_thread = None  # 释放线程资源
+        app.logger.info('detection stopped')
+        return True
+    else:
+        app.logger.info('No inference stopped')
+        return False
+
+@app.route('/stop_detection', methods=['GET'])
+def stop_inference():
+    #global inference_thread
+    if stop_inference_internal():
+        app.logger.info('detection stopped')
+        return jsonify({"status": "DETECTION_STOPPED"}), 200
+    else:
+        app.logger.info('No_detection_running')
+        return jsonify({"status": "No_detection_running"}), 200
+
+@app.route('/images/<filename>')
+def get_image(filename):
+    app.logger.info('get_image'+filename)
+    #pdb.set_trace()
+    return send_from_directory('static/images', filename)
+
+
+if __name__ == '__main__':
+
+    # Start the Flask server
+    app.run(debug=False, host='172.16.20.163', port=5001)

+ 20 - 0
config.py

@@ -0,0 +1,20 @@
+import numpy as np
+
+
+#CLIENT_URL = 'http://172.16.20.23:8081/'
+
+SAVE_IMG_PATH = '/mnt/xcd/code/ai_test/static/images'  # 图片保存在服务器的实际位置
+
+POST_IMG_PATH1 = 'http://172.16.20.163:5001/images'  # 通过端口映射post发送能够访问的位置 焊接考核科目1
+POST_IMG_PATH2 = 'http://172.16.20.163:5002/images' #焊接考核科目2
+
+VIDEO_SOURCE = '/mnt/xcd/code/ai_test/static/videos/1.mp4'  # 视频源路径
+#焊接考核视频流
+# Define paths to RTSP streams
+
+
+MODEL_PATH="/mnt/xcd/code/ai_test/weights/ch1_welding_switch_813.pt"
+
+
+
+

+ 27 - 0
globals.py

@@ -0,0 +1,27 @@
+import threading
+# 全局变量来控制推理线程
+import redis
+import time
+# 连接到 Redis 服务器
+redis_client = redis.StrictRedis(host='localhost', port=5050, db=0,decode_responses=True)
+
+inference_thread = None
+stop_event = threading.Event()
+lock=threading.Lock()
+
+###############焊接考核
+#为True时,表示某一步骤完成,并保存图片post
+step1=False 
+step2=False
+step3=False
+step4=False
+step5=False
+step6=False 
+# 压缩氧
+# 1 = 外壳去掉
+# 2 = 脖带戴好 
+# 3 = 咬口具
+# 4 = 氧气瓶开启
+# 5 = 补气
+# 6 = 带鼻夹
+

+ 69 - 0
welding_wearing_detect.py

@@ -0,0 +1,69 @@
+import torch
+import cv2
+import threading
+from datetime import datetime
+from ultralytics import YOLO
+from globals import stop_event,redis_client
+from config import SAVE_IMG_PATH,POST_IMG_PATH1,VIDEO_SOURCE,MODEL_PATH
+
+
+def init_compressed_oxygen_detection():
+    pass
+
+def start_compressed_oxygen_detection(start_events):
+        
+    event = threading.Event()
+    start_events.append(event)
+    thread = threading.Thread(target=process_video, args=(MODEL_PATH,VIDEO_SOURCE,event))
+    thread.daemon=True
+    thread.start()
+    thread.join()
+
+
+def process_video(model_path, video_source, start_event):
+
+    
+    model = YOLO(model_path)
+    cap = cv2.VideoCapture(video_source)
+    while cap.isOpened():
+    # Read a frame from the video
+        success, frame = cap.read()
+        if stop_event.is_set():#控制停止推理
+            break
+        if success:
+            
+            if cap.get(cv2.CAP_PROP_POS_FRAMES) % 10 != 0:#跳帧检测,
+                continue
+
+
+            results = model.predict(frame,conf=0.6,verbose=False)
+
+            for r in results:
+                boxes = r.boxes.xyxy  # 提取所有检测到的边界框坐标
+                confidences = r.boxes.conf  # 提取所有检测到的置信度
+                classes = r.boxes.cls  # 提取所有检测到的类别索引
+
+                
+                for i in range(len(boxes)):
+                    x1, y1, x2, y2 = boxes[i].tolist()
+                    confidence = confidences[i].item()
+                    cls = int(classes[i].item())
+                    label = model.names[cls]
+                pass
+                
+                    
+                start_event.set()    
+
+
+        else:
+            # Break the loop if the end of the video is reached
+            break
+
+        # Release the video capture object and close the display window
+    cap.release()
+    
+    if torch.cuda.is_available():
+        torch.cuda.empty_cache()
+    del model
+
+