赞
踩
背景:要求封装一个图片上色的api接口,接口的输入为一张黑白图,返回的结果是一张对灰度图片进行染色后的图片
现在很多开源项目可能都只针对linux系统做了适配,但是对于大多数时候都只有一台windows笔记本 or 比较依赖windows环境的学习者来说,使用wsl2 在windows上搭建一个ubuntu 系统就可以以屁眼插火箭的速度提升了部署效率,大大节省了配置环境的时间成本!
本博客用以记录封装 api 的整个流程。
使用工具:
首先就是在windows上安装ubuntu啦,其实整个过程还是比较容易的,网上教程很多,不做赘述。
安装完成之后就可以从 cmd 中使用ubuntu了,界面如下:
值得一提的是,wsl 相较于原生ubuntu有个天然优势,就是在wsl下依旧可以访问windows下的目录,可以使用linux的操作逻辑去管理windows下的文件,非常方便。相较于把文件上传到服务器,再用ssh去连接服务器只能突出一个丝滑和优雅 :)
共享文件夹的path为:/mnt (可以看到目录下的C D E盘)
===============================================================================================
这一部分主要是为了聊docker,如果无兴趣且环境已经解决(例如本机conda有torch)可直接跳到本机部署部分
===============================================================================================
首先是安装docker,其实之前写过一个和安装docker相关的博客,在这里()。不过由于之前初学理解不深,且步骤不全、不够简化。现在重新对 docker安装 进行阐述:
1.首先是更新库(这一步如果之前更新过库的话,这一步可以跳过)
sudo apt-get update
2.卸载旧版本docker(如果之前没装过,这一步也可以跳过)
sudo apt-get remove docker docker-engine docker.io
3.安装docker(可能截止到目前为止最有用的一步,笑死)
sudo apt install docker.io
其实到这一步就已经安装完docker了,对,就已经可以正常使用了。。。。(为什么之前官方那个那么复杂,所以这才是官方鸭 hhhh)
为了每次服务器(主机)关机重启后能自动运行docker,而不是手动去让docker运行,那么可以将docker设置为开机自启(没错,就是微信默认设置的那玩意==)
命令如下:
4.设置自启
sudo systemctl start docker
sudo systemctl enable docker
可以输入 docker --version
查看是否安装成功
docker安装完之后,有时候会出现用不了gpu的情况,例如你明明拉的是cuda版本的torch,但是就是用不了cuda,那是为啥呢,其实很有可能是因为你没有安装nvidia-docker,安装步骤也很简单,如下:
1.老步骤,首先更新库,然后安装nvidia-docker2包,指令如下:
sudo apt-get update
sudo apt-get install -y nvidia-docker2
2.重启docker
sudo systemctl restart docker
3.可以测试下:
sudo docker run --rm --gpus all nvidia/cuda:11.0-base nvidia-smi
如果返回显卡信息,就说明安装成功啦!
至此,docker 安装完毕。
完成docker安装后,下一步就是去拉取pytorch镜像。步骤很简单,就是先去下载一个镜像,然后把镜像转成一个容器
1.拉取镜像
docker pull pytorch/pytorch:2.1.0-cuda11.8-cudnn8-devel
这个是从docker hub获得的,网址如下:https://hub.docker.com/r/pytorch/pytorch/tags。解释下,docker pull 是拉取指令,后面的是具体版本,指的是pytorch2.1.0 版本,cuda是11.8,cudnn为8。
devel是版本,版本还有一种是runtime,大概意思就是devel版本中的库更全,而runtime只包含基本库,类比conda和miniconda,不过空间够的话就拉devel版本吧,有的包好像还包含base版本,反正都是库全不全的区别!(目前理解,很有可能不对哈哈哈哈哈)
2.构建容器
详细命令如下:
docker run -it --gpus all -v [本地路径]:[容器内部路径] --name [容器名字] -p [本地端口]:[容器端口] [镜像名]:[镜像tag] /bin/bash
详细说明下:
后面不谈了。假设针对我的镜像:
我创建容器的指令就应该是:
docker run -it --gpus all -v /mnt/e/colorize/code:/workspace --name colorize -p 8000:8000 pytorch/pytorch:2.1.0-cuda11.8-cudnn8-devel /bin/bash
ok ,这样你应该就进入容器了,然后ctrl + p + q 可以返回宿主机。docker exec -it [容器ID] /bin/bash
又可以重新进入容器。
至此,容器部分结束!
之后在容器中运行 pip install requirements.txt -i https://mirrors.aliyun.com/pypi/simple
环境部分其实就解决了。
但是,docker还没有结束!这次部署学了更多新东西,想一并记录,不仅希望有助于提升下次工作效率,更希望能帮到其它有需要的朋友!
首先,是docker容器打包,其实之前一直有个疑问,就是 conda 完全能解决环境的问题了,大不了就是多花点时间,那为什么还要花那么多的时间去搭建docker容器呢,其实docker容器有几个天然优势,就是容器可以离线打包成压缩文件,这个文件包含了所有的环境,用户只需要获得你的tar压缩文件,对文件进行解压,获取镜像,然后这个镜像构建的容器就可以直接运行项目了,全程可离线,不会有任何库相关的问题(如果容器打包完整的话),真正的即插即用!
打包的具体步骤如下:
1.提交容器为镜像
docker commit container_name your_new_image_name
container_name
是容器的名称或 ID,your_new_image_name
是新创建的镜像指定的名称。这个命令会将容器的当前状态(包括所有更改)保存为一个新的镜像。
2.保存镜像为 tar 文件
创建新镜像后,可以使用 docker save
命令将其保存为一个 tar 文件:
docker save your_new_image_name > your_new_image_name.tar
也可以使用下述指令指定打包路径:
docker save -o /your/path/new_image_name.tar new_image_name
这样就完成了打包的操作!
3.其他地方加载 tar 文件为镜像
在一台新的机器上,可使用下述命令,将打包好的镜像解压出来以便使用!
docker load -i your_new_image_name.tar
至此,打包和解压步骤全部结束!
(另外因为pip打包之前都出问题,这里一并将可用的方法进行阐述)
首先进入conda环境
pip freeze > requirements.txt
部署项目,进入 github 主页,将项目下载到本地 == over
首先是需要安装fastapi,安装指令如下:
pip install "fastapi[all]"
因为本项目仅仅只考虑上传文件部分,因此不考虑其它接口的构建形式,官网可看详情
from typing import Annotated
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(file: Annotated[bytes, File()]):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
return {"filename": file.filename}
这里就构建了两种post可访问的路由(地址)-- files 和 uploadfile,
构建完之后首先运行一次该文件,假设文件名为main.py,运行指令为:
uvicorn main:app --host 0.0.0.0 --port 8000
这里就是将服务绑定到端口8000,设置主机为0.0.0.0,之所以设置为0.0.0.0是为了所有的连接都能够访问,不管是局域网还是宿主机都可以,默认一般设置为 127.0.0.1,就会导致只有本机可以使用了,其他的机器都用不了这个服务!
运行成功后截图如下
此外,为了避免每次运行服务都需要额外的输入指令,可以设置一个函数,用于运行后直接启动。结合本项目,main.py文件的内容为:
from colorization_pipline import ImageColorizationPipeline from fastapi.responses import StreamingResponse from fastapi import FastAPI, File, UploadFile from typing import Union import numpy as np import cv2 import io model_path = 'modelscope/damo/cv_ddcolor_image-colorization/pytorch_model.pt' #模型权重 colorizer = ImageColorizationPipeline(model_path=model_path) app = FastAPI() @app.post("/api/photo_process/colorize") async def create_upload_file(file: Union[UploadFile, None] = None): contents = await file.read() #读取输入的内容 nparr = np.fromstring(contents, np.uint8) image = cv2.imdecode(nparr, cv2.IMREAD_COLOR) #解码获取到的图片输入 color_image = colorizer.process(image) #上色函数 # 将处理后的图像编码为JPEG格式 _, encoded_image = cv2.imencode('.jpg', color_image) encoded_image_bytes = encoded_image.tobytes() # 创建一个字节流以便发送 stream = io.BytesIO(encoded_image_bytes) # 返回图像 return StreamingResponse(stream, media_type="image/jpeg") if __name__=="__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)
这个是结合本项目背景进行修改后的main文件。至此,接口封装完毕!
可以使用postman去测试端口是否可以使用
输入及postman测试输出样例如下:
首先是人物图片测试:
其次是动漫场景测试:
最后是大场景测试:
至此,测试完毕!
首先,如果服务本地使用postman 访问localhost可以,但是其他机器或者使用其他ip不可以,那极有可能是因为防火墙问题。
解决方法就是新建出站规则和入站规则,具体如下:
选择 控制面板 -> 系统与安全 -> windows defender 防火墙 -> 高级设置
选择新建入站规则
选择端口 —> 将开放的端口填入(本实验为8000)
然后一直下一步,取个名字就可以了!
之后在出站规则中重复一次上述步骤。
至此,防火墙设置完毕!
原因是因为wsl2 会呈现出一个单独的机器,会有自己的一个独立的IP,但是由于依然只有宿主机的网卡,因此外部链接访问的话依然只能访问物理机,所以要先将请求转发到wsl2上,之后才能检测到该请求!
使用下述指令可以将访问宿主机 ip 的请求转发至 wsl 对应的地址
netsh interface portproxy add v4tov4 listenaddress=0.0.0.0 listenport=8000 connectaddress=WSL的IP地址 connectport=8000
至此,部署完成!
环境:
docker包 后续发布到docker hub上,工程文件后续发布到github上
硬件环境(可根据实际调整,要求较低)
参考资料:
https://github.com/piddnad/DDColor(阿里团队的达摩院开发,在目前测试过的与colorize相关的project中取得了SOTA的结果)
https://fastapi.tiangolo.com/
https://www.zhihu.com/question/484035804/answer/3218940256
https://zhuanlan.zhihu.com/p/361934132
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。