Functions.js 6.04 KB
var response = JSON.parse([
    `{
        "area": 101090.2833,
        "bbox": [719.4526, 244.1255, 182.7314, 553.2178],
        "category_id": 1,
        "keypoints": [
            805.4897, 256.4165, 0.8422, 819.5366, 245.0034, 0.8773, 795.8325, 244.1255, 0.8664, 845.8745, 254.6606, 0.8105, 788.8091, 251.1489, 0.5631, 885.3813, 320.5054, 0.7525, 749.3022, 331.9185, 0.7706, 898.5503, 377.5708, 0.7825, 719.4526, 414.4438, 0.7897, 901.1841, 435.5142, 0.7782, 749.3022, 443.4155, 0.8086, 852.02, 504.8706, 0.6854, 785.2974, 511.894, 0.6738, 833.5835, 644.4614, 0.7899, 800.2222, 659.3862, 0.7655, 833.5835, 796.3433, 0.7055, 824.8042, 743.6675, 0.5165
        ],
        "score": 0.7185
    }`
]);
console.log(response);

//두 좌표 사이의 거리를 반환하는 함수
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;
    }
}

//객체와 방향정보를 받아 자세정보를 반환하는 함수
function check_straight(jsonObj,position){ //jsonObj: API로 받은 JSON 객체, position: 사진의 방향정보
    var trust_value = []; //17개의 신체부위 좌표에 대한 신뢰도를 저장할 배열
    for(i=2; i<51; i+=3){
        trust_value.push(jsonObj.keypoints[i]);
    }
    var x_position = []; //17개의 신체부위의 X좌표값을 저장할 배열
    for(i=0; i<49; i+=3){
        x_position.push(jsonObj.keypoints[i]);
    }
    var y_position = []; //17개의 신체부위의 Y좌표값을 저장할 배열
    for(i=1; i<50; i+=3){
        y_position.push(jsonObj.keypoints[i]);
    }

    if(position == 'front'){ //정면 사진일 경우
        //사용할 데이터의 신뢰도가 0.4 미만이면 실행하지 않음
        if(trust_value[3] < 0.4){
            return 'error_low_trust_value (keypoint:4)'
        }
        if(trust_value[4] < 0.4){
            return 'error_low_trust_value (keypoint:5)'
        }
        if(trust_value[5] < 0.4){
            return 'error_low_trust_value (keypoint:6)'
        }
        if(trust_value[6] < 0.4){
            return 'error_low_trust_value (keypoint:7)'
        }

        //왼쪽귀(4)-왼쪽어깨(6) 거리와 오른쪽귀(5)-오른쪽어깨(7) 거리가 30% 이상 차이날 경우 > 좌우편향
        var d_left = distance(x_position[3], y_position[3], x_position[5], y_position[5]);
        var d_right = distance(x_position[4], y_position[4], x_position[6], y_position[6]);
        var gap = difference(d_left, d_right);

        if(gap >= 30){ //기운 각도가 30도를 넘을 경우
            if(d_left > d_right){ //오른쪽으로 기울인 경우
                return 'leaning right by ' + gap + 'percent.';
            }else if(d_left < d_right){ //왼쪽으로 기울인 경우
                return 'leaning left by ' + gap + 'percent.';
            }
        }else{ //기운 각도가 30도 미만인 경우
            return 'okay';
        }
        

    }else if(position == 'left'){ //좌측 측면 사진일 경우
        //사용할 데이터의 신뢰도가 0.4 미만이면 실행하지 않음
        if(trust_value[11] < 0.4){
            return 'error_low_trust_value (keypoint:12)'
        }
        if(trust_value[5] < 0.4){
            return 'error_low_trust_value  (keypoint:6)'
        }
        if(trust_value[3] < 0.4){
            return 'error_low_trust_value  (keypoint:4)'
        }

        //엉덩이(12)-어깨(6) 각도가 70도 이하일 경우 > 굽은등
        var minimum_angle1 = (180 * 70) / Math.PI;
        var d1 = Math.abs(x_position[11]-x_position[5]);
        var d2 = Math.abs(y_position[11]-y_position[5]);
        var angle1 = Math.atan(d2/d1);
        angle1 = (180 * angle1) / Math.PI; //라디안 > 육십분법 변환
        if(angle1 <= minimum_angle1){
            return 'bent_back';
        }

        //어깨(6)-귀(4) 각도가 30도 이상일 경우 > 거북목
        var maximum_angle2 = (180 * 30) / Math.PI;
        var d1 = Math.abs(y_position[3] - y_position[5]);
        var d2 = Math.abs(x_position[3] - x_position[5]);
        var angle2 = Math.atan(d2/d1);
        angle2 = (180 * angle2) / Math.PI; //라디안 > 육십분법 변환
        if(angle2 >= maximum_angle2){
            return 'bent_neck';
        }

        //굽은등, 거북목 모두 없을 경우
        return 'okay';

    }else if(position == 'right'){ //우측 측면 사진일 경우
        //사용할 데이터의 신뢰도가 0.4 미만이면 실행하지 않음
        if(trust_value[12] < 0.4){
            return 'error_low_trust_value (keypoint:13)'
        }
        if(trust_value[6] < 0.4){
            return 'error_low_trust_value (keypoint:7)'
        }
        if(trust_value[4] < 0.4){
            return 'error_low_trust_value (keypoint:5)'
        }

        //엉덩이(13)-어깨(7) 각도가 70도 이하일 경우 > 굽은등
        var minimum_angle1 = (180 * 70) / Math.PI;
        var d1 = Math.abs(x_position[12]-x_position[6]);
        var d2 = Math.abs(y_position[12]-y_position[6]);
        var angle1 = Math.atan(d2/d1);
        angle1 = (180 * angle1) / Math.PI; //라디안 > 육십분법 변환
        if(angle1 <= minimum_angle1){
            return 'bent_back';
        }

        //어깨(7)-귀(5) 각도가 30도 이상일 경우 > 거북목
        var maximum_angle2 = (180 * 30) / Math.PI;
        var d1 = Math.abs(y_position[4] - y_position[6]);
        var d2 = Math.abs(x_position[4] - x_position[6]);
        var angle2 = Math.atan(d2/d1);
        angle2 = (180 * angle2) / Math.PI; //라디안 > 육십분법 변환
        if(angle2 >= maximum_angle2){
            return 'bent_neck';
        }

        //굽은등, 거북목 모두 없을 경우
        return 'okay';
    }

}

console.log(check_straight(response,'front'));
console.log(check_straight(response,'left'));
console.log(check_straight(response,'right'));