banner
月落星河Tsukistar

月落星河Tsukistar

浩瀚中的伟大,孤独间的渺小
github
twitter
youtube
bilibili
email

serverless环境下动态调整图像大小的系统的设计与实现

最近毕业设计选题,基于我之前做过的项目和图像处理有关,serverless 也是最近几年开始流行的一种服务,于是选择这个题目,从零开始研究 serverless。(后记:出题老师后来想了想我这个的工作量太小了,所以把题目扩充了许多,现在要去研究证件识别和处理之类的了 QwQ)

参考文章:【AWS 征文】使用 AWS Serverless 架构动态调整图片大小

开发环境#

Python 3.6(腾讯云对于 Python 3 目前只支持这个版本),腾讯云 SCF

步骤#

配置环境#

在腾讯云的 “Serverless Framework” 中新建一个 Flask 框架,名称和地域随便填,如下图:

新建框架

部署完成后在 “开发部署” 中点击 “更新代码”:

更新代码

随后选择本地开发将项目下载下来:

下载代码

(其实更便捷的地方在 “云函数 - 函数服务 - 选择新建的那个函数 - 函数代码” 处修改代码或者新增文件,可以保证环境的一致性,但是上面的方法便于本机调试与修改,各有利弊)

云函数在线修改

至此,基本框架已经搭好了。

功能开发#

目前函数能够处理并返回的图片存放于我的云存储,主要是便于调用和预留参数。利用 Flask app 的固有格式,预留了 screen_width(屏幕宽度)和 pic_url(图片路径)两个参数。
在调用时,指定屏幕宽度则返回对应宽度等比缩放的图片:

等比缩放

不指定则返回原图:

原图

在 Flask 部分代码如下:

@app.route("/pic/<pic_url>")
def source_picture(pic_url):
    img_src = "存储空间地址" + pic_url
    # 相当于把一张图片读入再读出,图片大小会变得小一些
    response = make_response(picture.image_output(picture.image_input(img_src)))
    # 设置response的headers对象
    response.headers['Content-Type'] = 'image/jpeg'
    return response


@app.route("/pic/<screen_width>/<pic_url>")
def picture_url_get(screen_width, pic_url):
    # 避免数据类型错误
    width = int(screen_width)
    img_src = "存储空间地址" + pic_url
    # 创建response对象
    response = make_response(picture.image_output(picture.image_resize(width, img_src)))
    # 设置response的headers对象
    response.headers['Content-Type'] = 'image/jpeg'
    return response

主要使用了 make_response 来创建 response 对象包装图片,并返回到浏览器,避免先存储再访问存储好的图片。

对于图片处理部分:

image_input 函数使用 requests 从 URL 获取图片,封装成 response 对象,随后用 PIL 的 Image 库打开,注意 response 对象要用 BytesIO 处理:

def image_input(img_src):
    response = requests.get(img_src, headers=headers)
    image = Image.open(BytesIO(response.content))
    return image

image_output 函数使用 BytesIO 将图片转换为字节流,保存后返回:

def image_output(image):
    img_byte = BytesIO()
    image.save(img_byte, format="JPEG")
    img_byte = img_byte.getvalue()
    return img_byte

image_resize 函数使用了 Image 里的 resize 方法,将图片进行等比缩放,其中 Image.ANTIALIAS 是高清晰度的参数:

def image_resize(width, img_src):
    image = image_input(img_src)
    resize = image.resize((width, int(image.size[1] * width / image.size[0])), Image.ANTIALIAS)
    return resize

遇到的问题与解决方案#

npm 安装时遇到 rollbackFailedOptional: verb npm-session 问题#

使用npm install -g cnpm --registry=https://registry.npm.taobao.org命令,用淘宝源替换官方源,随后使用 cnpm 进行安装。

安装相应第三方库报错#

可以使用阿里镜像:https://mirrors.aliyun.com/pypi/simple/ ,同时serverless.yml文件中 pip 的相关代码改为hook: pip install -i https://mirrors.aliyun.com/pypi/simple/ -r requirements.txt -t ./

Pillow 的 import 错误#

原因为本地环境与云端环境不一致,即使均为 Python 3.6.0 版本,Windows 上与 Linux 上的第三方库也有细微的不同。解决方法为将代码上传后,在云端执行pip install -i https://mirrors.aliyun.com/pypi/simple/ -r requirements.txt -t ./下载依赖。

总结#

整个流程下来自己大致摸清了部署 serverless 服务的步骤,同时也意识到由于 serverless 的依赖都是随着代码附带的,若开发和部署不是同一个操作系统,建议在代码上传后于云环境中进行部署,以免发生运行时的错误。

图片大小的改变只是其中的一个小应用,理论上来讲许多应用都可以在 serverless 环境下运行并得出结果,例如短链接、图像识别、文字识别等等,未来 serverless 的应用会愈发广泛。

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。