Body Keypoint Detection

Description

This API processes body detection requests in the cloud and returns body keypoint detection information for people in an image.

Version

1.0

Image Requirements

Supported image formats: JPG and PNG.

API URL

    Production environment: https://openapi.meitu.com
    Task submission endpoint: https://openapi.meitu.com/api/v1/sdk/sync/push
    Task name (task): /v1/Body_Keypoint_Detection/487158
    Task type (task_type): formula

Method

POST

Content-Type: application/json

Authentication

Open Platform API Signature

Request Parameters

RequiredParameterTypeDescription
YesparamsstringAlgorithm parameters (JSON string)
Yesinit_imagesobject[]Media file list
YestaskstringFixed value: /v1/Body_Keypoint_Detection/487158
Yestask_typestringFixed value: formula
Nosync_timeoutintSynchronization timeout; default: 30

The init_images media file parameters are described below.

RequiredParameterTypeDescription
YesurlstringImage URL or Base64-encoded data
YesprofileobjectAttribute information

The profile attribute information is described below.

RequiredParameterTypeDescription
Yesmedia_profilesobjectMedia attribute information
YesversionstringFixed value: v1

The media_profiles media attribute information is described below.

RequiredParameterTypeDescription
Yesmedia_data_typestringurl indicates a URL; formats such as jpg indicate Base64-encoded data

The params inference parameter is a JSON string with the following structure.

RequiredFieldTypeDescription
Norsp_media_typestringDefault: url; jpg returns the resulting image in Base64-encoded format, while url returns it as a URL
YesparameterobjectCore algorithm parameter object

Details of the parameter algorithm parameters:

RequiredParameterTypeDescription
NoversionstringAlgorithm version; default: 1.0.0

Request Example

{
  "task": "/v1/Body_Keypoint_Detection/487158",
  "task_type": "formula",
  "init_images": [
    {
      "url": "https://obs.mtlab.meitu.com/public/EtRGxLI8ulQ43pGhuZfym9aYUD2PUbMP/MTcwOTE4MjgwMA==/58fdb25d-8e6f-4026-4a5e-45d9894190a4.png",
      "profile": {
        "media_profiles": {
          "media_data_type": "url"
        },
        "version": "v1"
      }
    }
  ],
  "params": "{\"rsp_media_type\":\"url\",\"parameter\":{\"version\":\"1.0.0\"}}",
  "sync_timeout": 30
}

Response Fields

Note: Generated results are periodically deleted. Download and save them promptly.
FieldTypeDescription
request_idstringRequest identifier
trace_idstringTrace identifier
codeintBusiness status code; 0 indicates that the request was accepted successfully
error_codeintError code; 0 indicates success
messagestringBusiness message
tipsanyAdditional information; may be null
dataobjectTask status and algorithm result

Fields in data are described below.

FieldTypeDescription
statusintStatus code: -1, task not found; 0, created successfully; 1, processing; 2, failed; 9, timed out—use the Query API; 10, succeeded
resultobjectAlgorithm result
progressnumberTask progress
predict_elapsedintEstimated processing time, in milliseconds
create_timeint64Creation timestamp, in milliseconds
task_idstringTask ID
custom_task_idstringClient-defined task ID
trace_idstringTrace identifier
client_infostringClient information
init_imagesobject[]/nullEchoed input media

Fields in result are described below.

FieldTypeDescription
idstringUnique task identifier
urlsstring[]Result resource URL list
imagesstring[]Returned image resources
parametersobjectAlgorithm parameter information, including the string-type version
dataobjectRaw algorithm response data
mtlab_resobjectRaw MTLab result
media_info_listobject[]Media result information list

Fields in result.data and result.mtlab_res are described below.

FieldTypeDescription
ErrorCodeintAlgorithm error code; 0 indicates success
ErrorMsgstringAlgorithm error message
error_codeintSame as ErrorCode
error_msgstringSame as ErrorMsg
media_info_listobject[]Media result information list
msg_idstringMessage ID
parameterobjectAlgorithm parameters, including the string-type version

Fields in media_info_list are described below.

FieldTypeDescription
media_datastringMedia data, such as an image URL or Base64-encoded data
media_extraobjectAdditional algorithm result
media_profilesobject/nullMedia configuration parameters

Fields in media_extra are described below.

FieldTypeDescription
body_posearrayBody detection information containing body keypoints for N people in the image. Each person has 14 points, and each point is represented as [x, y, score]. See Body Keypoint Index Reference for the keypoint order.

Fields for each keypoint in body_pose are described below.

FieldTypeDescription
xfloatHorizontal coordinate of the keypoint, using the top-left corner of the image as (0, 0); the example value range is 0~1
yfloatVertical coordinate of the keypoint, using the top-left corner of the image as (0, 0); the example value range is 0~1
scorefloatKeypoint confidence score in the range [0, 1]; a higher value indicates greater confidence in the predicted point

Each triplet represents one keypoint. [0, 0, 0] indicates that the keypoint was not detected. The array order follows the keypoint order defined by the algorithm.

API-specific error codes and messages:

ErrorCode Status CodeError MessageDescription
20001PROCESS_ERRORProcessing error

Response Examples

Successful Response Example

{
  "request_id": "",
  "trace_id": "",
  "code": 0,
  "error_code": 0,
  "message": "success",
  "tips": null,
  "data": {
    "status": 10,
    "result": {
      "id": "t_mt1a3i5n7bfb3cb4d5-xxxx-416c-aca2-4ea85e2392d0",
      "urls": [""],
      "images": [""],
      "parameters": {
        "version": "1.0.0"
      },
      "data": {
        "ErrorCode": 0,
        "ErrorMsg": "",
        "error_code": 0,
        "error_msg": "",
        "media_info_list": [
          {
            "media_data": "",
            "media_extra": {
              "body_pose": [
                [
                  [0.382604, 0.237499, 0.960717],
                  [0.397724, 0.353015, 0.89843],
                  [0.313316, 0.413948, 0.875583],
                  [0.5135, 0.376142, 0.862831],
                  [0.31644, 0.526003, 0.829664],
                  [0.600144, 0.489705, 0.841293],
                  [0.480908, 0.576402, 0.791474],
                  [0.602069, 0.600498, 0.751575],
                  [0.415567, 0.600929, 0.638177],
                  [0.550402, 0.588666, 0.609929],
                  [0.31724, 0.587703, 0.800953],
                  [0.617525, 0.65204, 0.0674782],
                  [0.433666, 0.826302, 0.819607],
                  [0, 0, 0]
                ]
              ]
            },
            "media_profiles": null
          }
        ],
        "msg_id": "",
        "parameter": {
          "version": "1.0.0"
        }
      },
      "mtlab_res": {
        "ErrorCode": 0,
        "ErrorMsg": "",
        "error_code": 0,
        "error_msg": "",
        "media_info_list": [
          {
            "media_data": "",
            "media_extra": {
              "body_pose": [
                [
                  [0.382604, 0.237499, 0.960717],
                  [0.397724, 0.353015, 0.89843],
                  [0.313316, 0.413948, 0.875583],
                  [0.5135, 0.376142, 0.862831],
                  [0.31644, 0.526003, 0.829664],
                  [0.600144, 0.489705, 0.841293],
                  [0.480908, 0.576402, 0.791474],
                  [0.602069, 0.600498, 0.751575],
                  [0.415567, 0.600929, 0.638177],
                  [0.550402, 0.588666, 0.609929],
                  [0.31724, 0.587703, 0.800953],
                  [0.617525, 0.65204, 0.0674782],
                  [0.433666, 0.826302, 0.819607],
                  [0, 0, 0]
                ]
              ]
            },
            "media_profiles": null
          }
        ],
        "msg_id": "",
        "parameter": {
          "version": "1.0.0"
        }
      },
      "media_info_list": [
        {
          "media_data": "",
          "media_extra": {
            "body_pose": [
              [
                [0.382604, 0.237499, 0.960717],
                [0.397724, 0.353015, 0.89843],
                [0.313316, 0.413948, 0.875583],
                [0.5135, 0.376142, 0.862831],
                [0.31644, 0.526003, 0.829664],
                [0.600144, 0.489705, 0.841293],
                [0.480908, 0.576402, 0.791474],
                [0.602069, 0.600498, 0.751575],
                [0.415567, 0.600929, 0.638177],
                [0.550402, 0.588666, 0.609929],
                [0.31724, 0.587703, 0.800953],
                [0.617525, 0.65204, 0.0674782],
                [0.433666, 0.826302, 0.819607],
                [0, 0, 0]
              ]
            ]
          },
          "media_profiles": null
        }
      ]
    },
    "progress": 0,
    "predict_elapsed": 10000,
    "create_time": 1770357763826,
    "task_id": "t_mt1a3i5n7bfb3cb4d5-xxxx-416c-aca2-4ea85e2392d0",
    "custom_task_id": "",
    "trace_id": "",
    "client_info": "",
    "init_images": null
  }
}

Query-Required Response Example

Use the Query API to retrieve the result.

Response Status: 200

Content-Type: application/json; charset=utf-8

{
  "request_id": "",
  "trace_id": "",
  "code": 0,
  "error_code": 0,
  "message": "success",
  "tips": null,
  "data": {
    "status": 9,
    "result": {
      "id": "t_mt1a3i5n7b7a7ba41b-xxxx-4cdb-a0be-1fd951bd1ffc"
    },
    "progress": 0,
    "predict_elapsed": 10000,
    "create_time": 1770283596272,
    "task_id": "t_mt1a3i5n7b7a7ba41b-xxxx-4cdb-a0be-1fd951bd1ffc",
    "custom_task_id": "",
    "trace_id": "1e106f37-xxxx-4f2c-8bb2-f480ebae4dda",
    "client_info": "",
    "init_images": null
  }
}

Failed Response Example

Response Status: 400

Content-Type: application/json; charset=utf-8

{
  "request_id": "",
  "trace_id": "",
  "code": 20001,
  "error_code": 20001,
  "message": "PROCESS_ERROR",
  "tips": null,
  "data": {
    "status": 2,
    "result": {
      "ErrorCode": 20001,
      "ErrorMsg": "PROCESS_ERROR"
    },
    "progress": 0,
    "predict_elapsed": 0,
    "create_time": 0,
    "task_id": "",
    "custom_task_id": "",
    "trace_id": "",
    "client_info": "",
    "init_images": null
  }
}

General Error Codes and Messages

For details, see API Error Codes.

SDK Examples

Python

import json

import requests
from sign_sdk import sign

def api_call_example():
    key = "your_api_key"
    secret = "your_api_secret"
    url = "https://openapi.meitu.com/api/v1/sdk/sync/push"
    method = "POST"

    headers = {
        "Content-Type": "application/json",
        sign.HeaderHost: "openapi.meitu.com",
    }
    inner_params = {
        "rsp_media_type": "url",
        "parameter": {"version": "1.0.0"},
    }
    payload = {
        "task": "/v1/Body_Keypoint_Detection/487158",
        "task_type": "formula",
        "init_images": [
            {
                "url": "https://obs.mtlab.meitu.com/public/EtRGxLI8ulQ43pGhuZfym9aYUD2PUbMP/MTcwOTE4MjgwMA==/58fdb25d-8e6f-4026-4a5e-45d9894190a4.png",
                "profile": {
                    "media_profiles": {"media_data_type": "url"},
                    "version": "v1",
                },
            }
        ],
        "params": json.dumps(inner_params, ensure_ascii=False),
        "sync_timeout": 30,
    }
    body = json.dumps(payload, ensure_ascii=False)

    signer = sign.Signer(key, secret)
    signed_request = signer.sign(url, method, headers, body)
    response = requests.Session().send(signed_request)
    print(f"Status: {response.status_code}")
    print(f"Response: {response.text}")

if __name__ == "__main__":
    api_call_example()

Go

package main

import (
	"fmt"
	"io"
	"net/http"

	"github.com/mtlab/api/signer"
)

func main() {
	key := "your_api_key"
	secret := "your_api_secret"
	signObj := signer.NewSigner(key, secret)

	url := "https://openapi.meitu.com/api/v1/sdk/sync/push"
	method := http.MethodPost
	headers := make(http.Header)
	headers.Set(signer.HeaderHost, "openapi.meitu.com")
	headers.Set("Content-Type", "application/json")

	body := `{
  "task": "/v1/Body_Keypoint_Detection/487158",
  "task_type": "formula",
  "init_images": [{
    "url": "https://obs.mtlab.meitu.com/public/EtRGxLI8ulQ43pGhuZfym9aYUD2PUbMP/MTcwOTE4MjgwMA==/58fdb25d-8e6f-4026-4a5e-45d9894190a4.png",
    "profile": {
      "media_profiles": {"media_data_type": "url"},
      "version": "v1"
    }
  }],
  "params": "{\"rsp_media_type\":\"url\",\"parameter\":{\"version\":\"1.0.0\"}}",
  "sync_timeout": 30
}`

	req, err := signObj.Sign(url, method, headers, body)
	if err != nil {
		fmt.Println("Failed to sign request:", err)
		return
	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		fmt.Println("Failed to send request:", err)
		return
	}
	defer resp.Body.Close()

	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("Read response failed:", err)
		return
	}
	fmt.Println("Response:", resp.StatusCode, string(responseBody))
}

PHP

<?php
require 'signer.php';

$key = 'your_api_key';
$secret = 'your_api_secret';
$signer = new Signer($key, $secret);

$url = 'https://openapi.meitu.com/api/v1/sdk/sync/push';
$method = 'POST';
$headers = ['Content-Type' => 'application/json'];

$innerParams = json_encode([
    'rsp_media_type' => 'url',
    'parameter' => ['version' => '1.0.0'],
]);

$body = json_encode([
    'task' => '/v1/Body_Keypoint_Detection/487158',
    'task_type' => 'formula',
    'init_images' => [
        [
            'url' => 'https://obs.mtlab.meitu.com/public/EtRGxLI8ulQ43pGhuZfym9aYUD2PUbMP/MTcwOTE4MjgwMA==/58fdb25d-8e6f-4026-4a5e-45d9894190a4.png',
            'profile' => [
                'media_profiles' => ['media_data_type' => 'url'],
                'version' => 'v1',
            ],
        ],
    ],
    'params' => $innerParams,
    'sync_timeout' => 30,
]);

$curl = $signer->sign($url, $method, $headers, $body);
$response = curl_exec($curl);
$status = curl_getinfo($curl, CURLINFO_HTTP_CODE);

if ($status === 0) {
    echo 'Error: ' . curl_error($curl);
} else {
    echo "Status: {$status}\n";
    echo "Response: {$response}\n";
}
curl_close($curl);
?>

Java

package com.meitu.openai.common;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) throws Exception {
        Signer signer = new Signer("your_api_key", "your_api_secret");
        String url = "https://openapi.meitu.com/api/v1/sdk/sync/push";
        String method = "POST";

        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put(Signer.HeaderHost, "openapi.meitu.com");

        String body = "{\n" +
                "  \"task\": \"/v1/Body_Keypoint_Detection/487158\",\n" +
                "  \"task_type\": \"formula\",\n" +
                "  \"init_images\": [{\n" +
                "    \"url\": \"https://obs.mtlab.meitu.com/public/EtRGxLI8ulQ43pGhuZfym9aYUD2PUbMP/MTcwOTE4MjgwMA==/58fdb25d-8e6f-4026-4a5e-45d9894190a4.png\",\n" +
                "    \"profile\": {\n" +
                "      \"media_profiles\": {\"media_data_type\": \"url\"},\n" +
                "      \"version\": \"v1\"\n" +
                "    }\n" +
                "  }],\n" +
                "  \"params\": \"{\\\"rsp_media_type\\\":\\\"url\\\",\\\"parameter\\\":{\\\"version\\\":\\\"1.0.0\\\"}}\",\n" +
                "  \"sync_timeout\": 30\n" +
                "}";

        Map<String, String> signedHeaders = signer.sign(url, method, headers, body);
        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
        connection.setRequestMethod(method);
        for (Map.Entry<String, String> entry : signedHeaders.entrySet()) {
            connection.setRequestProperty(entry.getKey(), entry.getValue());
        }
        connection.setDoOutput(true);
        connection.getOutputStream().write(body.getBytes(StandardCharsets.UTF_8));

        int status = connection.getResponseCode();
        InputStream stream = status >= 400
                ? connection.getErrorStream()
                : connection.getInputStream();
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
            StringBuilder response = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            System.out.println("Response: " + status + " " + response);
        }
    }
}