analyse_func.py 15 KB

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