Intelligent Removal (Including Watermark Removal)
Description
This API processes intelligent removal requests in the cloud, including removing text from images, removing content through interactive selection boxes, and removing content with irregular shapes (brush strokes).
Version
1.0
Image Requirements
- Image formats: JPG and PNG.
- Image dimensions: minimum 48×48 pixels and maximum 4096×4096 pixels.
- Image file size: 2 MB.
- Face bounding boxes detectable by the system are square. The minimum side length is 1/48 of the shorter image dimension and no less than 48 pixels. For example, for a 4096×3200-pixel image, the minimum detectable face size is 66×66 pixels.
API URL
Production environment: https://openapi.meitu.com
Task submission endpoint: https://openapi.meitu.com/api/v1/sdk/sync/push
Task name (task): /v1/ai_eraser_watermark/485833
Task type (task_type): formulaMethod
POST
Content-Type: application/json
Authentication
Request Parameters
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | params | string | Algorithm parameters (JSON string) |
| Yes | init_images | object[] | Media file list. Pass one original image when using interactive selection boxes or text removal. Pass two images when using irregular shapes (brush strokes): the first is the original image and the second is the mask image |
| Yes | task | string | Fixed value: /v1/ai_eraser_watermark/485833 |
| Yes | task_type | string | Fixed value: formula |
| No | sync_timeout | int | Default: 30. Synchronous timeout duration |
The structure of each media file in init_images is as follows:
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | url | string | Media URL or base64-encoded content |
| Yes | profile | object | Attribute information |
The profile attribute information is described below:
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | media_profiles | object | Media attribute information |
| Yes | version | string | Fixed value: v1 |
The media_profiles media attribute information is described below:
| Required | Parameter | Type | Description |
|---|---|---|---|
| Yes | media_data_type | string | url indicates a URL; types such as jpg indicate base64-encoded content |
The params inference parameter is a JSON string with the following structure:
| Required | Field | Type | Description |
|---|---|---|---|
| No | rsp_media_type | string | Default: url, which returns the result image as a URL; jpg returns the result image as base64-encoded content |
| Yes | parameter | object | Core algorithm parameter object |
Details of the algorithm parameters in parameter:
| Required | Parameter | Type | Description |
|---|---|---|---|
| No | userboxes | string | User interaction boxes for box-selection mode, specified using relative coordinates. Four points define each interaction box clockwise starting from the top-left corner. This parameter is ignored when brush-stroke mode is used |
| No | is_text | bool | Specifies the algorithm processing mode. true invokes the document removal model, while false invokes the image removal model |
Request Examples
Remove text from an image:
{
"task": "/v1/ai_eraser_watermark/485833",
"task_type": "formula",
"init_images": [
{
"url": "https://obs.mtlab.meitu.com/public/EtRGxLI8ulQ43pGhuZfym9aYUD2PUbMP/MTcwNjE0ODAwMA==/4d5c9604-3f3f-4247-7459-61dbc86c3300.jpeg",
"profile": {
"media_profiles": {
"media_data_type": "url"
},
"version": "v1"
}
}
],
"params": "{\"rsp_media_type\":\"url\",\"parameter\":{\"is_text\":true}}",
"sync_timeout": 30
}Use interactive selection boxes:
{
"task": "/v1/ai_eraser_watermark/485833",
"task_type": "formula",
"init_images": [
{
"url": "https://example.com/input.jpg",
"profile": {
"media_profiles": {
"media_data_type": "url"
},
"version": "v1"
}
}
],
"params": "{\"rsp_media_type\":\"url\",\"parameter\":{\"userboxes\":\"[[[0.1171, 0.3129],[0.8658, 0.3426],[0.8943, 0.6700],[0.0537, 0.6550]]]\"}}",
"sync_timeout": 30
}Use an irregular shape (brush strokes):
{
"task": "/v1/ai_eraser_watermark/485833",
"task_type": "formula",
"init_images": [
{
"url": "https://example.com/input.jpg",
"profile": {
"media_profiles": {
"media_data_type": "url"
},
"version": "v1"
}
},
{
"url": "https://example.com/mask.jpg",
"profile": {
"media_profiles": {
"media_data_type": "url"
},
"version": "v1"
}
}
],
"params": "{\"rsp_media_type\":\"url\",\"parameter\":{}}",
"sync_timeout": 30
}Response Fields
Note: Generated results are periodically deleted. Download and save them promptly.| Field | Type | Description |
|---|---|---|
| request_id | string | Request identifier |
| trace_id | string | Trace identifier |
| code | int | Business status code. 0 indicates that the request was accepted successfully |
| error_code | int | Error code. 0 indicates success |
| message | string | Business message |
| tips | any | Additional information; may be null |
| data | object | Task status and algorithm result |
Fields in data:
| Field | Type | Description |
|---|---|---|
| status | int | Status code: -1, task not found; 0, created successfully; 1, processing; 2, failed; 9, timed out—use the Query API; 10, succeeded |
| result | object | Algorithm result |
| progress | number | Task progress |
| predict_elapsed | int | Estimated processing time, in milliseconds |
| create_time | int64 | Creation timestamp, in milliseconds |
| task_id | string | Task ID |
| custom_task_id | string | Custom task ID supplied by the client |
| trace_id | string | Trace identifier |
| client_info | string | Client information |
| init_images | object[]/null | Echo of the input media |
Fields in data.result:
| Field | Type | Description |
|---|---|---|
| id | string | Task ID |
| urls | array | List of result file URLs |
| parameters | object | Request parameters |
| data | object | Processing data |
| msg | string | Processing result message |
| msg_id | string | Message ID |
| images | array | List of result image URLs |
| mtlab_res | object | Detailed information returned by Meitu Lab |
| media_info_list | array | Media information list |
Fields in data.result.parameters:
| Field | Type | Description |
|---|---|---|
| has_watermark | bool | Whether the image contains a watermark; true indicates that a watermark is present |
| is_text | bool | Whether the image contains text; false indicates that it does not contain text |
| rsp_media_type | string | Returned media type; png indicates PNG format |
| version | string | Current API version |
Fields in data.result.data:
| Field | Type | Description |
|---|---|---|
| duration | object | Processing duration information |
| error_code | int | Algorithm error code; 0 indicates success |
| error_msg | string | Algorithm error message |
| extra | object | Additional information |
| media_info_list | array | Media information list |
| msg_id | string | Message ID |
| parameter | object | Parameters returned by the algorithm; the fields are the same as those in data.result.parameters |
Fields in data.result.data.duration:
| Field | Type | Description |
|---|---|---|
| alg_process_time | number | Algorithm processing time, in milliseconds |
| created_timestamp | number | Creation timestamp, in seconds |
| pull_timestamp | number | Retrieval timestamp, in seconds |
| repost_time | number | Republish time, in milliseconds |
| upload_time | number | Upload time, in milliseconds |
| waiting_time | number | Waiting time, in milliseconds |
Fields in each element of data.result.media_info_list and data.result.data.media_info_list:
| Field | Type | Description |
|---|---|---|
| media_data | string | Media file URL |
| media_extra | object/null | Additional media information |
| media_profiles | object | Detailed description of the media file |
Fields in media_profiles:
| Field | Type | Description |
|---|---|---|
| media_data_type | string | Media file type; url indicates that the file is accessible through a URL |
| rsp_media_type | string | Media response type; png indicates PNG format |
Error codes and messages specific to this API:
| Error Code | Error Message | Description |
|---|---|---|
| 20001 | PROCESS_ERROR | Processing 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_mt1a3i5n7b5e06e9a8-xxxx-4a63-8b81-904c89418132",
"urls": [
"https://obs-large.mtlab.meitu.com/mtopen/ff56d688358849259556be0f50065a60/e11d21c9-070c-4e93-6f42-990db30ccda2.png"
],
"parameters": {
"has_watermark": true,
"is_text": false,
"rsp_media_type": "png",
"version": "1.1.6"
},
"data": {
"duration": {
"alg_process_time": 1821,
"created_timestamp": 1767065223,
"pull_timestamp": 1767065223,
"repost_time": 0,
"upload_time": 109,
"waiting_time": 78
},
"error_code": 0,
"error_msg": "success",
"extra": {},
"media_info_list": [
{
"media_data": "https://obs-large.mtlab.meitu.com/mtopen/ff56d688358849259556be0f50065a60/e11d21c9-070c-4e93-6f42-990db30ccda2.png",
"media_extra": null,
"media_profiles": {
"media_data_type": "url",
"rsp_media_type": "png"
}
}
],
"msg_id": "c2abad9a-xxxx-4049-45a2-r009c438d1bb",
"parameter": {
"has_watermark": true,
"is_text": false,
"rsp_media_type": "png",
"version": "1.1.6"
}
},
"msg": "success",
"msg_id": "c2abad9a-xxxx-4049-45a2-r009c438d1bb",
"images": [
"https://obs-large.mtlab.meitu.com/mtopen/ff56d688358849259556be0f50065a60/e11d21c9-070c-4e93-6f42-990db30ccda2.png"
],
"mtlab_res": {
"ErrorCode": 0,
"ErrorMsg": "",
"error_code": 0,
"error_msg": "",
"media_info_list": null,
"msg_id": "c2abad9a-xxxx-4049-45a2-r009c438d1bb",
"parameter": null
},
"media_info_list": [
{
"media_data": "https://obs-large.mtlab.meitu.com/mtopen/ff56d688358849259556be0f50065a60/e11d21c9-xxxx-4e93-6f42-990db30ccda2.png",
"media_extra": null,
"media_profiles": {
"media_data_type": "url",
"rsp_media_type": "png"
}
}
]
},
"progress": 1,
"predict_elapsed": 10000,
"create_time": 1767065223728,
"task_id": "t_mt1a3i5n7b5e06e9a8-xxxx-4a63-8b81-904c89418132",
"custom_task_id": "",
"trace_id": "",
"client_info": "",
"init_images": null
}
}Response Example Requiring a Query
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_mt1a3i5n7b5e06e9a8-xxxx-4a63-8b81-904c89418132"
},
"progress": 0,
"predict_elapsed": 10000,
"create_time": 1767065223728,
"task_id": "t_mt1a3i5n7b5e06e9a8-xxxx-4a63-8b81-904c89418132",
"custom_task_id": "",
"trace_id": "8a2f1605-0f70-xxxx-af6b-a3b379f7ac1e",
"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": {
"error_code": 20001,
"message": "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
See API Error Codes for details.
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": {"is_text": True},
}
payload = {
"task": "/v1/ai_eraser_watermark/485833",
"task_type": "formula",
"init_images": [
{
"url": "https://obs.mtlab.meitu.com/public/EtRGxLI8ulQ43pGhuZfym9aYUD2PUbMP/MTcwNjE0ODAwMA==/4d5c9604-3f3f-4247-7459-61dbc86c3300.jpeg",
"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/ai_eraser_watermark/485833",
"task_type": "formula",
"init_images": [{
"url": "https://obs.mtlab.meitu.com/public/EtRGxLI8ulQ43pGhuZfym9aYUD2PUbMP/MTcwNjE0ODAwMA==/4d5c9604-3f3f-4247-7459-61dbc86c3300.jpeg",
"profile": {
"media_profiles": {"media_data_type": "url"},
"version": "v1"
}
}],
"params": "{\"rsp_media_type\":\"url\",\"parameter\":{\"is_text\":true}}",
"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' => ['is_text' => true],
]);
$body = json_encode([
'task' => '/v1/ai_eraser_watermark/485833',
'task_type' => 'formula',
'init_images' => [
[
'url' => 'https://obs.mtlab.meitu.com/public/EtRGxLI8ulQ43pGhuZfym9aYUD2PUbMP/MTcwNjE0ODAwMA==/4d5c9604-3f3f-4247-7459-61dbc86c3300.jpeg',
'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/ai_eraser_watermark/485833\",\n" +
" \"task_type\": \"formula\",\n" +
" \"init_images\": [{\n" +
" \"url\": \"https://obs.mtlab.meitu.com/public/EtRGxLI8ulQ43pGhuZfym9aYUD2PUbMP/MTcwNjE0ODAwMA==/4d5c9604-3f3f-4247-7459-61dbc86c3300.jpeg\",\n" +
" \"profile\": {\n" +
" \"media_profiles\": {\"media_data_type\": \"url\"},\n" +
" \"version\": \"v1\"\n" +
" }\n" +
" }],\n" +
" \"params\": \"{\\\"rsp_media_type\\\":\\\"url\\\",\\\"parameter\\\":{\\\"is_text\\\":true}}\",\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);
}
}
}