149 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from ultralytics import YOLO
 | ||
| from scipy.spatial import procrustes
 | ||
| import numpy as np
 | ||
| import cv2
 | ||
| import time
 | ||
| from scheduler.thread_manager import MyThread
 | ||
| 
 | ||
| __fei_eyes = None
 | ||
| class FeiEyes:
 | ||
|     
 | ||
|     def __init__(self):
 | ||
|     
 | ||
|         """   
 | ||
|         鼻子(0)
 | ||
|         左眼(1),右眼(2)
 | ||
|         左耳(3),右耳(4)
 | ||
|         左肩(5),右肩(6)
 | ||
|         左肘(7),右肘(8)
 | ||
|         左腕(9),右腕(10)
 | ||
|         左髋(11),右髋(12)
 | ||
|         左膝(13),右膝(14)
 | ||
|         左脚踝(15),右脚踝(16)
 | ||
|         """
 | ||
|         self.POSE_PAIRS = [ 
 | ||
|         (3, 5),  (5, 6),  # upper body
 | ||
|         (5, 7), (6, 8), (7, 9), (8, 10),  # lower body
 | ||
|         (11, 12), (11, 13), (12, 14), (13, 15)  # arms
 | ||
|         ]
 | ||
|         self.my_face = np.array([[154.4565, 193.7006],
 | ||
|                 [181.8575, 164.8366],
 | ||
|                 [117.1820, 164.3602],
 | ||
|                 [213.5605, 193.0460],
 | ||
|                 [ 62.7056, 193.5217]])
 | ||
|         self.is_running = False
 | ||
|         self.img = None
 | ||
|         
 | ||
|     def is_sitting(self, keypoints):
 | ||
|         if len(keypoints) < 17:  # 确保有足够的关键点
 | ||
|             return False
 | ||
|         # 检查每个关键点的置信度
 | ||
|         if keypoints[11][2] < 0.5 or keypoints[12][2] < 0.5 or keypoints[13][2] < 0.5 or keypoints[14][2] < 0.5 or keypoints[15][2] < 0.5 or keypoints[16][2] < 0.5:
 | ||
|             return False
 | ||
| 
 | ||
|         left_hip, right_hip = keypoints[11][:2], keypoints[12][:2]
 | ||
|         left_knee, right_knee = keypoints[13][:2], keypoints[14][:2]
 | ||
|         left_ankle, right_ankle = keypoints[15][:2], keypoints[16][:2]
 | ||
| 
 | ||
|         hip_knee_y = (left_hip[1] + right_hip[1] + left_knee[1] + right_knee[1]) / 4
 | ||
|         knee_ankle_y = (left_knee[1] + right_knee[1] + left_ankle[1] + right_ankle[1]) / 4
 | ||
| 
 | ||
|         return hip_knee_y < knee_ankle_y
 | ||
| 
 | ||
|     def is_standing(self, keypoints):
 | ||
|         if len(keypoints) < 17 or keypoints[0][2] < 0.5 or keypoints[15][2] < 0.5 or keypoints[16][2] < 0.5:
 | ||
|             return False
 | ||
| 
 | ||
|         head = keypoints[0][:2]
 | ||
|         left_ankle, right_ankle = keypoints[15][:2], keypoints[16][:2]
 | ||
| 
 | ||
|         return head[1] > left_ankle[1] and head[1] > right_ankle[1]
 | ||
| 
 | ||
|     def get_counts(self):
 | ||
|         if not self.is_running:
 | ||
|             return 0,0,0
 | ||
|         return self.person_count, self.stand_count, self.sit_count
 | ||
| 
 | ||
|     def get_status(self):
 | ||
|         return self.is_running
 | ||
|     
 | ||
|     def get_img(self):
 | ||
|         if self.is_running:
 | ||
|             return self.img
 | ||
|         else:
 | ||
|             return None
 | ||
|     
 | ||
|     def start(self):
 | ||
|         cap = cv2.VideoCapture(0)
 | ||
|         if cap.isOpened():
 | ||
|             self.is_running = True
 | ||
|             MyThread(target=self.run, args=[cap]).start()
 | ||
| 
 | ||
|     def stop(self):
 | ||
|         self.is_running = False
 | ||
| 
 | ||
|     def run(self, cap):
 | ||
|          model = YOLO("yolov8n-pose.pt")
 | ||
|          while self.is_running:
 | ||
|             time.sleep(0.033)
 | ||
|             ret, frame = cap.read()
 | ||
|             self.img = frame
 | ||
|             operated_frame = frame.copy()
 | ||
|             if not ret:
 | ||
|                 break
 | ||
|             results = model.predict(operated_frame, verbose=False)
 | ||
|             person_count = 0
 | ||
|             sit_count = 0
 | ||
|             stand_count = 0
 | ||
|             for res in results:  # loop over results
 | ||
|                 for box, cls in zip(res.boxes.xyxy, res.boxes.cls):  # loop over detections
 | ||
|                     x1, y1, x2, y2 = box
 | ||
|                     cv2.rectangle(operated_frame, (int(x1.item()), int(y1.item())), (int(x2.item()), int(y2.item())), (0, 255, 0), 2)
 | ||
|                     cv2.putText(operated_frame, f"{res.names[int(cls.item())]}", (int(x1.item()), int(y1.item()) - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)        
 | ||
|                 if res.keypoints is not None and res.keypoints.xy.numel() > 0: # check if keypoints exist
 | ||
|                     keypoints = res.keypoints[0]
 | ||
|                     #总人数
 | ||
|                     person_count += 1
 | ||
|                     #坐着的人数
 | ||
|                     if self.is_sitting(keypoints):
 | ||
|                         sit_count += 1
 | ||
|                     #站着的人数
 | ||
|                     elif self.is_standing(keypoints):
 | ||
|                         stand_count += 1
 | ||
| 
 | ||
|                     for keypoint in keypoints:  # loop over keypoints
 | ||
|                        
 | ||
|                         if len(keypoint) == 3: 
 | ||
|                             x, y, conf = keypoint
 | ||
|                             if conf > 0.5:  # draw keypoints with confidence greater than 0.5
 | ||
|                                 cv2.circle(operated_frame, (int(x.item()), int(y.item())), 3, (0, 0, 255), -1)
 | ||
| 
 | ||
|                     # Draw lines connecting keypoints
 | ||
|                     for pair in self.POSE_PAIRS:
 | ||
|                          if pair[0] < len(keypoints) and pair[1] < len(keypoints):
 | ||
|                             pt1, pt2 = keypoints[pair[0]][:2], keypoints[pair[1]][:2]
 | ||
|                             conf1, conf2 = keypoints[pair[0]][2], keypoints[pair[1]][2]
 | ||
|                             if conf1 > 0.5 and conf2 > 0.5:
 | ||
|                             # cv2.line(operated_frame, (int(pt1[0].item()), int(pt1[1].item())), (int(pt2[0].item()), int(pt2[1].item())), (255, 255, 0), 2)
 | ||
|                                 pass
 | ||
|             self.person_count = person_count
 | ||
|             self.sit_count = sit_count
 | ||
|             self.stand_count = stand_count
 | ||
|             cv2.imshow("YOLO v8 Fay Eyes", operated_frame)
 | ||
|             cv2.waitKey(1)
 | ||
| 
 | ||
|          cap.release()
 | ||
|          cv2.destroyAllWindows()
 | ||
| 
 | ||
| 
 | ||
| def new_instance():
 | ||
|     global __fei_eyes
 | ||
|     if __fei_eyes is None:
 | ||
|         __fei_eyes = FeiEyes()
 | ||
|     return __fei_eyes
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
|         
 | ||
| 
 | 
