analyse_func.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. # -!- coding: utf-8 -!-
  2. import numpy as np
  3. import cv2 as cv
  4. import math
  5. import sys
  6. from demo_func import run_openpose_for_image_front, run_openpose_for_image_side
  7. def text_save(filename, data):
  8. file = open(filename, 'w', encoding='utf-8')
  9. for i in range(len(data)):
  10. s = str(data[i]).replace('[', '').replace(']', '')
  11. s = s.replace("'", '').replace(',', '') + '\n'
  12. file.write(s)
  13. file.close()
  14. print("保存成功")
  15. def angle(v1, v2):
  16. dx1 = v1[2] - v1[0]
  17. dy1 = v1[3] - v1[1]
  18. dx2 = v2[2] - v2[0]
  19. dy2 = v2[3] - v2[1]
  20. angle1 = math.atan2(dy1, dx1)
  21. angle1 = round(angle1 * 180.0 / math.pi, 2)
  22. # print(angle1)
  23. angle2 = math.atan2(dy2, dx2)
  24. angle2 = round(angle2 * 180.0 / math.pi, 2)
  25. # print(angle2)
  26. if angle1 * angle2 >= 0:
  27. included_angle = abs(angle1 - angle2)
  28. else:
  29. included_angle = abs(angle1) + abs(angle2)
  30. if included_angle > 180:
  31. included_angle = 360 - included_angle
  32. return included_angle
  33. def angle_for_xo(v1, v2):
  34. dx1 = v1[2] - v1[0]
  35. dy1 = v1[3] - v1[1]
  36. dx2 = v2[2] - v2[0]
  37. dy2 = v2[3] - v2[1]
  38. angle1 = math.atan2(dy1, dx1)
  39. angle1 = round(angle1 * 180.0 / math.pi, 2)
  40. angle2 = math.atan2(dy2, dx2)
  41. angle2 = round(angle2 * 180.0 / math.pi, 2)
  42. return angle1 - angle2
  43. def cal_head_extra_stress(angle):
  44. HEAD_STRESS_ARGUMENT_0 = 11
  45. HEAD_STRESS_ARGUMENT_1 = 1.02777777777769
  46. HEAD_STRESS_ARGUMENT_2 = 0.00981481481482367
  47. HEAD_STRESS_ARGUMENT_3 = -0.000567901234568158
  48. HEAD_STRESS_ARGUMENT_4 = 0.00000576131687243021
  49. return (HEAD_STRESS_ARGUMENT_1 * angle + HEAD_STRESS_ARGUMENT_2 * pow(angle, 2) \
  50. + HEAD_STRESS_ARGUMENT_3 * pow(angle, 3) + HEAD_STRESS_ARGUMENT_4 * pow(angle, 4)) / HEAD_STRESS_ARGUMENT_0
  51. def analyse_npy_front(npy_front, height):
  52. levels = {
  53. # (level, threshold)
  54. "head_angle": [
  55. (0, 4), (1, 10), (2, 20)
  56. ],
  57. "shoulder_angle": [
  58. (0, 2.8), (1, 8), (2, 15)
  59. ],
  60. "shoulder_offset": [
  61. (0, 3), (1, 8), (2, 15)
  62. ],
  63. "hip_angle": [
  64. (0, 2.19), (1, 8), (2, 15)
  65. ],
  66. "hip_offset": [
  67. (0, 2.19), (1, 8), (2, 15)
  68. ],
  69. "leg_angle": 4
  70. }
  71. result = []
  72. data = np.load(npy_front)
  73. print("------------------")
  74. result.append("------------------")
  75. print("正面分析内容如下:")
  76. result.append("正面分析内容如下:")
  77. # h-eye - h-elbow
  78. h_pixel_eye2elbow = abs(data[14][1] - data[3][1])
  79. # print("h_pixel{}".format(h_pixel_eye2elbow))
  80. h_real_eye2elbow = float(height) * 0.333
  81. # print("h_real{}".format(h_real_eye2elbow))
  82. # body mid x
  83. ankle_mid_x = (data[13][0] + data[10][0]) / 2
  84. # for head
  85. ear_r_x = data[16][0]
  86. ear_r_y = data[16][1]
  87. ear_l_x = data[17][0]
  88. ear_l_y = data[17][1]
  89. head_angle = angle([ear_r_x, ear_r_y, ear_l_x, ear_l_y], [0, 0, 1, 0])
  90. head_front_level = 0
  91. for level in levels["head_angle"]:
  92. head_front_level = level[0]
  93. if head_angle <= level[1]:
  94. break
  95. head_direction = None
  96. if ear_l_y < ear_l_y:
  97. head_direction = "左"
  98. elif ear_l_y > ear_r_y:
  99. head_direction = "右"
  100. if head_front_level > 0 and head_direction:
  101. print("头部分析:头部{}部高,向右倾斜,角度为{}度".format(head_direction, round(head_angle,2)))
  102. result.append("头部分析:头部{}部高,向右倾斜,角度为{}度".format(head_direction, round(head_angle,2)))
  103. else:
  104. print("头部分析:头部保持较好平衡")
  105. result.append("头部分析:头部保持较好平衡")
  106. result.append(head_front_level)
  107. print(head_front_level)
  108. # for shoulder
  109. shoulder_r_x = data[2][0]
  110. shoulder_r_y = data[2][1]
  111. shoulder_l_x = data[5][0]
  112. shoulder_l_y = data[5][1]
  113. shoulder_mid_x = (shoulder_l_x + shoulder_r_x) / 2
  114. neck_x = data[1][0] - 2
  115. shoulder_offset = (shoulder_mid_x - neck_x) * h_real_eye2elbow / h_pixel_eye2elbow
  116. shoulder_angle = angle([shoulder_r_x, shoulder_r_y, shoulder_l_x, shoulder_l_y], [0, 0, 1, 0])
  117. shoulder_angle = min(shoulder_angle, abs(shoulder_angle - 3))
  118. shoulder_angle_level = 0
  119. shoulder_offset_level = 0
  120. for level in levels["shoulder_angle"]:
  121. shoulder_angle_level = level[0]
  122. if shoulder_angle <= level[1]:
  123. break
  124. for level in levels["shoulder_offset"]:
  125. shoulder_offset_level = level[0]
  126. if shoulder_offset <= level[1]:
  127. break
  128. if shoulder_offset_level == 0:
  129. shoulder_level = shoulder_angle_level
  130. elif shoulder_angle_level == 0:
  131. shoulder_level = shoulder_offset_level
  132. else:
  133. shoulder_level = round(0.6 * shoulder_angle_level + 0.4 * shoulder_offset_level)
  134. result.append("肩部分析:")
  135. print("肩部分析:")
  136. shoulder_offset_direction = None
  137. if shoulder_offset > 0:
  138. shoulder_offset_direction = "左"
  139. elif shoulder_offset < 0:
  140. shoulder_offset_direction = "右"
  141. shoulder_angle_direction = None
  142. if shoulder_l_y < shoulder_r_y:
  143. shoulder_angle_direction = "右"
  144. elif shoulder_l_y > shoulder_r_y:
  145. shoulder_angle_direction = "左"
  146. if shoulder_offset_direction:
  147. print("肩部向{}横移,距离为{}cm".format(shoulder_offset_direction, round(abs(shoulder_offset), 2)))
  148. result.append("肩部向{}横移,距离为{}cm".format(shoulder_offset_direction, round(abs(shoulder_offset), 2)))
  149. else:
  150. print("肩部中心位居中轴,位置良好")
  151. result.append("肩部中心位居中轴,位置良好")
  152. if shoulder_angle_direction:
  153. print("肩部向{}倾斜角度为{}度".format(shoulder_angle_direction, round(shoulder_angle,2)))
  154. result.append("肩部向{}倾斜角度为{}度".format(shoulder_angle_direction, round(shoulder_angle,2)))
  155. else:
  156. print("肩部无左右倾斜")
  157. result.append("肩部无左右倾斜")
  158. result.append(shoulder_level)
  159. print(shoulder_level)
  160. # for hip
  161. hip_r_x = data[8][0]
  162. hip_r_y = data[8][1]
  163. hip_l_x = data[11][0]
  164. hip_l_y = data[11][1]
  165. hip_mid_x = (hip_r_x + hip_l_x) / 2
  166. hip_offset = (hip_mid_x - ankle_mid_x) * h_real_eye2elbow / h_pixel_eye2elbow
  167. hd_hip = abs(data[11][1] - data[8][1])
  168. d_hip = math.sqrt((hip_l_x - hip_r_x) ** 2 + (hip_l_y - hip_r_y) ** 2)
  169. rate_hip = hd_hip / d_hip
  170. hip_angle = angle([hip_r_x, hip_r_y, hip_l_x, hip_l_y], [0, 0, 1, 0])
  171. hip_angle_level = 0
  172. hip_offset_level = 0
  173. for level in levels["hip_angle"]:
  174. hip_angle_level = level[0]
  175. if hip_angle <= level[1]:
  176. break
  177. for level in levels["hip_offset"]:
  178. hip_offset_level = level[0]
  179. if hip_offset <= level[1]:
  180. break
  181. print("髋部分析:")
  182. result.append("髋部分析:")
  183. hip_offset_direction = None
  184. if hip_offset > 0:
  185. hip_offset_direction = "左"
  186. elif hip_offset < 0:
  187. hip_offset_direction = "右"
  188. hip_angle_direction = None
  189. if hip_l_y < hip_r_y:
  190. hip_angle_direction = "右"
  191. elif hip_l_y > hip_r_y:
  192. hip_angle_direction = "左"
  193. if hip_offset_direction:
  194. print("髋部向{}横移,距离为{}cm".format(hip_offset_direction, round(abs(hip_offset), 2)))
  195. result.append("髋部向{}横移,距离为{}cm".format(hip_offset_direction, round(abs(hip_offset), 2)))
  196. else:
  197. print("髋部中心位居中轴,位置良好")
  198. result.append("髋部中心位居中轴,位置良好")
  199. if hip_angle_direction:
  200. print("髋部向{}倾斜角度为{}度".format(hip_angle_direction, round(hip_angle,2)))
  201. result.append("髋部向{}倾斜角度为{}度".format(hip_angle_direction, round(hip_angle,2)))
  202. else:
  203. print("髋部角度保持较好平衡")
  204. result.append("髋部角度保持较好平衡")
  205. hip_level = round(0.6 * hip_offset_level + 0.4 * hip_angle_level)
  206. print(hip_level)
  207. result.append(hip_level)
  208. #
  209. print("腿型分析:")
  210. result.append("腿型分析:")
  211. # for knee distance
  212. knee_r_x = data[9][0]
  213. knee_r_y = data[9][1]
  214. knee_l_x = data[12][0]
  215. knee_l_y = data[12][1]
  216. ankle_r_x = data[10][0]
  217. ankle_r_y = data[10][1]
  218. ankle_l_x = data[13][0]
  219. ankle_l_y = data[13][1]
  220. xo_l_angle = angle_for_xo([hip_l_x, hip_l_y, knee_l_x, knee_l_y], [hip_l_x, hip_l_y, ankle_l_x, ankle_l_y])
  221. xo_r_angle = angle_for_xo([hip_r_x, hip_r_y, knee_r_x, knee_r_y], [hip_r_x, hip_r_y, ankle_r_x, ankle_r_y])
  222. xo_angle = max(abs(xo_l_angle), abs(xo_r_angle))
  223. if xo_angle > levels["leg_angle"]:
  224. xo_direction = "X" if xo_l_angle < 0 and xo_l_angle + xo_r_angle < 0 else "O"
  225. print("腿型可能为{}型腿".format(xo_direction))
  226. result.append("腿型可能为{}型腿".format(xo_direction))
  227. else:
  228. print("腿型基本正常,非X、O型腿")
  229. result.append("腿型基本正常,非X、O型腿")
  230. return result
  231. def analyse_npy_side(npy_side, height):
  232. levels = {
  233. "head_forward_angle": [
  234. (0, 4.57), (1, 8), (2, 15)
  235. ],
  236. "up_forward_angle": [
  237. (0, 5), (1, 10), (2, 15)
  238. ],
  239. "hip_forward_offset": [
  240. (0, 3), (1, 5), (2, 8)
  241. ],
  242. "knee_forward_angle": [
  243. (0, 3.86), (1, 8), (2, 13)
  244. ]
  245. }
  246. result = []
  247. data = np.load(npy_side)
  248. h_pixel_eye2elbow = abs(data[14][1] - data[3][1])
  249. # print("h_pixel{}".format(h_pixel_eye2elbow))
  250. h_real_eye2elbow = float(height) * 0.333
  251. result.append(" ")
  252. print("------------------")
  253. result.append("------------------")
  254. print("侧面分析内容如下:")
  255. result.append("侧面分析内容如下:")
  256. # for head
  257. ear_r_x = data[len(data) - 1][0]
  258. ear_r_y = data[len(data) - 1][1]
  259. shoulder_r_x = data[2][0]
  260. shoulder_r_y = data[2][1]
  261. head_forward_angle = angle([shoulder_r_x, shoulder_r_y, ear_r_x, ear_r_y, ], [0, 0, 0, -1])
  262. head_forward_level = 0
  263. head_extra_stress = round(cal_head_extra_stress(head_forward_angle), 2) if 0 < head_forward_angle < 90 else 0
  264. for level in levels["head_forward_angle"]:
  265. head_forward_level = level[0]
  266. if head_forward_angle <= level[1]:
  267. break
  268. head_forward_direction = None
  269. if ear_r_x > shoulder_r_x:
  270. head_forward_direction = "前倾"
  271. elif ear_r_x < shoulder_r_x:
  272. head_forward_direction = "后仰"
  273. if head_forward_direction:
  274. print("头部{}角度为{}度,颈椎额外承受压力为头部重量{}倍".format(head_forward_direction, round(head_forward_angle, 2),
  275. round(head_extra_stress,2)))
  276. result.append("头部{}角度为{}度,颈椎额外承受压力为头部重量{}倍".format(head_forward_direction, round(head_forward_angle, 2),
  277. round(head_extra_stress,2)))
  278. else:
  279. print("无头部前倾问题")
  280. result.append("无头部前倾问题")
  281. print(head_forward_level)
  282. result.append(head_forward_level)
  283. # upper part of body
  284. neck_x = data[1][0]
  285. neck_y = data[1][1]
  286. ankle_r_x = data[10][0]
  287. ankle_r_y = data[10][1]
  288. up_angle = round(angle([ankle_r_x, ankle_r_y, neck_x, neck_y], [0, 0, 0, -1]), 2)
  289. up_angle = min(up_angle, abs(up_angle - 3))
  290. up_level = 0
  291. for level in levels["up_forward_angle"]:
  292. up_level = level[0]
  293. if up_angle <= level[1]:
  294. break
  295. up_forward_direction = "后仰" if neck_x < ankle_r_x else "前倾"
  296. up_state = "身体{}{}度".format(up_forward_direction, round(up_angle,2))
  297. print("站姿分析:{}".format(up_state))
  298. result.append("站姿分析:{}".format(up_state))
  299. print(up_level)
  300. result.append(up_level)
  301. # for hip
  302. hip_risk_level = 0
  303. hip_r_x = data[8][0] - 2
  304. hip_r_y = data[8][1]
  305. knee_r_x = data[9][0]
  306. knee_r_y = data[9][1]
  307. hip_offset = abs((hip_r_x - ankle_r_x)) * h_real_eye2elbow / h_pixel_eye2elbow
  308. for level in levels["hip_forward_offset"]:
  309. hip_risk_level = level[0]
  310. if hip_offset <= level[1]:
  311. break
  312. hip_forward_direction = None
  313. if hip_r_x > ankle_r_x:
  314. hip_forward_direction = "前移"
  315. elif hip_r_x < ankle_r_x:
  316. hip_forward_direction = "后移"
  317. if hip_forward_direction:
  318. hip_state = "髋关节{}{}cm".format(hip_forward_direction, round(hip_offset,2))
  319. else:
  320. hip_state = "髋关节正常"
  321. print("髋部分析:{}".format(hip_state))
  322. result.append("髋部分析:{}".format(hip_state))
  323. result.append(hip_risk_level)
  324. print(hip_risk_level)
  325. # for knee
  326. knee_angle_r = 180 - angle([hip_r_x, hip_r_y, knee_r_x, knee_r_y], [knee_r_x, knee_r_y, ankle_r_x, ankle_r_y])
  327. if knee_angle_r > 90:
  328. knee_angle_r = 180 - knee_angle_r
  329. knee_angle_r -= 3
  330. knee_forward_risk_level = 0
  331. for level in levels["knee_forward_angle"]:
  332. knee_forward_risk_level = level[0]
  333. if knee_angle_r <= level[1]:
  334. break
  335. if knee_forward_risk_level == 0:
  336. print("膝盖角度分析:膝盖无明显超伸")
  337. result.append("膝盖角度分析:膝盖无明显超伸")
  338. else:
  339. print("膝盖角度分析:下肢膝盖超伸角度为{}度".format(round(knee_angle_r, 2)))
  340. result.append("膝盖角度分析:下肢膝盖超伸角度为{}度".format(round(knee_angle_r, 2)))
  341. print(knee_forward_risk_level)
  342. result.append(knee_forward_risk_level)
  343. return result
  344. def do_analysis(index, height):
  345. source_npy_front = "pose_temp_data/{}-0.npy".format(index)
  346. source_npy_side = "pose_temp_data/{}-1.npy".format(index)
  347. save_path = "pose_processed_txt/{}.txt".format(index)
  348. run_openpose_for_image_front(index)
  349. run_openpose_for_image_side(index)
  350. result_front = analyse_npy_front(source_npy_front, height)
  351. result_side = analyse_npy_side(source_npy_side, height)
  352. result = result_front + result_side
  353. text_save(save_path, result)
  354. if __name__ == '__main__':
  355. heights = [104, 100, 104.5, 124, 107, 120.6, 111, 120, 118, 103.5, 101, 114, 128, 142, 117
  356. , 181, 105, 183, 150, 177
  357. ]
  358. for (i, h) in enumerate(heights):
  359. try:
  360. print("{}/{}".format(i + 1, len(heights)))
  361. do_analysis(i + 1, h)
  362. except Exception:
  363. print("\nWarning")
  364. print("照片{}有关键点未识别出来".format(i + 1))
  365. continue