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 类型,请检查输入参数。")