Showing
2 changed files
with
116 additions
and
1 deletions
straight-up/src/AnalysisPose.js
0 → 100644
| 1 | +//두 좌표 사이의 거리를 반환하는 함수 | ||
| 2 | +function distance(x1, y1, x2, y2) { | ||
| 3 | + var x = Math.abs(x1 - x2); | ||
| 4 | + var y = Math.abs(y1 - y2); | ||
| 5 | + var result = Math.hypot(x, y); | ||
| 6 | + return result; | ||
| 7 | +} | ||
| 8 | + | ||
| 9 | +//두 길이의 차이를 %비로 반환하는 함수 | ||
| 10 | +function difference(d1, d2) { | ||
| 11 | + if (d1 > d2) { | ||
| 12 | + return (1 - (d2 / d1)) * 100; | ||
| 13 | + } else if (d1 < d2) { | ||
| 14 | + return (1 - (d1 / d2)) * 100; | ||
| 15 | + } else if (d1 === d2) { | ||
| 16 | + return 0; | ||
| 17 | + } | ||
| 18 | +} | ||
| 19 | + | ||
| 20 | +//객체와 방향정보를 받아 자세정보를 반환하는 함수 | ||
| 21 | +const checkStraight = (resData, position) => { //resData: API로 받은 JSON 객체, position: 사진의 방향정보 | ||
| 22 | + var trust_value = []; //17개의 신체부위 좌표에 대한 신뢰도를 저장할 배열 | ||
| 23 | + var x_position = []; //17개의 신체부위의 X좌표값을 저장할 배열 | ||
| 24 | + var y_position = []; //17개의 신체부위의 Y좌표값을 저장할 배열 | ||
| 25 | + const neck_maximum_angle = (180 * 30) / Math.PI; //어깨-귀 각도가 30도 이상일 경우 > 거북목 | ||
| 26 | + const back_minimum_angle = (180 * 70) / Math.PI; //엉덩이-어깨 각도가 70도 이하일 경우 > 굽은등 | ||
| 27 | + let ear = 3; | ||
| 28 | + let shoulder = 5; | ||
| 29 | + let hip = 11; | ||
| 30 | + for (let i = 0; i < 49; i += 3) { | ||
| 31 | + x_position.push(resData[i]); | ||
| 32 | + y_position.push(resData[i + 1]); | ||
| 33 | + trust_value.push(resData[i + 2]); | ||
| 34 | + } | ||
| 35 | + if (position === 'front') { //정면 사진일 경우 | ||
| 36 | + //사용할 데이터의 신뢰도가 0.4 미만이면 실행하지 않음 | ||
| 37 | + if (trust_value[ear] < 0.4) { | ||
| 38 | + return 'error_low_trust_value (keypoint:left_ear:4)' | ||
| 39 | + } | ||
| 40 | + if (trust_value[ear+1] < 0.4) { | ||
| 41 | + return 'error_low_trust_value (keypoint:right_ear:5)' | ||
| 42 | + } | ||
| 43 | + if (trust_value[shoulder] < 0.4) { | ||
| 44 | + return 'error_low_trust_value (keypoint:left_shoulder:6)' | ||
| 45 | + } | ||
| 46 | + if (trust_value[shoulder+1] < 0.4) { | ||
| 47 | + return 'error_low_trust_value (keypoint:right_shoulder_7)' | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + //왼쪽귀(4)-왼쪽어깨(6) 거리와 오른쪽귀(5)-오른쪽어깨(7) 거리가 30% 이상 차이날 경우 > 좌우편향 | ||
| 51 | + var d_left = distance(x_position[ear], y_position[ear], x_position[shoulder], y_position[shoulder]); | ||
| 52 | + var d_right = distance(x_position[ear+1], y_position[ear+1], x_position[shoulder+1], y_position[shoulder+1]); | ||
| 53 | + var gap = difference(d_left, d_right); | ||
| 54 | + | ||
| 55 | + if (gap >= 30) { //기운 각도가 30도를 넘을 경우 | ||
| 56 | + if (d_left > d_right) { //오른쪽으로 기울인 경우 | ||
| 57 | + return 'leaning right by ' + gap + 'percent.'; | ||
| 58 | + } else if (d_left < d_right) { //왼쪽으로 기울인 경우 | ||
| 59 | + return 'leaning left by ' + gap + 'percent.'; | ||
| 60 | + } | ||
| 61 | + } else { //기운 각도가 30도 미만인 경우 | ||
| 62 | + return 'okay'; | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + | ||
| 66 | + } | ||
| 67 | + else { | ||
| 68 | + if (position === 'right') { | ||
| 69 | + ear++; | ||
| 70 | + shoulder++; | ||
| 71 | + hip++; | ||
| 72 | + } | ||
| 73 | + if (trust_value[hip] < 0.4) { //사용할 데이터의 신뢰도가 0.4 미만이면 실행하지 않음 | ||
| 74 | + return `error_low_trust_value (keypoint:${position}hip)`; | ||
| 75 | + } | ||
| 76 | + if (trust_value[shoulder] < 0.4) { | ||
| 77 | + return `error_low_trust_value (keypoint:${position}shoulder)`; | ||
| 78 | + } | ||
| 79 | + if (trust_value[ear] < 0.4) { | ||
| 80 | + return `error_low_trust_value (keypoint:${position}ear)`; | ||
| 81 | + } | ||
| 82 | + //엉덩이(12)-어깨(6) 각도가 70도 이하일 경우 > 굽은등 | ||
| 83 | + | ||
| 84 | + var back_d1 = Math.abs(x_position[hip] - x_position[shoulder]); | ||
| 85 | + var back_d2 = Math.abs(y_position[hip] - y_position[shoulder]); | ||
| 86 | + var back_angle = Math.atan(back_d2 / back_d1); | ||
| 87 | + var back_angle_rad = (180 * back_angle) / Math.PI; //라디안 > 육십분법 변환 | ||
| 88 | + if (back_angle_rad <= back_minimum_angle) { | ||
| 89 | + return 'bent_back'; | ||
| 90 | + } | ||
| 91 | + //어깨(6)-귀(4) 각도가 30도 이상일 경우 > 거북목 | ||
| 92 | + var neck_d1 = Math.abs(y_position[ear] - y_position[shoulder]); | ||
| 93 | + var neck_d2 = Math.abs(x_position[ear] - x_position[shoulder]); | ||
| 94 | + var neck_angle = Math.atan(neck_d2 / neck_d1); | ||
| 95 | + var neck_angle_rad = (180 * neck_angle) / Math.PI; //라디안 > 육십분법 변환 | ||
| 96 | + if (neck_angle_rad >= neck_maximum_angle) { | ||
| 97 | + return 'bent_neck'; | ||
| 98 | + } | ||
| 99 | + //굽은등, 거북목 모두 없을 경우 | ||
| 100 | + return 'okay'; | ||
| 101 | + } | ||
| 102 | +} | ||
| 103 | + | ||
| 104 | +export default checkStraight; | ||
| 105 | +/* | ||
| 106 | +console.log(check_straight(response,'front')); | ||
| 107 | +console.log(check_straight(response,'left')); | ||
| 108 | +console.log(check_straight(response,'right')); | ||
| 109 | +*/ | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| 1 | import React, { useState } from 'react' | 1 | import React, { useState } from 'react' |
| 2 | import Header from './components/Header'; | 2 | import Header from './components/Header'; |
| 3 | +import checkStraight from './AnalysisPose'; | ||
| 3 | import './style/Main.css'; | 4 | import './style/Main.css'; |
| 4 | require('dotenv').config(); | 5 | require('dotenv').config(); |
| 5 | 6 | ||
| ... | @@ -37,7 +38,12 @@ export default function Main() { | ... | @@ -37,7 +38,12 @@ export default function Main() { |
| 37 | }, | 38 | }, |
| 38 | data: imageFormData | 39 | data: imageFormData |
| 39 | }).then(function (response) { | 40 | }).then(function (response) { |
| 40 | - console.log(JSON.stringify(response.data)); | 41 | + const resdata = response.data[0].keypoints; |
| 42 | + console.log(resdata[0]); | ||
| 43 | + const result = checkStraight(resdata, 'front'); | ||
| 44 | + console.log(result); | ||
| 45 | + | ||
| 46 | + // console.log(resdata[0] === ) | ||
| 41 | }).catch(function (error) { | 47 | }).catch(function (error) { |
| 42 | if (error.response) { | 48 | if (error.response) { |
| 43 | // 요청이 이루어졌으며 서버가 2xx의 범위를 벗어나는 상태 코드로 응답했습니다. | 49 | // 요청이 이루어졌으며 서버가 2xx의 범위를 벗어나는 상태 코드로 응답했습니다. | ... | ... |
-
Please register or login to post a comment