发布于 2026-01-06 1 阅读
0

🎨 图像处理即服务 🐍 AWS AI LIVE!

🎨图像处理即服务🐍

AWS AI 直播!

👋 你好

你是否编写过图像转换脚本?你是否与他人共享过该脚本,或者在多台计算机上运行过?你需要更新脚本或设置说明多少次?最终你是否将其开发成服务或在线应用程序?如果你的脚本很有用,你很可能希望将其分享给其他人。部署处理服务是一个常见的需求,但也伴随着一系列挑战。无服务器技术可以帮助你轻松高效地解决这些挑战。

在这篇文章中,你将看到如何……

  • 创建一个图像处理服务,用于生成着色页。
  • 使用最少的资源将其发布到网上。

……而且全部用不到 200 行 Python 和 JavaScript 代码就能完成!

🛠️ 工具

要构建和部署一个涂色页生成器,你需要一些工具:

  • 一个用于处理图像的库
  • 一个Web应用程序框架
  • 网络服务器
  • 采用无服务器解决方案,使演示全天候可用

🧱 建筑

以下是使用 Cloud Run 构建着色页生成器的一种可能架构:

使用 Cloud Run 构建 Web 应用程序的架构

以下是工作流程:

  • 1 - 用户打开 Web 应用程序:浏览器请求主页。
  • 2 - Cloud Run 提供应用程序 HTML 代码。
  • 3 - 浏览器请求所需的其他资源。
  • 4 - Cloud Run 提供 CSS、JavaScript 和其他资源。
  • A - 用户选择一张图片,前端将图片发送到/api/coloring-page端点。
  • B - 后端处理输入图像并返回输出图像,然后用户可以通过浏览器查看、下载或打印该图像。

🐍 软件栈

当然,有很多不同的软件栈可以用来实现这样的架构。

这里有一个基于 Python 的好例子:

模式

其中包括:

  • Gunicorn:一款生产级 WSGI HTTP 服务器
  • Flask:一个流行的 Web 应用框架
  • scikit-image:一个功能强大的图像处理库

在名为以下名称的文件中定义这些应用程序依赖项requirements.txt

# https://pypi.org/project/gunicorn
gunicorn==20.1.0

# https://pypi.org/project/flask
Flask==2.1.1

# https://pypi.org/project/scikit-image
# scikit-image dependencies include NumPy and Pillow
scikit-image==0.19.2
Enter fullscreen mode Exit fullscreen mode

🎨 图像处理

如何从图像中去除颜色?一种方法是检测物体边缘,然后去除结果图像中除边缘以外的所有颜色。这可以通过Sobel滤波器来实现,Sobel 滤波器是一种卷积滤波器,它可以检测图像强度变化最大的区域。

创建一个名为 `image.py` 的 Python 文件main.py,定义一个图像处理函数,并在其中使用 scikit-image 中的 Sobel 滤波器和其他函数:

import numpy as np
import skimage
from PIL import Image
from PIL.Image import Image as PilImage


def generate_coloring_page(input: PilImage) -> PilImage:
    # Convert to grayscale if needed
    if input.mode != "L":
        input = input.convert("L")
    np_image = np.asarray(input)

    # Detect the edges
    np_image = skimage.filters.sobel(np_image)
    # Convert to 8 bpp
    np_image = skimage.util.img_as_ubyte(np_image)
    # Invert to get dark edges on a light background
    np_image = 255 - np_image
    # Improve the contrast
    np_image = skimage.exposure.rescale_intensity(np_image)

    return Image.fromarray(np_image)
Enter fullscreen mode Exit fullscreen mode

注意:NumPy 和 Pillow 库作为 scikit-image 的依赖项自动安装。

例如,以下是 Cloud Run 徽标在每个步骤中的处理方式:

彩色输入转换为边缘检测灰度输出

✨ Web应用程序

后端

要公开这两个端点(GET /POST /api/coloring-page),请在以下位置添加 Flask 路由main.py

import io

import flask
from PIL import Image

app = flask.Flask(__name__, static_url_path="")


@app.get("/")
def index():
    return app.send_static_file("index.html")


@app.post("/api/coloring-page")
def coloring_page():
    file = flask.request.files.get("input-image")
    if file is None:
        return "Missing input-image parameter", 400

    input_image = Image.open(file.stream)
    output_image = generate_coloring_page(input_image)

    image_io = io.BytesIO()
    output_format = "png"
    output_image.save(image_io, format=output_format)
    image_io.seek(0)

    return flask.send_file(image_io, mimetype=f"image/{output_format}")
Enter fullscreen mode Exit fullscreen mode

前端

在浏览器端,编写一个 JavaScript 函数,调用该/api/coloring-page端点并接收处理后的图像:

async function fetchColoringPage(inputFile) {
    const formData = new FormData()
    formData.append('input-image', inputFile)

    const url = '/api/coloring-page'
    const init = { method: 'POST', body: formData }
    try {
        const response = await fetch(url, init)
        return response.ok ? response.blob() : null
    } catch (error) {
        console.error(error)
        return null
    }
}
Enter fullscreen mode Exit fullscreen mode

你的应用基础已经搭建完成。现在你只需要添加一些 HTML、CSS 和 JS 代码,就能实现你想要的用户体验。

地方发展

要在您的计算机上开发和测试应用程序,在设置好环境后,请确保您拥有所需的依赖项:

pip install --upgrade -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

将以下代码块添加到main.py您的应用程序中。它只会在您手动运行应用程序时执行:

import os

# ...

if __name__ == "__main__":
    os.environ["FLASK_ENV"] = "development"
    app.run(host="localhost", port=8080, debug=True)
Enter fullscreen mode Exit fullscreen mode

运行你的应用:

python main.py
Enter fullscreen mode Exit fullscreen mode

Flask启动本地Web服务器:

 * Serving Flask app 'main' (lazy loading)
 * Environment: development
 * Debug mode: on
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 718-408-327
 * Running on http://localhost:8080/ (Press CTRL+C to quit)
Enter fullscreen mode Exit fullscreen mode

注意:在此模式下,您使用的是开发用 Web 服务器(不适用于生产环境)。接下来,您将配置部署,以便使用 Gunicorn(一款生产级服务器)来运行您的应用程序。

一切就绪。localhost:8080在浏览器中打开,测试、改进、迭代。

🚀 部署

当您的应用准备就绪后,您可以使用名为以下名称的文件中的一行代码来定义它的服务方式Procfile

web: gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app
Enter fullscreen mode Exit fullscreen mode

目前,一个典型的项目中包含以下文件:

.
├── main.py
├── Procfile
├── requirements.txt
└── static
    ├── favicon.ico
    ├── index.html
    ├── scripts.js
    └── styles.css
Enter fullscreen mode Exit fullscreen mode

好了,现在你可以从源代码文件夹部署你的应用了:

SERVICE="coloring-page-generator"
SOURCE="."

gcloud run deploy $SERVICE --source $SOURCE --allow-unauthenticated
Enter fullscreen mode Exit fullscreen mode

⚙️ 引擎盖下

命令行输出详细列出了所有步骤:

This command is equivalent to running `gcloud builds submit --pack image=[IMAGE] SOURCE` and `gcloud run deploy SERVICE --image [IMAGE]`

Building using Buildpacks and deploying container to Cloud Run service [SERVICE] in project [PROJECT_ID] region [REGION]
OK Building and deploying... Done.
  OK Creating Container Repository...
  OK Uploading sources...
  OK Building Container... Logs are available at […].
  OK Creating Revision...
  OK Routing traffic...   
  OK Setting IAM Policy...
Done.
Service [SERVICE] revision [SERVICE-REVISION] has been deployed and is serving 100 percent of traffic.
Service URL: https://SERVICE-PROJECTHASH-REGIONID.a.run.app
Enter fullscreen mode Exit fullscreen mode

Cloud Build 间接用于容器化您的应用。其核心组件之一是 Google Cloud Buildpacks,它可以根据您的源代码自动构建可用于生产环境的容器镜像。以下是主要步骤:

  • Cloud Build会获取源代码。
  • Buildpacks 会自动检测应用程序语言(本例中为 Python),并使用相应的安全基础镜像。
  • Buildpacks 安装应用程序依赖项(requirements.txt在 Python 中定义)。
  • Buildpacks 配置服务入口点(Procfile在 Python 中定义)。
  • Cloud Build 将容器镜像推送到Artifact Registry
  • Cloud Run 会基于此容器镜像创建服务的新版本。
  • Cloud Run 将生产流量路由到它。

笔记:

  • Buildpacks 目前支持以下运行时:Go、Java、.NET、Node.js 和 Python。
  • 基础镜像由 Google 积极维护,定期扫描安全漏洞并修复已知问题。这意味着,当您部署更新时,您的服务将基于尽可能安全的镜像。
  • 如果您需要构建自己的容器镜像,例如使用自定义运行时,您可以添加自己的镜像Dockerfile,Buildpacks 将使用它。

💫 更新

来自真实用户的更多测试表明存在一些问题。

首先,该应用无法处理使用非原生方向拍摄的数码相机照片。您可以使用 EXIF 方向数据来解决此问题:

-from PIL import Image
+from PIL import Image, ImageOps
...
def generate_coloring_page(input: PilImage) -> PilImage:
    # Convert to grayscale if needed
    if input.mode != "L":
        input = input.convert("L")
+   # Transpose if taken in non-native orientation (rotated digital camera)
+   NATIVE_ORIENTATION = 1
+   if input.getexif().get(0x0112, NATIVE_ORIENTATION) != NATIVE_ORIENTATION:
+       input = ImageOps.exif_transpose(input)
    np_image = np.asarray(input)
    ...
Enter fullscreen mode Exit fullscreen mode

此外,该应用对输入图像的细节过于敏感。绘画中的纹理或图片中的噪点会在处理后的图像中产生许多边缘。您可以通过预先添加一个去噪步骤来改进处理算法:

...
def generate_coloring_page(input: PilImage) -> PilImage:
    ...
+   # Remove some noise to keep the most visible edges
+   np_image = skimage.restoration.denoise_tv_chambolle(np_image, weight=0.05)
    # Detect the edges
    np_image = skimage.filters.sobel(np_image)
    ...
Enter fullscreen mode Exit fullscreen mode

这一额外步骤可以使着色页更加干净,并且如果打印出来,还可以减少墨水用量:

波提切利的《维纳斯的诞生》,降噪前后对比

重新部署后,应用程序将自动更新:

gcloud run deploy $SERVICE --source $SOURCE
Enter fullscreen mode Exit fullscreen mode

🎉 它活了

该应用在 Cloud Run 中显示为一项服务:

截屏

服务控制面板可让您概览应用程序使用情况:

截屏

好了,你的图像处理应用程序已经上线了!

动画演示

🤯 它是无服务器的

在这种架构中使用 Cloud Run 有诸多好处:

  • 您的应用全天候24小时可用。
  • 环境完全托管:您可以专注于代码编写,而无需担心基础设施。
  • 您的应用已自动通过HTTPS提供服务。
  • 您可以将您的应用映射到自定义域名。
  • Cloud Run 会自动扩展实例数量,计费仅包含代码运行时使用的资源。
  • 如果您的应用未使用,Cloud Run 将缩减至零。
  • 如果您的应用流量增加(例如,它上了新闻),Cloud Run 会根据需要扩展实例数量。
  • 您可以通过微调许多设置来控制性能和成本:CPU、内存、并发性、最小实例数、最大实例数等等。
  • 每个月,免费套餐提供前 50 个 vCPU 小时、100 GiB 小时和 200 万次请求,无需付费。

💾 源代码

该项目仅包含七个文件和不到 200 行 Python + JavaScript 代码。

您可以将此示例作为基础,构建自己的图像处理应用程序:

🖖 更多

文章来源:https://dev.to/googlecloud/image-processing-as-a-service-8b4