183 lines
7.8 KiB
Python
183 lines
7.8 KiB
Python
from threading import Thread
|
|
|
|
import numpy as np
|
|
|
|
from PureBackend.general import *
|
|
from MCamera.mn_camera import *
|
|
from MCamera.camera import *
|
|
from Database.manager_database import *
|
|
from score_doc import get_fin_score
|
|
from Exercise_mn.base_exercise import BaseExercise
|
|
|
|
|
|
class Overhang(BaseExercise):
|
|
def __init__(self, info, statistic_time=120, camera=None):
|
|
super().__init__(info, statistic_time, camera=camera)
|
|
# 计时
|
|
self.bar = None
|
|
self.per = None
|
|
self.costtime = 0
|
|
self.endtime = None
|
|
self.starttime = None
|
|
# 动作持续帧数
|
|
self._time = 0
|
|
# 开始标志
|
|
self.form = 0
|
|
# 状态反馈
|
|
self.state = 0
|
|
self.pre_pos = 0
|
|
self.sta_time = time.time()
|
|
self.feedback = "开始"
|
|
self.exercise_type = "屈臂悬垂"
|
|
self.end_test = 0
|
|
self.had_start = False
|
|
self.had_done = False
|
|
# 计时
|
|
self.chronograph = 0
|
|
# 引体向上参数
|
|
self.corner = (0, 480, 260, 380)
|
|
MoveNetAlgorithmPlugin.set_corner(corner=self.corner)
|
|
MoveNetAlgorithmPlugin.set_config(config=self.config)
|
|
|
|
def get_result(self):
|
|
# 人员年龄
|
|
age = self.info.get(AGE)
|
|
# 人员性别
|
|
gender = "woman" if self.info.get(GENDER) == "女" else "man"
|
|
if self.costtime < 0:
|
|
score = 0
|
|
else:
|
|
score = get_fin_score.Military(gender, int(age),
|
|
integratedProjectResult=round(self.costtime,
|
|
1)).IntegratedProjectScoreEvaluation()
|
|
if gender != "woman":
|
|
score = 0
|
|
if self.starttime and self.starttime != 0:
|
|
this_time = time.time()
|
|
count_time = this_time - self.starttime
|
|
else:
|
|
count_time = 0
|
|
|
|
result = {
|
|
"count": self.costtime,
|
|
"score": score,
|
|
"had_done": self.had_done,
|
|
"time": self.chronograph,
|
|
'countdown': count_time
|
|
}
|
|
return result
|
|
|
|
def speak_counting(self, counting_times, name, gender):
|
|
self.speak_driver.start()
|
|
self.speak_driver.speed_control(200)
|
|
self.speak_driver.volume_control(1)
|
|
self.speak_driver.add_speak("考试人员{}".format(name))
|
|
self.speak_driver.add_speak(f"考试项目{self.exercise_type}")
|
|
if gender != "女":
|
|
self.speak_driver.add_speak(f"注意,该考生性别为男性,{self.exercise_type}项目成绩无效")
|
|
|
|
def timekeeping(self):
|
|
start_time = time.time()
|
|
while self.had_start:
|
|
now_time = time.time()
|
|
self.chronograph = int(now_time - start_time)
|
|
time.sleep(0.1)
|
|
if self.had_done:
|
|
break
|
|
|
|
def run(self) -> None:
|
|
self.speak_counting(5, self.info[NAME], self.info[GENDER])
|
|
# 清除历史记录
|
|
# 记录开始时间
|
|
self.start_time = time.time()
|
|
self.is_start = True
|
|
# 不停更新计算和更新画面
|
|
threading.Thread(target=self.thread_counting_streaming, daemon=True).start()
|
|
while not self.is_done():
|
|
_img = self.cap.get_frame()
|
|
self.img = self.display(_img)
|
|
self.is_start = False
|
|
|
|
def display(self, img):
|
|
cv2.rectangle(img, (self.corner[2], self.corner[0]), (self.corner[3], self.corner[1]), (0, 255, 0), 2)
|
|
# 绘制状态条
|
|
cv2.rectangle(img, (650 - 100, 60), (650 - 80, 282), (255, 255, 255), 2)
|
|
if self.bar and self.per:
|
|
cv2.rectangle(img, (650 - 98, int(self.bar)), (650 - 82, 280), (102, 106, 233),
|
|
cv2.FILLED)
|
|
cv2.putText(img, f'{int(self.per)}%', (650 - 125, 320), cv2.FONT_HERSHEY_PLAIN, 2,
|
|
(255, 255, 255), 2)
|
|
# # 绘制计数器
|
|
# cv2.rectangle(img, (0, 480 - 120), (120, 480), (102, 106, 233), cv2.FILLED)
|
|
# cv2.putText(img, str(int(self.count)), (10, 480 - 35), cv2.FONT_HERSHEY_PLAIN, 5,
|
|
# (255, 255, 255), 5)
|
|
# 展示状态反馈
|
|
cv2.rectangle(img, (640 - 160, 0), (640, 50), (102, 106, 233), cv2.FILLED)
|
|
img_output = self.cv2_img_add_text(img, self.feedback, 640 - 120, 5, (255, 255, 255), 38)
|
|
return img_output
|
|
|
|
def analysis(self, frame):
|
|
catch_time = frame[CATCH_TIME]
|
|
if catch_time < self.start_cal_time:
|
|
return
|
|
img = frame[FRAME_DAT]
|
|
lm_list = frame[MN_RESULT]
|
|
self.detector.set_result(lm_list)
|
|
|
|
if len(lm_list) != 0:
|
|
elbow_1 = self.detector.findAngle(img, LEFT_SHOULDER, LEFT_ELBOW, LEFT_WRIST)
|
|
shoulder_1 = self.detector.findAngle(img, LEFT_ELBOW, LEFT_SHOULDER, LEFT_HIP)
|
|
elbow_2 = self.detector.findAngle(img, RIGHT_SHOULDER, RIGHT_ELBOW, RIGHT_WRIST)
|
|
shoulder_2 = self.detector.findAngle(img, RIGHT_ELBOW, RIGHT_SHOULDER, RIGHT_HIP)
|
|
eye_1_y = self.detector.findPosition(img, False)[LEFT_EYE]['key_points'][1]
|
|
eye_2_y = self.detector.findPosition(img, False)[RIGHT_EYE]['key_points'][1]
|
|
nose_y = self.detector.findPosition(img, False)[NOSE]['key_points'][1]
|
|
wrist_1_y = self.detector.findPosition(img, False)[LEFT_WRIST]['key_points'][1]
|
|
wrist_2_y = self.detector.findPosition(img, False)[RIGHT_WRIST]['key_points'][1]
|
|
shoulder_1_y = self.detector.findPosition(img, False)[LEFT_SHOULDER]['key_points'][1]
|
|
shoulder_2_y = self.detector.findPosition(img, False)[RIGHT_SHOULDER]['key_points'][1]
|
|
|
|
|
|
# 成功概率
|
|
self.per = np.interp(elbow_1, (90, 160), (0, 100))
|
|
# 显示进度栏
|
|
self.bar = np.interp(elbow_1, (90, 160), (280, 62))
|
|
if self.pre_pos == 0:
|
|
self.pre_pos = 1
|
|
self.speak_driver.add_speak("请进入准备状态")
|
|
|
|
if self.form == 0:
|
|
if time.time() - self.sta_time > 1.5:
|
|
if elbow_1 > 150 and elbow_2 > 150 and shoulder_1 > 100 and shoulder_2 > 100 and eye_1_y > wrist_1_y and eye_2_y > wrist_2_y:
|
|
self.form = 1
|
|
self.speak_driver.add_speak("请开始考试")
|
|
|
|
elif self.pre_pos == 1 and self.form == 1:
|
|
hand_1_y = wrist_1_y - (shoulder_1_y - wrist_1_y) / 3
|
|
hand_2_y = wrist_2_y - (shoulder_2_y - wrist_2_y) / 3
|
|
head_1_y = nose_y + (nose_y - eye_1_y) * 1.3
|
|
head_2_y = nose_y + (nose_y - eye_2_y) * 1.3
|
|
if elbow_1 > 120 and elbow_2 > 120 and head_1_y > hand_1_y and head_2_y > hand_2_y:
|
|
if self.state == 1:
|
|
self.end_test += 1
|
|
if self.end_test > 3:
|
|
self.endtime = time.time()
|
|
self.costtime = round(self.endtime - self.starttime, 3)
|
|
self.speak_driver.add_speak("考试结束")
|
|
Thread(target=self.speak_driver.add_speak,
|
|
args=(f"总耗时为{round(self.costtime, 2)}秒",)).start()
|
|
self.pre_pos = 2
|
|
self.had_done = True
|
|
|
|
if elbow_1 < 90 and elbow_2 < 90 and head_1_y < hand_1_y and head_2_y < hand_2_y:
|
|
if self.state == 0:
|
|
self.feedback = "悬垂"
|
|
self._time += 1
|
|
if self._time > 3:
|
|
self._time = 0
|
|
self.starttime = time.time()
|
|
self.had_start = True
|
|
self.state = 1
|
|
self.speak_driver.add_speak("计时开始")
|
|
threading.Thread(target=self.timekeeping).start()
|