前言
很高兴,收到了一份新款 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=${HOME}/Ascend/thirdpart/${CPU_ARCH} #代码编译时链接第三方库
export PYTHONPATH=${THIRDPART_PATH}/acllite:$PYTHONPATH #设置pythonpath为固定目录
export INSTALL_DIR=${HOME}/Ascend/ascend-toolkit/latest #CANN软件安装后文件存储路径
获取ascend公共文件,并拷贝到第三方依赖文件夹:
cd ${HOME}
git clone https://gitee.com/ascend/samples.git
mkdir -p ${THIRDPART_PATH}
cp -r ${HOME}/samples/common ${THIRDPART_PATH}
然后拷贝 python acllite 库到三方依赖文件夹就行了:
cp -r ${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/<filename>')
def processed_file(filename):
return render_template('result.html', filename=filename)
@app.route('/static/processed/<filename>')
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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Image Cartoonization</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f0f0f0;
margin: 0;
padding: 20px;
}
.container {
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 {
text-align: center;
margin-bottom: 20px;
color: #333;
}
form {
text-align: center;
}
input[type="file"] {
display: none;
}
.custom-file-upload {
border: 1px solid #ccc;
display: inline-block;
padding: 6px 12px;
cursor: pointer;
background-color: #f0f0f0;
color: #333;
border-radius: 4px;
}
.custom-file-upload:hover {
background-color: #e0e0e0;
}
input[type="submit"] {
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 {
background-color: #45a049;
}
</style>
</head>
<body>
<div class="container">
<h1>Upload an Image to Cartoonize</h1>
<form action="/upload" method="post" enctype="multipart/form-data">
<label for="file-upload" class="custom-file-upload">
Choose File
</label>
<input id="file-upload" type="file" name="file">
<input type="submit" value="Upload">
</form>
</div>
</body>
</html>
result.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Processed Image</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f0f0f0;
margin: 0;
padding: 20px;
text-align: center;
}
.container {
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 {
color: #333;
}
img {
max-width: 100%;
height: auto;
margin-top: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
a {
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 {
background-color: #45a049;
}
</style>
</head>
<body>
<div class="container">
<h1>Processed Image</h1>
<img src="{{ url_for('send_processed_file', filename=filename) }}" alt="Processed Image">
<br>
<a href="/">Upload another image</a>
</div>
</body>
</html>
打开浏览器,访问 http://<香橙派IP地址>:5000/
,你应该能看到上传图片的表单。上传图片后,处理后的图片将会展示在结果页面上,并提供返回主页的链接以便上传另一张图片。
注意事项
- 确保
static/uploads
和static/processed
目录存在并且可写。 - 根据实际情况修改模型路径和其他配置。
- 可能需要根据实际情况调整
AclLiteImage
的初始化和使用方法。
使用体验总结
当你收到一款像 OrangePi AIpro 这样强大的开发板时,你不仅仅获得了昇腾系列 AI 处理器的强大性能支持,还拥有了丰富的硬件接口和便捷的开发环境。在使用 OrangePi AIpro 的过程中,我深刻体验到了它为 AI 开发者带来的诸多优势:
- 强大的计算能力:搭载8-12 TOPS的 AI 算力,OrangePi AIpro 让你能够快速处理复杂的 AI 任务。
- 丰富的硬件接口:支持双HDMI输出、千兆网口、Wi-Fi 5 和蓝牙 4.2,以及多种 USB 接口和 Type-C,为你的项目提供了灵活多样的连接方式,适合各种物联网和数据传输需求。
- 完善的昇腾生态:生态系统不仅包括硬件和软件支持,还涵盖了多种工具和资源,极大地丰富了开发者在使用这款开发板时的选择和便利性。特别是昇腾社区的AI案例,给了我这种AI小白很多灵感。
总的来说,这是国产开发板香橙派 OrangePi AIpro 以及国产计算框架 CANN 的应用典范,不仅在性能上有了质的飞跃,而且在使用体验和开发效率上都极大地提升,是两者的巨大进步。唯一的不足可能就是散热问题,也可以说是风扇的问题,风扇调大就会特别响,不过OrangePi AIpro 20T版本好像用到了铜管散热,大大降低了这个问题,希望能兼容一下8T的散热。
非常期待华为昇腾和香橙派后续的继续合作,带来更好的国产AI开发板。国产加油!