OrangePi AIpro 浅上手及搭建卡通图像生成多元化AI服务
前言
很高兴,收到了一份新款 OrangePi AIpro 开发板,这是香橙派第一次与华为昇腾合作,使用昇腾系列 AI 处理器来设计这款高性价比的 AI 开发板。这块开发板不仅性能强大,还支持丰富的硬件接口,为AI开发者提供了一个理想的实验平台。作为一名会点AI的软件工程师,我迫不及待地想要尝试这款设备,将其应用到实际项目中。*^____^*
OrangePi AIpro 开发板简介
OrangePi AIpro 拥有8-12 TOPS(每秒万亿次操作)的AI算力,就像你拥有了一台超级计算机,可以快速处理各种复杂的AI任务,比如识别图像、分析视频等。无论是开发智能家居、智能安防,这款开发板都能轻松胜任。其次, AIpro 还配备了8GB或16GB的高速内存,这意味着你可以运行更多、更复杂的AI应用程序,体验流畅的性能。即使是较大规模的数据处理和深度学习模型训练,这款开发板也能轻松应对,毫不费力。
此外,OrangePi AIpro 提供了许多便捷的接口,支持双HDMI输出,能够连接两个4K高清显示屏,带来更广阔的视觉体验;千兆网口保证你在大数据传输和实时联网应用中享有快速、稳定的网络连接;Wi-Fi 5和蓝牙4.2让你可以随时随地进行无线连接,非常适合物联网项目;多种USB接口和Type-C支持高速数据传输,连接外部设备更加方便;M.2插槽支持大容量SSD硬盘,为你提供更多存储空间,存储和读取数据速度更快。
远程连接及相关设置
这次收到的 OrangePi AIpro 开发板带了一张TF卡,内置了官方的 Ubuntu 系统,省去了很多烧录带来的麻烦,所以烧录这部分就略过了,如果大家对烧录系统到 TF 卡以及烧录到 SATA SSD 的过程,可以参考我的这篇博客。
OrangePi Ai Pro 开箱及镜像烧录指南-CSDN博客
第一次使用开发板,链接wifi到开发板是我使用开发板必不可少的操作,这样就可以使用 SSH、VNC 等工具来对开发板进行操作,省去了每次使用时需要链接开发板到显示器的步骤。
至于连接工具,官方是有提供 MobaXterm 安装包的,但我更习惯使用 XShell,这里就使用 XShell 进行连接。配置好我们的 SSH 连接信息,点击连接即可进行连接。
为了避免算力恐慌的问题,这里我们刷入官方的“超频”固件,据说这款固件是从CANN软件层面进行优化,将我们的 OrangePi AIpro 开发板从8T的算力优化到了8~12T的算力,但是能不能到12T似乎是个随机数,不同的板子的上限貌似不同 (*^____^*)。
使用 Xftp 将最新的固件文件 Ascend310B-firmware-7.3.t10.0.b528-rc-signed-opiaipro-12t-1.6ghz-20240605.run 传输到我们的开发板上,然后对固件进行升级。
# 给固件权限 chmod +x Ascend310B-firmware-7.3.t10.0.b528-rc-signed-opiaipro-12t-1.6ghz-20240605.run # 运行固件 ./Ascend310B-firmware-7.3.t10.0.b528-rc-signed-opiaipro-12t-1.6ghz-20240605.run --full
升级后断电重启即可体验到8~12T的算力啦!
开放 JupyterLab 端口
为了更为方便的在我的电脑上使用 OrangePi AIpro 的环境来调试 AI 模型,这里配置并开放 JupyterLab 的访问端口,从而使得我的电脑可以访问到 OPI AIpro 的 JupyterLab。(如果你想得到一个可以随时使用 OrangePi AIpro 算力的 JupyterLab,完全可以向我一样,打开 JupyterLab 的端口,然后搭配内网穿透服务,风扇开到最大,这样就可以得到一个带有算力资源且随时可以敲代码的网页服务。)
安装防火墙
首先,我们需要确保系统的安全性。防火墙是保护系统免受未经授权访问的重要工具。我们需要先安装防火墙:
sudo apt install firewalld
启动防火墙并开放端口
安装完成后,我们需要启动防火墙并确保它在每次系统启动时自动运行。同时,为了方便后续访问 Jupyter Notebook,我们还需要开放 8888 端口。以下是具体步骤:
# 切换到 root 用户 su root # 启动防火墙并设置开机自启 sudo systemctl start firewalld sudo systemctl enable firewalld # 开放 8888 端口,允许通过该端口进行访问 firewall-cmd --add-port=8888/tcp --permanent # 重新加载防火墙配置 sudo firewall-cmd --reload
通过这些步骤,我们已经成功启动了防火墙,并开放了 8888 端口,为我们通过浏览器访问 Jupyter Notebook 提供了便利。
创建启动 Jupyter Notebook 的脚本
为了更加方便地启动 Jupyter Notebook,我们可以创建一个启动脚本,从而简化启动过程,还可以自动设置环境变量,确保 Jupyter Notebook 能够正常运行。以下是脚本的具体内容:
. /usr/local/Ascend/ascend-toolkit/set_env.sh export PYTHONPATH=/usr/local/Ascend/thirdpart/aarch64/acllite:$PYTHONPATH if [ $# -eq 1 ]; then jupyter lab --ip $1 --port 8888 --allow-root --no-browser else jupyter lab --ip 0.0.0.0 --port 8888 --allow-root --no-browser fi
将以上内容保存为 start_notebook_all_ports.sh 文件。
赋予脚本运行权限
为了使脚本能够执行,我们需要赋予它运行权限:
chmod +x start_notebook_all_ports.sh
运行脚本
现在,我们可以运行这个脚本来启动 Jupyter Notebook:
./start_notebook_all_ports.sh
运行这个脚本后,你可以在浏览器中通过开发板的 IP 地址和 8888 端口访问 Jupyter Notebook。例如,如果开发板的 IP 地址是 192.168.1.100,那么你可以在浏览器中输入 http://192.168.1.100:8888 来访问,我这里是 192.168.8.131。
获取 Jupyter Notebook Token
为了确保 Jupyter Notebook 的安全性,每次启动时都会生成一个访问令牌(Token)。我们可以通过以下命令来获取这个令牌:
jupyter server list
将输出中的 Token 复制到浏览器中,即可成功登录 Jupyter Lab。
成功打开 Jupyter Lab
成功打开 Jupyter Lab 后,你可以开始在 OrangePi AIpro 开发板上进行 AI 项目的开发与实验。这款开发板的强大性能和丰富接口将大大提升你的开发效率和体验。
通过以上步骤,我们就可以随时可以在 OrangePi AIpro 开发板上进行 AI 开发和实验。
搭建卡通图像生成服务
安装 python-aclite 等依赖包
打开 ~/.bashrc 并在最后添加下面内容,并 source ~/.bashrc 使其生效:
export CPU_ARCH=`arch` export THIRDPART_PATH=$https://blog.csdn.net/qq_21484461/article/details/{HOME}/Ascend/thirdpart/${CPU_ARCH} #代码编译时链接第三方库 export PYTHONPATH=${THIRDPART_PATH}/acllite:$PYTHONPATH #设置pythonpath为固定目录 export INSTALL_DIR=$https://blog.csdn.net/qq_21484461/article/details/{HOME}/Ascend/ascend-toolkit/latest #CANN软件安装后文件存储路径
获取ascend公共文件,并拷贝到第三方依赖文件夹:
cd $https://blog.csdn.net/qq_21484461/article/details/{HOME} git clone https://gitee.com/ascend/samples.git mkdir -p ${THIRDPART_PATH} cp -r $https://blog.csdn.net/qq_21484461/article/details/{HOME}/samples/common ${THIRDPART_PATH}
然后拷贝 python acllite 库到三方依赖文件夹就行了:
cp -r $https://blog.csdn.net/qq_21484461/article/details/{HOME}/samples/python/common/acllite ${THIRDPART_PATH}
体验图片卡通化AI
打开JupyterLab,按照操作手册找到 demo5,找到 main.ipynb 文件,并点击上面的 restart 双箭头,然后样例就开始运行了。
运行后,我们就可以看到卡通化后的图片了。
打造图片卡通化 AI 服务器
但我们想要的不仅仅于此。我想将其打造成网页服务器或者API,这样配合内网穿透服务,我们就可以随时使用我们的 OrangePi AIpro 中所含有的 AI 服务啦!这里我主要使用 flask 来构建一个 OrangePi AIpro 图片卡通化的网页服务。下面是简单实现步骤和代码实现:
为了在上传图片后显示处理后的结果,我们需要在上传和处理图片后,将处理后的图片路径传递给模板,并在模板中显示该图片。
下面是完整的实现步骤:
1. 创建 Flask 应用
创建一个新的目录,例如 cartoonization_app,并在其中创建以下文件:
- app.py: 主 Flask 应用文件。
- templates/: 目录,存放 HTML 模板。
- static/: 目录,存放生成的图片。
2. 编写 app.py
在 app.py 中编写 Flask 应用:
import os import sys import numpy as np import cv2 from flask import Flask, request, render_template, send_from_directory, redirect, url_for # 添加模型路径 path = os.path.dirname(os.path.abspath(__file__)) sys.path.append(os.path.join(path, "..")) sys.path.append(os.path.join(path, "../../../common/acllite/")) import acl import acllite_utils as utils import constants as const from acllite_imageproc import AclLiteImageProc from acllite_model import AclLiteModel from acllite_image import AclLiteImage from acllite_resource import AclLiteResource app = Flask(__name__) app.config['UPLOAD_FOLDER'] = 'static/uploads' app.config['PROCESSED_FOLDER'] = 'static/processed' os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) os.makedirs(app.config['PROCESSED_FOLDER'], exist_ok=True) class Cartoonization(object): def __init__(self, model_path, model_width, model_height): self._model_path = model_path self._model_width = model_width self._model_height = model_height self.device_id = 0 self._dvpp = None self._model = None def init(self): self._dvpp = AclLiteImageProc() self._model = AclLiteModel(self._model_path) return const.SUCCESS @utils.display_time def pre_process(self, image): image_dvpp = image.copy_to_dvpp() yuv_image = self._dvpp.jpegd(image_dvpp) crop_and_paste_image = self._dvpp.crop_and_paste_get_roi(yuv_image, image.width, image.height, \ self._model_width, self._model_height) return crop_and_paste_image @utils.display_time def inference(self, resized_image): return self._model.execute(resized_image) @utils.display_time def post_process(self, infer_output, origin_image): data = ((np.squeeze(infer_output[0]) + 1) * 127.5) img = cv2.cvtColor(data, cv2.COLOR_RGB2BGR) img = cv2.resize(img, (origin_image.width, origin_image.height)) return img # 初始化Cartoonization对象 currentPath = os.path.join(path, "..") MODEL_PATH = os.path.join(currentPath, "model/cartoonization.om") MODEL_WIDTH = 256 MODEL_HEIGHT = 256 acl_resource = AclLiteResource() acl_resource.init() cartoonization = Cartoonization(MODEL_PATH, MODEL_WIDTH, MODEL_HEIGHT) ret = cartoonization.init() utils.check_ret("Cartoonization.init ", ret) @app.route('/') def index(): return render_template('index.html') @app.route('/upload', methods=['POST']) def upload_file(): if 'file' not in request.files: return 'No file part' file = request.files['file'] if file.filename == '': return 'No selected file' if file: filename = os.path.join(app.config['UPLOAD_FOLDER'], file.filename) file.save(filename) # 处理图片 image = AclLiteImage(filename) crop_and_paste_image = cartoonization.pre_process(image) result = cartoonization.inference([crop_and_paste_image]) processed_image = cartoonization.post_process(result, image) # 保存处理后的图片 processed_filename = os.path.join(app.config['PROCESSED_FOLDER'], file.filename) cv2.imwrite(processed_filename, processed_image) return redirect(url_for('processed_file', filename=file.filename)) @app.route('/processed/') def processed_file(filename): return render_template('result.html', filename=filename) @app.route('/static/processed/') def send_processed_file(filename): return send_from_directory(app.config['PROCESSED_FOLDER'], filename) if __name__ == '__main__': app.run(debug=True, host="0.0.0.0", port=5000)
3. 创建模板
在 templates 目录下创建两个 HTML 文件:
index.html
Image Cartoonization body https://blog.csdn.net/qq_21484461/article/details/{ font-family: Arial, sans-serif; background-color: #f0f0f0; margin: 0; padding: 20px; } .container https://blog.csdn.net/qq_21484461/article/details/{ max-width: 600px; margin: 0 auto; background-color: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0,0,0,0.1); } h1 https://blog.csdn.net/qq_21484461/article/details/{ text-align: center; margin-bottom: 20px; color: #333; } form https://blog.csdn.net/qq_21484461/article/details/{ text-align: center; } input[type="file"] https://blog.csdn.net/qq_21484461/article/details/{ display: none; } .custom-file-upload https://blog.csdn.net/qq_21484461/article/details/{ border: 1px solid #ccc; display: inline-block; padding: 6px 12px; cursor: pointer; background-color: #f0f0f0; color: #333; border-radius: 4px; } .custom-file-upload:hover https://blog.csdn.net/qq_21484461/article/details/{ background-color: #e0e0e0; } input[type="submit"] https://blog.csdn.net/qq_21484461/article/details/{ margin-top: 10px; background-color: #4CAF50; color: white; border: none; padding: 10px 20px; text-align: center; text-decoration: none; display: inline-block; font-size: 16px; cursor: pointer; border-radius: 4px; } input[type="submit"]:hover https://blog.csdn.net/qq_21484461/article/details/{ background-color: #45a049; }
Upload an Image to Cartoonize
Choose Fileresult.html
Processed Image body https://blog.csdn.net/qq_21484461/article/details/{ font-family: Arial, sans-serif; background-color: #f0f0f0; margin: 0; padding: 20px; text-align: center; } .container https://blog.csdn.net/qq_21484461/article/details/{ max-width: 800px; margin: 0 auto; background-color: #fff; padding: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0,0,0,0.1); } h1 https://blog.csdn.net/qq_21484461/article/details/{ color: #333; } img https://blog.csdn.net/qq_21484461/article/details/{ max-width: 100%; height: auto; margin-top: 20px; border-radius: 8px; box-shadow: 0 0 10px rgba(0,0,0,0.1); } a https://blog.csdn.net/qq_21484461/article/details/{ display: inline-block; margin-top: 20px; padding: 10px 20px; background-color: #4CAF50; color: white; text-decoration: none; border-radius: 4px; transition: background-color 0.3s ease; } a:hover https://blog.csdn.net/qq_21484461/article/details/{ background-color: #45a049; }
Processed Image