AnalysisPose.js
4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
//두 좌표 사이의 거리를 반환하는 함수
function distance(x1, y1, x2, y2) {
var x = Math.abs(x1 - x2);
var y = Math.abs(y1 - y2);
var result = Math.hypot(x, y);
return result;
}
//두 길이의 차이를 %비로 반환하는 함수
function difference(d1, d2) {
if (d1 > d2) {
return (1 - (d2 / d1)) * 100;
} else if (d1 < d2) {
return (1 - (d1 / d2)) * 100;
} else if (d1 === d2) {
return 0;
}
}
//객체와 방향정보를 받아 자세정보를 반환하는 함수
const checkStraight = (resData, position) => { //resData: API로 받은 JSON 객체, position: 사진의 방향정보
var trust_value = []; //17개의 신체부위 좌표에 대한 신뢰도를 저장할 배열
var x_position = []; //17개의 신체부위의 X좌표값을 저장할 배열
var y_position = []; //17개의 신체부위의 Y좌표값을 저장할 배열
const neck_maximum_angle = (180 * 30) / Math.PI; //어깨-귀 각도가 30도 이상일 경우 > 거북목
const back_minimum_angle = (180 * 70) / Math.PI; //엉덩이-어깨 각도가 70도 이하일 경우 > 굽은등
let ear = 3;
let shoulder = 5;
let hip = 11;
for (let i = 0; i < 49; i += 3) {
x_position.push(resData[i]);
y_position.push(resData[i + 1]);
trust_value.push(resData[i + 2]);
}
if (position === 'front') { //정면 사진일 경우
//사용할 데이터의 신뢰도가 0.4 미만이면 실행하지 않음
if (trust_value[ear] < 0.4) {
return 'error_low_trust_value (keypoint:left_ear:4)'
}
if (trust_value[ear + 1] < 0.4) {
return 'error_low_trust_value (keypoint:right_ear:5)'
}
if (trust_value[shoulder] < 0.4) {
return 'error_low_trust_value (keypoint:left_shoulder:6)'
}
if (trust_value[shoulder + 1] < 0.4) {
return 'error_low_trust_value (keypoint:right_shoulder_7)'
}
//왼쪽귀(4)-왼쪽어깨(6) 거리와 오른쪽귀(5)-오른쪽어깨(7) 거리가 30% 이상 차이날 경우 > 좌우편향
var d_left = distance(x_position[ear], y_position[ear], x_position[shoulder], y_position[shoulder]);
var d_right = distance(x_position[ear + 1], y_position[ear + 1], x_position[shoulder + 1], y_position[shoulder + 1]);
var gap = difference(d_left, d_right);
if (gap >= 15) { //기운 각도가 15도를 넘을 경우
if (d_left > d_right) { //오른쪽으로 기울인 경우
return 'leaning right by ' + gap + 'percent.';
} else if (d_left < d_right) { //왼쪽으로 기울인 경우
return 'leaning left by ' + gap + 'percent.';
}
} else { //기운 각도가 15도 미만인 경우
return 'okay';
}
}
else {
if (position === 'right') {
ear++;
shoulder++;
hip++;
}
if (trust_value[hip] < 0.4) { //사용할 데이터의 신뢰도가 0.4 미만이면 실행하지 않음
return `error_low_trust_value (keypoint:${position}hip)`;
}
if (trust_value[shoulder] < 0.4) {
return `error_low_trust_value (keypoint:${position}shoulder)`;
}
if (trust_value[ear] < 0.4) {
return `error_low_trust_value (keypoint:${position}ear)`;
}
//엉덩이(12)-어깨(6) 각도가 70도 이하일 경우 > 굽은등
var back_d1 = Math.abs(x_position[hip] - x_position[shoulder]);
var back_d2 = Math.abs(y_position[hip] - y_position[shoulder]);
var back_angle = Math.atan(back_d2 / back_d1);
var back_angle_rad = (180 * back_angle) / Math.PI; //라디안 > 육십분법 변환
if (back_angle_rad <= back_minimum_angle) {
return 'bent_back';
}
//어깨(6)-귀(4) 각도가 30도 이상일 경우 > 거북목
var neck_d1 = Math.abs(y_position[ear] - y_position[shoulder]);
var neck_d2 = Math.abs(x_position[ear] - x_position[shoulder]);
var neck_angle = Math.atan(neck_d2 / neck_d1);
var neck_angle_rad = (180 * neck_angle) / Math.PI; //라디안 > 육십분법 변환
if (neck_angle_rad >= neck_maximum_angle) {
return 'bent_neck';
}
//굽은등, 거북목 모두 없을 경우
return 'okay';
}
}
export default checkStraight;