olrlobt
[Spring boot] 카카오 포즈 / RestTemplate으로 Kakao Pose API 호출하기 본문
카카오 포즈 Kakao Pose API
카카오 포즈(Pose) API는 이미지나 영상을 분석해 사람의 자세를 추출하는 기능을 제공한다. 이미지에서 사람들을 찾고 사람의 코, 눈, 귀, 어깨, 팔꿈치, 손목, 골반, 무릎, 발목의 위치를 키 포인트(Key Points)로 추출한다.
API에 대한 자세한 내용은 공식 홈페이지를 참조하자.
https://developers.kakao.com/docs/latest/ko/pose/common
Spring boot에서 사용해 보기
POST /pose HTTP/1.1
Host: cv-api.kakaobrain.com
Authorization: KakaoAK ${REST_API_KEY}
공식 홈페이지에서는 위와 같이 kakao pose를 호출할 수 있는 기본 정보를 제공하고 있으며, 필수적으로 제공해야 하는 Header와 Parameter, 요청받을 결과 변수를 제공해 주고 있다.
// url로 요청
curl -v -X POST "https://cv-api.kakaobrain.com/pose" \
-H "Content-Type: application/x-www-form-urlencoded" \
-H "Authorization: KakaoAK ${REST_API_KEY}" \
--data-urlencode "image_url=https://example.com/example.jpg"
// 파일로 요청
curl -v -X POST "https://cv-api.kakaobrain.com/pose" \
-H "Content-Type: multipart/form-data" \
-H "Authorization: KakaoAK ${REST_API_KEY}" \
-F "file=@example_pose.jpg"
또한, kakao pose를 호출하기 위한 샘플을 PHP로 제공하고 있다.
Kakao Pose API는 SDK는 지원하지 않고, REST API로만 지원을 해주고 있기 때문에, Spring 프로젝트에서 REST API를 호출하는 방법으로 사용해야 한다.
REST API를 호출하는 방법으로는 JS에서 API를 호출하거나, Spring의 RestTemplate 또는 WebClient를 활용하여 호출하는 방법이 있다. 하지만, kakao API의 카카오의 CORS 정책에 따라 프런트에서 호출하게 되면 CORS 오류를 접하게 된다.
일반적인 REST API CORS 오류의 경우 아래 포스팅한 방법을 통하여 해결할 수 있지만, kakao API의 경우 백엔드에서 호출을 해 주어야 한다.
/// 링크 추가 예정
RestTemplate의 경우 Spring 3.0 버전부터 사용이 가능하며, WebClient를 지원하는 Spring 5.0 버전부터는 권장하지 않는 방법이다. 하지만 나는 이 프로젝트에서, Spring 3.0.3 version을 사용하고 있기 때문에, RestTemplate를 사용하기로 했다.
Spring boot RestTemplate 활용하여 API 호출
RestTemplate란?
RestTemplate은 Spring Framework에서 제공하는 HTTP 클라이언트 라이브러리이다. RESTful 웹 서비스를 호출하고 응답을 처리하는 데 사용된다. RestTemplate은 HTTP GET, POST, PUT, DELETE와 같은 다양한 HTTP 요청 메서드를 지원한다.
APP KEY 발급
먼저 Kakao Pose API를 사용하기 위하여 APP key를 발급받는다.
String REST_API_KEY = "0000000000"; // REST API KEY
String IMAGE_URL = "https://sample/test3.jpg"; // IMAGE URL
발급받는 자세한 내용은 아래의 포스팅을 참조하길 바라며, 네 가지 앱 키 중 REST APP KEY를 사용한다.
IMAGE_URL의 경우, URL을 활용할 경우에만 사용하며, URL을 사용하지 않을 경우 FIle 경로를 파라미터로 넘겨주어야 한다.
APP key 발급받는 방법 : https://olrlobt.tistory.com/38
Header 설정
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.set("Authorization", "KakaoAK " + REST_API_KEY);
Kakao Pose API 요청에는 앞서 설명한 것과 같이 Header에 Authorization ( 앱 키)가 포함되어야 한다.
발급받은 APP KEY를 REST_API_KEY에 적어준다.
Parameter 설정
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("image_url", "${URL || FILE_LOCATION}");
Kakao Pose API 요청에 필요한 Parameter를 설정한다.
이미지 URL 또는 경로가 필요하며, Map으로 Key와 Value를 설정해 준다.
RestTemplate으로 API 요청과 응답
RestTemplate restTemplate = new RestTemplate();
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
String url = "https://cv-api.kakaobrain.com/pose";
ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
System.out.println(response.getBody());
HttpEntity는 HTTP 요청과 응답에서 메시지 바디와 헤더 정보를 포함하는 Spring Framework 클래스이다. 앞서 설정한 Header와 Parameter를 HttpEntity로 하나로 묶어 전송한다.
RestTemplate의 postForEntity() 메서드를 사용하여 url에 POST요청을 하여 결과를 ResponseEntity에 저장한다.
응답은 response에 담기며, 이때 postForEntity()의 인자는 다음과 같다.
- uri: POST 요청을 보낼 URI 정보
- request: POST 요청에 포함될 요청 바디
- responseType: 응답의 데이터 형식
전체코드
공통 Import
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.client.RestTemplate;
HttpHeader의 경우 import org.springframework.http.HttpHeaders; 를 사용하여야 아래 코드의 메서드 사용이 가능하다.
KakaoPose API 이미지 URL로 호출하기
@GetMapping("/kakaoPose")
public String kakaoPose() {
String REST_API_KEY = "0000000000"; // REST API KEY
String IMAGE_URL = "https://sample/test3.jpg"; // IMAGE URL
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.set("Authorization", "KakaoAK " + REST_API_KEY);
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("image_url", IMAGE_URL);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
String url = "https://cv-api.kakaobrain.com/pose";
ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
System.out.println(response.getBody());
return "/pose/kakaoPose";
}
KakaoPose API 이미지 파일 경로로 호출하기
@GetMapping("/kakaoPose")
public String kakaoPose() {
String REST_API_KEY = "00000000"; // REST API KEY
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
headers.set("Authorization", "KakaoAK " + REST_API_KEY);
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("file", new FileSystemResource("src/main/resources/static/sample/test3.jpg"));
HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<>(map, headers);
String url = "https://cv-api.kakaobrain.com/pose";
ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
System.out.println(response.getBody());
return "/pose/kakaoPose";
}
결과
이미지 URL 활용 결과
[{
"area":237851.0619,
"bbox":[0.0,17.71,293.9045,809.28],
"category_id":1,
"keypoints":[145.6747,96.85,0.8517,160.581,85.15,0.8582,132.1236,85.15,0.8626,178.1974,
90.35,0.8454,106.3764,90.35,0.8612,220.206,189.15,0.6754,56.2372,187.85,0.6627,248.6633,
299.65,0.7223,4.7429,295.75,0.5499,203.9446,354.25,0.6148,84.6946,352.95,0.6272,178.1974,
415.35,0.5205,99.6009,410.15,0.5491,168.7116,588.25,0.5944,94.1804,592.15,0.595,164.6463
,752.05,0.6214,106.3764,758.55,0.6667],
"score":0.687
}]
이미지 경로 활용 결과 (사람 2명)
[
{
"area":89408.5349,
"bbox":[377.9,744.6471,160.6688,556.4774],
"category_id":1,
"keypoints":[488.3203,799.3578,0.8625,490.4297,795.189,0.083,481.9922,791.0203,0.8599,
454.5703,793.1047,0.0047,454.5703,793.1047,0.8826,498.8672,847.2984,0.7761,
414.4922,857.7203,0.7718,524.1797,907.7453,0.291,391.2891,928.5891,0.7008,
513.6328,903.5765,0.2019,444.0234,943.1796,0.8312,500.9766,1007.7953,
0.5489,441.9141,1009.8796,0.5315,500.9766,1128.689,0.5807,454.5703,1126.6046,
0.5839,494.6484,1253.7515,0.7409,446.1328,1251.6671,0.6922],
"score":0.5679}
,
{
"area":57858.6248,
"bbox":[527.4547,779.4562,112.575,513.9562],
"category_id":1,
"keypoints":[553.7109,828.539,0.8768,562.1484,822.2859,0.8764,551.6016,822.2859,
0.634,583.2422,828.539,0.7463,560.0391,822.2859,0.0059,602.2266,884.8171,0.6553,
553.7109,880.6484,0.5587,629.6484,964.0234,0.471,536.8359,943.1796,0.1253,583.2422,
966.1078,0.6047,551.6016,966.1078,0.2317,606.4453,1024.4702,0.5532,562.1484,1024.4702,
0.452,610.6641,1130.7734,0.4675,574.8047,1128.689,0.37,612.7734,1249.5828,0.6841,
587.4609,1249.5828,0.6373],
"score":0.5261
}
]
위(URL 활용)의 경우, 1명이 있는 이미지를 활용했고,
아래(경로 활용)의 경우, 2명이 같이 있는 이미지를 활용했기 때문에, 결과가 2개로 나누어 출력되었다.
동영상 테스트의 경우 추후 포스팅으로 다룰 예정이다.
Canvas로 점찍어보기
위의 좌표 결과를 확인하여 점을 찍어보면 다음과 같이 나타낼 수 있다.
네모 사각 테두리의 경우 Bbox 속성을 의미하고
그 안에 key points들이 나타나는 모습이다.
'Spring > Project' 카테고리의 다른 글
[Pose Estimation] Mediapipe Pose 분석 결과 3D grid로 렌더링하기 (0) | 2023.04.03 |
---|---|
[Spring boot] FFmpeg로 영상 배속 설정하기 (0) | 2023.03.31 |
[Pose Estimation] YOLOv5, MediaPipe로 Multi Pose 구현 시도해보기 (0) | 2023.03.23 |
[Pose Estimation] MediaPipe Pose / 미디어 파이프로 사람 포즈 감지하기 (0) | 2023.03.15 |
[Pose Estimation] 다양한 Pose Estimation API 비교와 정리 (3) | 2023.03.14 |