From a1ccb1a0c2dd9f982c0e43e4ef338e77e0094af5 Mon Sep 17 00:00:00 2001
From: Ze-Yi LIN <58305964+Zeyi-Lin@users.noreply.github.com>
Date: Thu, 12 Sep 2024 00:43:34 +0800
Subject: [PATCH] feat: api watermark (#105)
* api add watermark
* del requests_api and update api docs
* Update deploy_api.py
* refactor
* Update api_EN.md
* Update api_EN.md
---
README.md | 2 +-
demo/processor.py | 4 +-
demo/utils.py | 17 ---
deploy_api.py | 54 ++++++--
docs/api_CN.md | 259 +++++++++++++++++++--------------------
docs/api_EN.md | 304 ++++++++++++++++++++++------------------------
hivision/utils.py | 18 +++
inference.py | 2 +
requests_api.py | 196 ------------------------------
9 files changed, 334 insertions(+), 522 deletions(-)
delete mode 100644 requests_api.py
diff --git a/README.md b/README.md
index 7a7aadb2..20815e81 100644
--- a/README.md
+++ b/README.md
@@ -52,7 +52,7 @@
- 在线体验: [![SwanHub Demo](https://img.shields.io/static/v1?label=Demo&message=SwanHub%20Demo&color=blue)](https://swanhub.co/ZeYiLin/HivisionIDPhotos/demo)、[![Spaces](https://img.shields.io/badge/🤗-Open%20in%20Spaces-blue)](https://huggingface.co/spaces/TheEeeeLin/HivisionIDPhotos)
-- 2024.09.11: Gradio Demo增加**透明图显示与下载**功能
+- 2024.09.11: Gradio Demo增加**透明图显示与下载**功能 | API接口增加**加水印**
- 2024.09.10: 增加新的**人脸检测模型** Retinaface-resnet50,以稍弱于mtcnn的速度换取更高的检测精度,推荐使用
- 2024.09.09: 增加新的**抠图模型** [BiRefNet-v1-lite](https://github.com/ZhengPeng7/BiRefNet) | Gradio增加**高级参数设置**和**水印**选项卡
- 2024.09.08: 增加新的**抠图模型** [RMBG-1.4](https://huggingface.co/briaai/RMBG-1.4) | **ComfyUI工作流** - [HivisionIDPhotos-ComfyUI](https://github.com/AIFSH/HivisionIDPhotos-ComfyUI) 贡献 by [AIFSH](https://github.com/AIFSH/HivisionIDPhotos-ComfyUI)
diff --git a/demo/processor.py b/demo/processor.py
index eaa1f725..38536534 100644
--- a/demo/processor.py
+++ b/demo/processor.py
@@ -1,13 +1,13 @@
import numpy as np
from hivision import IDCreator
from hivision.error import FaceError, APIError
-from hivision.utils import add_background, resize_image_to_kb
+from hivision.utils import add_background, resize_image_to_kb, add_watermark
from hivision.creator.layout_calculator import (
generate_layout_photo,
generate_layout_image,
)
from hivision.creator.choose_handler import choose_handler
-from demo.utils import add_watermark, range_check
+from demo.utils import range_check
import gradio as gr
import os
import time
diff --git a/demo/utils.py b/demo/utils.py
index 29182279..7b6c07c1 100644
--- a/demo/utils.py
+++ b/demo/utils.py
@@ -42,20 +42,3 @@ def csv_to_color_list(csv_file: str) -> dict:
def range_check(value, min_value=0, max_value=255):
value = int(value)
return max(min_value, min(value, max_value))
-
-
-def add_watermark(
- image, text, size=50, opacity=0.5, angle=45, color="#8B8B1B", space=75
-):
- image = Image.fromarray(image)
- watermarker = Watermarker(
- input_image=image,
- text=text,
- style=WatermarkerStyles.STRIPED,
- angle=angle,
- color=color,
- opacity=opacity,
- size=size,
- space=space,
- )
- return np.array(watermarker.image.convert("RGB"))
diff --git a/deploy_api.py b/deploy_api.py
index 1f0851a8..1b512023 100644
--- a/deploy_api.py
+++ b/deploy_api.py
@@ -6,7 +6,12 @@
generate_layout_image,
)
from hivision.creator.choose_handler import choose_handler
-from hivision.utils import add_background, resize_image_to_kb_base64, hex_to_rgb
+from hivision.utils import (
+ add_background,
+ resize_image_to_kb_base64,
+ hex_to_rgb,
+ add_watermark,
+)
import base64
import numpy as np
import cv2
@@ -27,14 +32,14 @@ def numpy_2_base64(img: np.ndarray):
@app.post("/idphoto")
async def idphoto_inference(
input_image: UploadFile,
- height: int = Form(413),
- width: int = Form(295),
+ height: str = Form(...),
+ width: str = Form(...),
human_matting_model: str = Form("hivision_modnet"),
face_detect_model: str = Form("mtcnn"),
- head_measure_ratio: float = 0.2,
- head_height_ratio: float = 0.45,
- top_distance_max: float = 0.12,
- top_distance_min: float = 0.10,
+ head_measure_ratio=0.2,
+ head_height_ratio=0.45,
+ top_distance_max=0.12,
+ top_distance_min=0.10,
):
image_bytes = await input_image.read()
@@ -101,7 +106,7 @@ async def idphoto_inference(
async def photo_add_background(
input_image: UploadFile,
color: str = Form(...),
- kb: int = Form(None),
+ kb: str = Form(None),
render: int = Form(0),
):
render_choice = ["pure_color", "updown_gradient", "center_gradient"]
@@ -147,7 +152,7 @@ async def generate_layout_photos(
input_image: UploadFile,
height: str = Form(...),
width: str = Form(...),
- kb: int = Form(None),
+ kb: str = Form(None),
):
# try:
image_bytes = await input_image.read()
@@ -185,6 +190,37 @@ async def generate_layout_photos(
return result_messgae
+# 透明图像添加纯色背景接口
+@app.post("/watermark")
+async def watermark(
+ input_image: UploadFile,
+ text: str = Form("Hello"),
+ size: int = 20,
+ opacity: float = 0.5,
+ angle: int = 30,
+ color: str = "#000000",
+ space: int = 25,
+):
+ image_bytes = await input_image.read()
+ nparr = np.frombuffer(image_bytes, np.uint8)
+ img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
+
+ try:
+ result_image = add_watermark(img, text, size, opacity, angle, color, space)
+
+ result_messgae = {
+ "status": True,
+ "image_base64": numpy_2_base64(result_image),
+ }
+ except Exception as e:
+ result_messgae = {
+ "status": False,
+ "error": e,
+ }
+
+ return result_messgae
+
+
if __name__ == "__main__":
import uvicorn
diff --git a/docs/api_CN.md b/docs/api_CN.md
index 4763b7ac..0230e01d 100644
--- a/docs/api_CN.md
+++ b/docs/api_CN.md
@@ -9,8 +9,6 @@
- [接口功能说明](#接口功能说明)
- [cURL 请求示例](#curl-请求示例)
- [Python 请求示例](#python-请求示例)
- - [Python Requests 请求方法](#1️⃣-python-requests-请求方法)
- - [Python 脚本请求方法](#2️⃣-python-脚本请求方法)
- [Java 请求示例](#java-请求示例)
- [Javascript 请求示例](#javascript-请求示例)
@@ -103,12 +101,21 @@ curl -X POST "http://127.0.0.1:8080/human_matting" \
-F "human_matting_model=hivision_modnet"
```
+### 5. 图片加水印
+```bash
+curl -X 'POST' \
+ 'http://127.0.0.1:8080/watermark?size=20&opacity=0.5&angle=30&color=%23000000&space=25' \
+ -H 'accept: application/json' \
+ -H 'Content-Type: multipart/form-data' \
+ -F 'input_image=@demo/images/test0.jpg;type=image/jpeg' \
+ -F 'text=Hello'
+```
+
+
## Python 请求示例
-### 1️⃣ Python Requests 请求方法
-
#### 1.生成证件照(底透明)
```python
@@ -178,124 +185,32 @@ response = requests.post(url, files=files, data=data).json()
print(response)
```
-### 2️⃣ Python 脚本请求方法
-
-```bash
-python requests_api.py -u -t -i -o [--height ] [--width ] [-c ] [-k ]
-```
-
-#### 参数说明
-
-##### 基本参数
-
-- `-u`, `--url`
-
- - **描述**: API 服务的 URL。
- - **默认值**: `http://127.0.0.1:8080`
-
-- `-t`, `--type`
-
- - **描述**: 请求 API 的种类。
- - **默认值**: `idphoto`
-
-- `-i`, `--input_image_dir`
-
- - **描述**: 输入图像路径。
- - **必需**: 是
- - **示例**: `./input_images/photo.jpg`
-
-- `-o`, `--output_image_dir`
- - **描述**: 保存图像路径。
- - **必需**: 是
- - **示例**: `./output_images/processed_photo.jpg`
-
-##### 可选参数
-
-- `--face_detect_model`
- - **描述**: 人脸检测模型
- - **默认值**: mtcnn
-
-- `--human_matting_model`
- - **描述**: 人像抠图模型
- - **默认值**: hivision_modnet
-
-- `--height`,
- - **描述**: 标准证件照的输出尺寸的高度。
- - **默认值**: 413
-
-- `--width`,
- - **描述**: 标准证件照的输出尺寸的宽度。
- - **默认值**: 295
-
-- `-c`, `--color`
- - **描述**: 给透明图增加背景色,格式为 Hex(如#638cce),仅在 type 为`add_background`时生效
- - **默认值**: `638cce`
-
-- `-k`, `--kb`
- - **描述**: 输出照片的 KB 值,仅在 type 为`add_background`和`generate_layout_photos`时生效,值为 None 时不做设置。
- - **默认值**: `None`
- - **示例**: 50
-
-- `-r`, `--render`
- - **描述**: 给透明图增加背景色时的渲染方式,仅在 type 为`add_background`和`generate_layout_photos`时生效
- - **默认值**: 0
-
-### 1.生成证件照(底透明)
-
-```bash
-python requests_api.py \
- -u http://127.0.0.1:8080 \
- -t idphoto \
- -i ./photo.jpg \
- -o ./idphoto.png \
- --height 413 \
- --width 295 \
- --face_detect_model mtcnn \
- --human_matting_model hivision_modnet
-```
-
-### 2.添加背景色
-
-```bash
-python requests_api.py \
- -u http://127.0.0.1:8080 \
- -t add_background \
- -i ./idphoto.png \
- -o ./idphoto_with_background.jpg \
- -c 638cce \
- -k 50 \
- -r 0
-```
-
-### 3.生成六寸排版照
-
-```bash
-python requests_api.py \
- -u http://127.0.0.1:8080 \
- -t generate_layout_photos \
- -i ./idphoto_with_background.jpg \
- -o ./layout_photo.jpg \
- --height 413 \
- --width 295 \
- -k 200
-```
+#### 5.图片加水印
+```python
+import requests
-### 4.人像抠图
+# 设置请求的 URL 和参数
+url = "http://127.0.0.1:8080/watermark"
+params = {"size": 20, "opacity": 0.5, "angle": 30, "color": "#000000", "space": 25}
-```bash
-python requests_api.py \
- -u http://127.0.0.1:8080 \
- -t human_matting \
- -i ./photo.jpg \
- -o ./photo_matting.png \
- --human_matting_model hivision_modnet
+# 设置文件和其他表单数据
+input_image_path = "demo/images/test0.jpg"
+files = {"input_image": open(input_image_path, "rb")}
+data = {"text": "Hello"}
+
+# 发送 POST 请求
+response = requests.post(url, params=params, files=files, data=data)
+
+# 检查响应
+if response.ok:
+ # 输出响应内容
+ print(response.json())
+else:
+ # 输出错误信息
+ print(f"Request failed with status code {response.status_code}: {response.text}")
```
-### 请求失败的情况
-
-- 照片中检测到的人脸大于 1,则失败
-
## Java 请求示例
@@ -322,11 +237,11 @@ python requests_api.py \
```java
/**
- * 生成证件照(底透明) /idphoto 接口
- * @param inputImageDir 文件地址
- * @return
- * @throws IOException
- */
+* 生成证件照(底透明) /idphoto 接口
+* @param inputImageDir 文件地址
+* @return
+* @throws IOException
+*/
public static String requestIdPhoto(String inputImageDir) throws IOException {
String url = BASE_URL+"/idphoto";
// 创建文件对象
@@ -344,11 +259,11 @@ public static String requestIdPhoto(String inputImageDir) throws IOException {
```java
/**
- * 添加背景色 /add_background 接口
- * @param inputImageDir 文件地址
- * @return
- * @throws IOException
- */
+* 添加背景色 /add_background 接口
+* @param inputImageDir 文件地址
+* @return
+* @throws IOException
+*/
public static String requestAddBackground(String inputImageDir) throws IOException {
String url = BASE_URL+"/add_background";
// 创建文件对象
@@ -366,11 +281,11 @@ public static String requestAddBackground(String inputImageDir) throws IOExcepti
```java
/**
- * 生成六寸排版照 /generate_layout_photos 接口
- * @param inputImageDir 文件地址
- * @return
- * @throws IOException
- */
+* 生成六寸排版照 /generate_layout_photos 接口
+* @param inputImageDir 文件地址
+* @return
+* @throws IOException
+*/
public static String requestGenerateLayoutPhotos(String inputImageDir) throws IOException {
String url = BASE_URL+"/generate_layout_photos";
// 创建文件对象
@@ -389,11 +304,11 @@ public static String requestGenerateLayoutPhotos(String inputImageDir) throws IO
```java
/**
- * 生成人像抠图照 /human_matting 接口
- * @param inputImageDir 文件地址
- * @return
- * @throws IOException
- */
+* 生成人像抠图照 /human_matting 接口
+* @param inputImageDir 文件地址
+* @return
+* @throws IOException
+*/
public static String requestHumanMattingPhotos(String inputImageDir) throws IOException {
String url = BASE_URL+"/human_matting";
// 创建文件对象
@@ -405,6 +320,37 @@ public static String requestHumanMattingPhotos(String inputImageDir) throws IOEx
}
```
+### 5.图像加水印
+
+```java
+/**
+ * 添加水印到图片 /watermark 接口
+ * @param inputImageDir 文件地址
+ * @param text 水印文本
+ * @param size 水印文字大小
+ * @param opacity 水印透明度
+ * @param angle 水印旋转角度
+ * @param color 水印颜色
+ * @param space 水印间距
+ * @return
+ * @throws IOException
+ */
+public static String requestAddWatermark(String inputImageDir, String text, int size, double opacity, int angle, String color, int space) throws IOException {
+ String url = BASE_URL + "/watermark?size=" + size + "&opacity=" + opacity + "&angle=" + angle + "&color=" + color + "&space=" + space;
+
+ // 创建文件对象
+ File inputFile = new File(inputImageDir);
+
+ // 创建参数映射
+ Map paramMap = new HashMap<>();
+ paramMap.put("input_image", inputFile);
+ paramMap.put("text", text);
+
+ // 发送POST请求并返回响应
+ return HttpUtil.post(url, paramMap);
+}
+```
+
## JavaScript 请求示例
@@ -512,4 +458,43 @@ async function uploadImage(inputImagePath) {
uploadImage("demo/images/test0.jpg").then(response => {
console.log(response);
});
+```
+
+### 5.图像加水印
+
+```javascript
+async function sendMultipartRequest() {
+ const url = "http://127.0.0.1:8080/watermark?size=20&opacity=0.5&angle=30&color=%23000000&space=25";
+
+ const formData = new FormData();
+ formData.append("text", "Hello");
+
+ // Assuming you have a file input element with id 'fileInput'
+ const fileInput = document.getElementById('fileInput');
+ if (fileInput.files.length > 0) {
+ formData.append("input_image", fileInput.files[0]);
+ }
+
+ try {
+ const response = await fetch(url, {
+ method: 'POST',
+ headers: {
+ 'Accept': 'application/json'
+ },
+ body: formData
+ });
+
+ if (response.ok) {
+ const jsonResponse = await response.json();
+ console.log(jsonResponse);
+ } else {
+ console.error('Request failed:', response.status, response.statusText);
+ }
+ } catch (error) {
+ console.error('Error:', error);
+ }
+}
+
+// Call the function to send request
+sendMultipartRequest();
```
\ No newline at end of file
diff --git a/docs/api_EN.md b/docs/api_EN.md
index cfb7f262..c412d690 100644
--- a/docs/api_EN.md
+++ b/docs/api_EN.md
@@ -1,22 +1,19 @@
# API Docs
-English / [中文](api_CN.md) / [日本語](api_JP.md) / [한국어](api_KO.md)
-
+English / [中文](README.md) / [日本語](api_JP.md) / [한국어](api_KO.md)
## Table of Contents
-- [Getting Started: Start the Backend Service](#getting-started-start-the-backend-service)
-- [API Function Descriptions](#api-function-descriptions)
+- [Before You Start: Start the Backend Service](#before-you-start-start-the-backend-service)
+- [API Functionality Description](#api-functionality-description)
- [cURL Request Examples](#curl-request-examples)
- [Python Request Examples](#python-request-examples)
- - [Python Requests Method](#1️⃣-python-requests-method)
- - [Python Script Method](#2️⃣-python-script-method)
- [Java Request Examples](#java-request-examples)
- [JavaScript Request Examples](#javascript-request-examples)
-## Getting Started: Start the Backend Service
+## Before You Start: Start the Backend Service
-Before making API requests, please start the backend service
+Before making API requests, please run the backend service.
```bash
python deploy_api.py
@@ -24,7 +21,7 @@ python deploy_api.py
-## API Function Descriptions
+## API Functionality Description
### 1. Generate ID Photo (Transparent Background)
@@ -32,37 +29,37 @@ API Name: `idphoto`
The logic of the `Generate ID Photo` API is to send an RGB image and output a standard ID photo and a high-definition ID photo:
-- **High-definition ID Photo**: The ID photo created based on the aspect ratio of `size`, with the filename being `output_image_dir` with the `_hd` suffix added.
-- **Standard ID Photo**: The size is equal to `size`, scaled from the high-definition ID photo, with the filename being `output_image_dir`.
+- **High-Definition ID Photo**: An ID photo created based on the aspect ratio of `size`, with the filename being `output_image_dir` plus `_hd` suffix.
+- **Standard ID Photo**: Size equals to `size`, scaled down from the high-definition ID photo, with the filename `output_image_dir`.
-It is important to note that both generated photos are transparent (RGBA four-channel images). To generate a complete ID photo, the following `Add Background Color` API is needed.
+It is important to note that both generated photos are transparent (RGBA four-channel images). To generate a complete ID photo, you will also need the `Add Background Color` API below.
> Q: Why is it designed this way?
-> A: Because in actual products, users often switch background colors to preview effects frequently. Providing a transparent background image allows for a better experience with color composition done by frontend JS code.
+> A: Because in actual products, users often switch background color previews frequently. Providing a transparent background image for the frontend JS code to synthesize colors is a better user experience.
### 2. Add Background Color
API Name: `add_background`
-The logic of the `Add Background Color` API is to send an RGBA image and add a background color based on `color`, resulting in a JPG image.
+The logic of the `Add Background Color` API is to send an RGBA image and add a background color based on `color`, synthesizing a JPG image.
-### 3. Generate Six-Inch Layout Photo
+### 3. Generate 6-inch Layout Photo
API Name: `generate_layout_photos`
-The logic of the `Generate Six-Inch Layout Photo` API is to send an RGB image (typically the ID photo after adding background color) and arrange the photos based on `size`, resulting in a six-inch layout photo.
+The logic of the `Generate 6-inch Layout Photo` API is to send an RGB image (generally the ID photo after adding background color), arrange the photos based on `size`, and then generate a 6-inch layout photo.
### 4. Human Matting
API Name: `human_matting`
-The logic of the `Human Matting` API is to send an RGB image and output a standard matting portrait and a high-definition matting portrait (with no background fill).
+The logic of the `Human Matting` API is to send an RGB image and output a standard matting portrait and a high-definition matting portrait (without any background filling).
## cURL Request Examples
-cURL is a command-line tool for transferring data using various network protocols. Below are examples of using cURL to call these APIs.
+cURL is a command-line tool used to transfer data with various network protocols. Below are examples of calling these APIs using cURL.
### 1. Generate ID Photo (Transparent Background)
@@ -85,7 +82,7 @@ curl -X POST "http://127.0.0.1:8080/add_background" \
-F "render=0"
```
-### 3. Generate Six-Inch Layout Photo
+### 3. Generate 6-inch Layout Photo
```bash
curl -X POST "http://127.0.0.1:8080/generate_layout_photos" \
@@ -103,19 +100,27 @@ curl -X POST "http://127.0.0.1:8080/human_matting" \
-F "human_matting_model=hivision_modnet"
```
+### 5. Add Watermark to Image
+```bash
+curl -X 'POST' \
+ 'http://127.0.0.1:8080/watermark?size=20&opacity=0.5&angle=30&color=%23000000&space=25' \
+ -H 'accept: application/json' \
+ -H 'Content-Type: multipart/form-data' \
+ -F 'input_image=@demo/images/test0.jpg;type=image/jpeg' \
+ -F 'text=Hello'
+```
+
## Python Request Examples
-### 1️⃣ Python Requests Method
-
#### 1. Generate ID Photo (Transparent Background)
```python
import requests
url = "http://127.0.0.1:8080/idphoto"
-input_image_path = "images/test0.jpg"
+input_image_path = "demo/images/test0.jpg"
files = {"input_image": open(input_image_path, "rb")}
data = {"height": 413, "width": 295, "human_matting_model": "hivision_modnet", "face_detect_model": "mtcnn"}
@@ -143,7 +148,7 @@ response = requests.post(url, files=files, data=data).json()
print(response)
```
-#### 3. Generate Six-Inch Layout Photo
+#### 3. Generate 6-inch Layout Photo
```python
import requests
@@ -177,128 +182,37 @@ response = requests.post(url, files=files, data=data).json()
print(response)
```
-### 2️⃣ Python Script Method
-
-```bash
-python requests_api.py -u -t -i -o [--height ] [--width ] [-c ] [-k ]
-```
-
-#### Parameter Descriptions
-
-##### Basic Parameters
-
-- `-u`, `--url`
-
- - **Description**: The URL of the API service.
- - **Default Value**: `http://127.0.0.1:8080`
-
-- `-t`, `--type`
-
- - **Description**: The type of API request.
- - **Default Value**: `idphoto`
-
-- `-i`, `--input_image_dir`
-
- - **Description**: The path to the input image.
- - **Required**: Yes
- - **Example**: `./input_images/photo.jpg`
-
-- `-o`, `--output_image_dir`
- - **Description**: The path to save the image.
- - **Required**: Yes
- - **Example**: `./output_images/processed_photo.jpg`
-
-##### Optional Parameters
-
-- `--face_detect_model`
- - **Description**: Face detection model
- - **Default Value**: mtcnn
-
-- `--human_matting_model`
- - **Description**: Human matting model
- - **Default Value**: hivision_modnet
-
-- `--height`
- - **Description**: The height of the output size for the standard ID photo.
- - **Default Value**: 413
-
-- `--width`
- - **Description**: The width of the output size for the standard ID photo.
- - **Default Value**: 295
-
-- `-c`, `--color`
- - **Description**: Add background color to the transparent image, format as Hex (e.g., #638cce), only effective when type is `add_background`
- - **Default Value**: `638cce`
-
-- `-k`, `--kb`
- - **Description**: The KB value of the output photo, only effective when type is `add_background` or `generate_layout_photos`, no setting when the value is None.
- - **Default Value**: `None`
- - **Example**: 50
-
-- `-r`, `--render`
- - **Description**: The rendering method for adding background color to the transparent image, only effective when type is `add_background` or `generate_layout_photos`
- - **Default Value**: 0
-
-### 1. Generate ID Photo (Transparent Background)
-
-```bash
-python requests_api.py \
- -u http://127.0.0.1:8080 \
- -t idphoto \
- -i ./photo.jpg \
- -o ./idphoto.png \
- --height 413 \
- --width 295 \
- --face_detect_model mtcnn \
- --human_matting_model hivision_modnet
-```
-
-### 2. Add Background Color
-
-```bash
-python requests_api.py \
- -u http://127.0.0.1:8080 \
- -t add_background \
- -i ./idphoto.png \
- -o ./idphoto_with_background.jpg \
- -c 638cce \
- -k 50 \
- -r 0
-```
+#### 5. Add Watermark to Image
-### 3. Generate Six-Inch Layout Photo
-
-```bash
-python requests_api.py \
- -u http://127.0.0.1:8080 \
- -t generate_layout_photos \
- -i ./idphoto_with_background.jpg \
- -o ./layout_photo.jpg \
- --height 413 \
- --width 295 \
- -k 200
-```
+```python
+import requests
-### 4. Human Matting
+# Set the request URL and parameters
+url = "http://127.0.0.1:8080/watermark"
+params = {"size": 20, "opacity": 0.5, "angle": 30, "color": "#000000", "space": 25}
-```bash
-python requests_api.py \
- -u http://127.0.0.1:8080 \
- -t human_matting \
- -i ./photo.jpg \
- -o ./photo_matting.png \
- --human_matting_model hivision_modnet
+# Set the file and other form data
+input_image_path = "demo/images/test0.jpg"
+files = {"input_image": open(input_image_path, "rb")}
+data = {"text": "Hello"}
+
+# Send POST request
+response = requests.post(url, params=params, files=files, data=data)
+
+# Check the response
+if response.ok:
+ # Output the response content
+ print(response.json())
+else:
+ # Output the error information
+ print(f"Request failed with status code {response.status_code}: {response.text}")
```
-### Failure Cases
-
-- If more than one face is detected in the photo, the request will fail.
-
## Java Request Examples
-### Add Maven Dependencies
+### Add Maven Dependency
```java
@@ -320,11 +234,11 @@ python requests_api.py \
```java
/**
- * Generate ID Photo (Transparent Background) /idphoto API
- * @param inputImageDir File path
- * @return
- * @throws IOException
- */
+* Generate ID Photo (Transparent Background) /idphoto API
+* @param inputImageDir File path
+* @return
+* @throws IOException
+*/
public static String requestIdPhoto(String inputImageDir) throws IOException {
String url = BASE_URL+"/idphoto";
// Create file object
@@ -342,11 +256,11 @@ public static String requestIdPhoto(String inputImageDir) throws IOException {
```java
/**
- * Add Background Color /add_background API
- * @param inputImageDir File path
- * @return
- * @throws IOException
- */
+* Add Background Color /add_background API
+* @param inputImageDir File path
+* @return
+* @throws IOException
+*/
public static String requestAddBackground(String inputImageDir) throws IOException {
String url = BASE_URL+"/add_background";
// Create file object
@@ -360,15 +274,15 @@ public static String requestAddBackground(String inputImageDir) throws IOExcepti
}
```
-#### 3. Generate Six-Inch Layout Photo
+#### 3. Generate 6-inch Layout Photo
```java
/**
- * Generate Six-Inch Layout Photo /generate_layout_photos API
- * @param inputImageDir File path
- * @return
- * @throws IOException
- */
+* Generate 6-inch Layout Photo /generate_layout_photos API
+* @param inputImageDir File path
+* @return
+* @throws IOException
+*/
public static String requestGenerateLayoutPhotos(String inputImageDir) throws IOException {
String url = BASE_URL+"/generate_layout_photos";
// Create file object
@@ -387,11 +301,11 @@ public static String requestGenerateLayoutPhotos(String inputImageDir) throws IO
```java
/**
- * Generate Human Matting Photo /human_matting API
- * @param inputImageDir File path
- * @return
- * @throws IOException
- */
+* Generate Human Matting Photo /human_matting API
+* @param inputImageDir File path
+* @return
+* @throws IOException
+*/
public static String requestHumanMattingPhotos(String inputImageDir) throws IOException {
String url = BASE_URL+"/human_matting";
// Create file object
@@ -403,6 +317,37 @@ public static String requestHumanMattingPhotos(String inputImageDir) throws IOEx
}
```
+### 5. Add Watermark to Image
+
+```java
+/**
+ * Add watermark to image /watermark API
+ * @param inputImageDir File path
+ * @param text Watermark text
+ * @param size Watermark text size
+ * @param opacity Watermark opacity
+ * @param angle Watermark rotation angle
+ * @param color Watermark color
+ * @param space Watermark spacing
+ * @return
+ * @throws IOException
+ */
+public static String requestAddWatermark(String inputImageDir, String text, int size, double opacity, int angle, String color, int space) throws IOException {
+ String url = BASE_URL + "/watermark?size=" + size + "&opacity=" + opacity + "&angle=" + angle + "&color=" + color + "&space=" + space;
+
+ // Create file object
+ File inputFile = new File(inputImageDir);
+
+ // Create parameter mapping
+ Map paramMap = new HashMap<>();
+ paramMap.put("input_image", inputFile);
+ paramMap.put("text", text);
+
+ // Send POST request and return response
+ return HttpUtil.post(url, paramMap);
+}
+```
+
## JavaScript Request Examples
@@ -430,7 +375,7 @@ async function generateIdPhoto(inputImagePath, height, width) {
}
// Example call
-generateIdPhoto("images/test0.jpg", 413, 295).then(response => {
+generateIdPhoto("images/test.jpg", 413, 295).then(response => {
console.log(response);
});
```
@@ -461,7 +406,7 @@ addBackground("test.png", "638cce", 200).then(response => {
});
```
-### 3. Generate Six-Inch Layout Photo
+### 3. Generate 6-inch Layout Photo
```javascript
async function generateLayoutPhotos(inputImagePath, height, width, kb) {
@@ -501,7 +446,7 @@ async function uploadImage(inputImagePath) {
body: formData
});
- const result = await response.json(); // Assume the response is in JSON format
+ const result = await response.json(); // Assuming the response is in JSON format
console.log(result);
return result;
}
@@ -510,4 +455,43 @@ async function uploadImage(inputImagePath) {
uploadImage("demo/images/test0.jpg").then(response => {
console.log(response);
});
+```
+
+### 5. Add Watermark to Image
+
+```javascript
+async function sendMultipartRequest() {
+ const url = "http://127.0.0.1:8080/watermark?size=20&opacity=0.5&angle=30&color=%23000000&space=25";
+
+ const formData = new FormData();
+ formData.append("text", "Hello");
+
+ // Assuming you have a file input element with id 'fileInput'
+ const fileInput = document.getElementById('fileInput');
+ if (fileInput.files.length > 0) {
+ formData.append("input_image", fileInput.files[0]);
+ }
+
+ try {
+ const response = await fetch(url, {
+ method: 'POST',
+ headers: {
+ 'Accept': 'application/json'
+ },
+ body: formData
+ });
+
+ if (response.ok) {
+ const jsonResponse = await response.json();
+ console.log(jsonResponse);
+ } else {
+ console.error('Request failed:', response.status, response.statusText);
+ }
+ } catch (error) {
+ console.error('Error:', error);
+ }
+}
+
+// Call the function to send request
+sendMultipartRequest();
```
\ No newline at end of file
diff --git a/hivision/utils.py b/hivision/utils.py
index 8a57d70b..6bf0465e 100644
--- a/hivision/utils.py
+++ b/hivision/utils.py
@@ -12,6 +12,7 @@
import numpy as np
import cv2
import base64
+from hivision.plugin.watermark import Watermarker, WatermarkerStyles
def resize_image_to_kb(input_image, output_image_path, target_size_kb):
@@ -273,3 +274,20 @@ def add_background(input_image, bgr=(0, 0, 0), mode="pure_color"):
)
return output
+
+
+def add_watermark(
+ image, text, size=50, opacity=0.5, angle=45, color="#8B8B1B", space=75
+):
+ image = Image.fromarray(image)
+ watermarker = Watermarker(
+ input_image=image,
+ text=text,
+ style=WatermarkerStyles.STRIPED,
+ angle=angle,
+ color=color,
+ opacity=opacity,
+ size=size,
+ space=space,
+ )
+ return np.array(watermarker.image.convert("RGB"))
diff --git a/inference.py b/inference.py
index 0d9e6398..80596dab 100644
--- a/inference.py
+++ b/inference.py
@@ -10,6 +10,7 @@
generate_layout_image,
)
from hivision.creator.choose_handler import choose_handler
+from hivision.utils import hex_to_rgb, resize_image_to_kb
INFERENCE_TYPE = [
@@ -17,6 +18,7 @@
"human_matting",
"add_background",
"generate_layout_photos",
+ "watermark",
]
MATTING_MODEL = [
"hivision_modnet",
diff --git a/requests_api.py b/requests_api.py
deleted file mode 100644
index 446352cd..00000000
--- a/requests_api.py
+++ /dev/null
@@ -1,196 +0,0 @@
-import requests
-import base64
-import argparse
-import os
-
-INFERENCE_TYPE = [
- "idphoto",
- "human_matting",
- "add_background",
- "generate_layout_photos",
-]
-MATTING_MODEL = [
- "hivision_modnet",
- "modnet_photographic_portrait_matting",
- "mnn_hivision_modnet",
- "rmbg-1.4",
- "birefnet-v1-lite",
-]
-FACE_DETECT_MODEL = [
- "mtcnn",
- "face_plusplus",
- "retinaface-resnet50",
-]
-RENDER = [0, 1, 2]
-
-
-def base64_save(_base64_image_data, save_path):
- # 解码 Base64 数据并保存为 PNG 文件
- img_data = base64.b64decode(_base64_image_data)
- with open(save_path, "wb") as file:
- file.write(img_data)
-
-
-# 读取本地图像文件并转换为Base64编码
-def file_2_base64(file_path):
- with open(file_path, "rb") as file:
- encoded_string = base64.b64encode(file.read()).decode("utf-8")
- return encoded_string
-
-
-# 发送请求到 /idphoto 接口
-def request_idphoto(
- file_path,
- height,
- width,
- human_matting_model="hivision_idphotos",
- face_detect_model="mtcnn",
-):
- files = {"input_image": open(file_path, "rb")}
- data = {
- "height": int(height),
- "width": int(width),
- "human_matting_model": human_matting_model,
- "face_detect_model": face_detect_model,
- }
- response = requests.post(url, files=files, data=data)
- return response.json()
-
-
-# 发送请求到 /add_background 接口
-def request_add_background(file_path, color, kb=None):
- files = {"input_image": open(file_path, "rb")}
- data = {"color": str(color), "kb": kb}
- response = requests.post(url, files=files, data=data)
- return response.json()
-
-
-# 发送请求到 /generate_layout_photos 接口
-def request_generate_layout_photos(file_path, height, width, kb=None):
- files = {"input_image": open(file_path, "rb")}
- data = {"height": height, "width": width, "kb": kb}
- response = requests.post(url, files=files, data=data)
- return response.json()
-
-
-# 发送请求到 /human_matting 接口
-def request_human_matting(
- file_path,
- human_matting_model="hivision_idphotos",
-):
- files = {"input_image": open(file_path, "rb")}
- data = {"human_matting_model": human_matting_model}
- response = requests.post(url, files=files, data=data)
- return response.json()
-
-
-# 示例调用
-if __name__ == "__main__":
-
- parser = argparse.ArgumentParser(
- description="HivisionIDPhotos 证件照制作推理程序。"
- )
- parser.add_argument(
- "-u", "--url", help="API 服务的 URL", default="http://localhost:8080"
- )
- parser.add_argument(
- "-t",
- "--type",
- help="请求 API 的种类,有 idphoto、add_background 和 generate_layout_photos 可选",
- default="idphoto",
- )
- parser.add_argument("-i", "--input_image_dir", help="输入图像路径", required=True)
- parser.add_argument("-o", "--output_image_dir", help="保存图像路径", required=True)
- parser.add_argument("--height", help="证件照尺寸-高", default=413)
- parser.add_argument("--width", help="证件照尺寸-宽", default=295)
- parser.add_argument("-c", "--color", help="证件照背景色", default="638cce")
- parser.add_argument(
- "-k", "--kb", help="输出照片的 KB 值,仅对换底和制作排版照生效", default=None
- )
- parser.add_argument(
- "-r",
- "--render",
- type=int,
- help="底色合成的模式,有 0:纯色、1:上下渐变、2:中心渐变 可选",
- choices=RENDER,
- default=0,
- )
- parser.add_argument(
- "--human_matting_model",
- help="抠图模型权重",
- default="hivision_modnet",
- choices=MATTING_MODEL,
- )
- parser.add_argument(
- "--face_detect_model",
- help="人脸检测模型",
- default="mtcnn",
- choices=FACE_DETECT_MODEL,
- )
-
- args = parser.parse_args()
- url = f"{args.url}/{args.type}" # 替换为实际的接口 URL
-
- if args.type == "idphoto":
- # 调用 /idphoto 接口
- idphoto_response = request_idphoto(
- args.input_image_dir,
- int(args.height),
- int(args.width),
- human_matting_model=args.human_matting_model,
- face_detect_model=args.face_detect_model,
- )
-
- if idphoto_response["status"]:
- # 解码 Base64 数据并保存为 PNG 文件
- base64_image_data_standard = idphoto_response["image_base64_standard"]
- base64_image_data_standard_hd = idphoto_response["image_base64_hd"]
-
- file_name, file_extension = os.path.splitext(args.output_image_dir)
- # 定义新的文件路径(在原有的文件名后添加"_hd")
- new_file_name = file_name + "_hd" + file_extension
-
- # 解码 Base64 数据并保存为 PNG 文件
- base64_save(base64_image_data_standard, args.output_image_dir)
- base64_save(base64_image_data_standard_hd, new_file_name)
-
- print(f"请求{args.type}接口成功,已保存图像。")
- else:
- print("人脸数量不等于 1,请上传单张人脸的图像。")
-
- elif args.type == "add_background":
- # 调用 /add_background 接口
- add_background_response = request_add_background(
- args.input_image_dir, args.color, kb=args.kb
- )
- base64_image_data = add_background_response["image_base64"]
- base64_save(base64_image_data, args.output_image_dir)
-
- print(f"请求{args.type}接口成功,已保存图像。")
-
- elif args.type == "generate_layout_photos":
- # 调用 /generate_layout_photos 接口
- generate_layout_response = request_generate_layout_photos(
- args.input_image_dir, int(args.height), int(args.width), args.kb
- )
- base64_image_data = generate_layout_response["image_base64"]
- base64_save(base64_image_data, args.output_image_dir)
-
- print(f"请求{args.type}接口成功,已保存图像。")
-
- elif args.type == "human_matting":
- # 调用 /human_matting 接口
- human_matting_response = request_human_matting(
- args.input_image_dir, args.human_matting_model
- )
- base64_image_data = human_matting_response["image_base64"]
-
- file_name, file_extension = os.path.splitext(args.output_image_dir)
-
- # 解码 Base64 数据并保存为 PNG 文件
- base64_save(base64_image_data, args.output_image_dir)
-
- print(f"请求{args.type}接口成功,已保存图像。")
-
- else:
- print("不支持的 API 类型,请检查输入参数。")