昇腾Atlas 200I DK A2 工业视觉实战——从相机采集、PaddleOCR识别到华为云IoTDA物联监护全流程
1 工效组合展示
围绕“视觉感知—智能识别—物联接入—云端部署”全链路展开,涵盖昇腾边缘计算、工业视觉、IoTDA设备接入与CodeArts应用部署。各模块分工协作、并行推进,形成完整闭环。

图1-1 实训各模块综合成果展示(OCR识别、目标检测、IoTDA在线调试等)
2 具身智能工业视觉获取与分析应用
完成昇腾开发板与海康工业相机的环境搭建,实现视觉数据采集与终端识别。主要包括工具安装、视觉环境构建与昇腾终端应用展现三个环节。
2.1 工具软件安装
安装昇腾制卡工具、MobaXterm操控终端与海康MVS客户端等工具软件。通过SSH远程登录Atlas 200I DK A2开发板,配置CANN环境变量与启动脚本,启动JupyterLab服务。

图2-1 实训所需工具软件(Ascend制卡工具、MobaXterm操控终端、海康MVS客户端)

图2-2 海康MVS客户端安装界面与安装选项

图2-3 SSH远程登录Atlas 200I DK A2开发板

图2-4 配置start_notebook.sh启动脚本(加载CANN环境变量)

图2-5 执行启动脚本运行JupyterLab服务

图2-6 JupyterLab启动成功并生成访问链接
2.2 工业视觉环境构建与应用
相机经USB3.0线缆与工控机连接后,先确认系统已正确识别USB3 Vision驱动;再在MVS客户端刷新设备列表,枚举到相机即可连接取景。同时完成光源与昇腾开发板的硬件连线,构成完整的工业视觉成像环境。

图2-7 工业相机USB驱动安装正常(设备管理器)

图2-8 MVS客户端识别工业相机(USB设备列表)

图2-9 昇腾开发板硬件连线示意图
2.3 昇腾工业视觉终端应用展现
通过浏览器访问开发板上的JupyterLab,加载内置视觉样例。选取轻量级的YOLOv5s模型运行目标检测,验证昇腾边缘终端的实时推理能力。

图2-10 JupyterLab样例主页(内置YOLOv5等视觉样例)

图2-11 01-yolov5样例目录(含om模型与测试资源)

图2-12 Atlas 200I DK A2终端YOLOv5目标检测(JupyterLab)
3 具身智能工业视觉识别快速编码实现
基于PaddleOCR开源方案,快速实现工业视觉字符识别功能。通过方案选型、环境构造、编码实现与运行测试四个步骤完成。
3.1 IMA-DS借力
借助PaddleOCR开源方案与现成交付工程,确定识别实现方案。避免从零搭建,显著缩短开发周期。

图3-1 OCR识别技术方案选型与交付文件清单(PaddleOCR开源方案借力)
3.2 运行环境构造
配置Python虚拟环境并安装PaddleOCR、OpenCV等依赖库。完成运行环境验证,确保代码与环境匹配。

图3-2 Python虚拟环境与PaddleOCR环境验证(Windows/PowerShell)
3.3 编码实现
# -*- coding: utf-8 -*-
"""
Camera OCR for Chinese text (PaddleOCR 2.x, Chinese labels on image).
Windows + venv (no conda) + local USB/IP camera.
Keys: SPACE=OCR once | c=auto | z=zoom in | x=zoom out | s=save | q=quit.
"""
import os
os.environ["OMP_NUM_THREADS"] = "4"
import time
import numpy as np
import cv2
from PIL import Image, ImageDraw, ImageFont
CAMERA_SOURCE = 0
OCR_INTERVAL = 2.0
OUTPUT_DIR = "ocr_output"
WINDOW_NAME = "Camera OCR"
os.makedirs(OUTPUT_DIR, exist_ok=True)
ZOOM = 1.0
def get_chinese_font(size=20):
"""Find a Chinese font on Windows."""
candidates = [
"C:/Windows/Fonts/msyh.ttc",
"C:/Windows/Fonts/msyhbd.ttc",
"C:/Windows/Fonts/simhei.ttf",
"C:/Windows/Fonts/simsun.ttc",
]
for path in candidates:
if os.path.exists(path):
return ImageFont.truetype(path, size)
return ImageFont.load_default()
CH_FONT = get_chinese_font(20)
def put_chinese_text(img, text, pos, color=(0, 255, 0), font=CH_FONT):
"""Draw Chinese text on OpenCV image using Pillow."""
img_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
draw = ImageDraw.Draw(img_pil)
draw.text(pos, text, font=font, fill=color)
return cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)
def open_camera(source):
if isinstance(source, str) and source.lower().startswith(("rtsp", "http")):
os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = "rtsp_transport;udp"
cap = cv2.VideoCapture(source)
if not cap.isOpened():
raise RuntimeError(f"Cannot open camera: {source}")
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
return cap
def preprocess(frame):
h, w = frame.shape[:2]
scale = max(1.0, 720.0 / min(h, w))
if scale > 1.0:
frame = cv2.resize(frame, None, fx=scale, fy=scale, interpolation=cv2.INTER_CUBIC)
kernel = np.array([[-1, -1, -1], [-1, 9, -1], [-1, -1, -1]])
frame = cv2.filter2D(frame, -1, kernel)
return frame
def zoom_frame(frame, factor):
if factor <= 1.0:
return frame
h, w = frame.shape[:2]
nh, nw = int(h / factor), int(w / factor)
y1 = (h - nh) // 2
x1 = (w - nw) // 2
return frame[y1:y1 + nh, x1:x1 + nw]
def build_ocr():
from paddleocr import PaddleOCR
ocr = PaddleOCR(use_angle_cls=True, lang="ch", show_log=False)
return ocr
def draw_box(annotated, box, text, score):
if not box:
return
pts = np.array([[int(p[0]), int(p[1])] for p in box], np.int32)
cv2.polylines(annotated, [pts], isClosed=True, color=(0, 255, 0), thickness=2)
if pts.size > 0:
x, y = pts[0]
label = f"{text} {score:.2f}"
annotated[:] = put_chinese_text(annotated, label, (x, max(y - 8, 14)), color=(0, 255, 0))
def ocr_image(ocr, frame):
texts = []
annotated = frame.copy()
try:
result = ocr.ocr(frame, cls=True)
except Exception as e:
print("OCR error:", e)
return annotated, texts
if not result or not result[0]:
return annotated, texts
for line in result[0]:
box, (text, score) = line[0], line[1]
texts.append((text, score))
draw_box(annotated, box, text, score)
return annotated, texts
def main():
global ZOOM
print("Initializing OCR engine. First run downloads models, please wait...")
ocr = build_ocr()
print("OCR engine ready.")
cap = open_camera(CAMERA_SOURCE)
print("Camera opened.")
print("SPACE=OCR once | c=auto | z=zoom in | x=zoom out | s=save | q=quit")
auto_mode = False
last_ocr_time = 0.0
display = None
try:
while True:
ret, frame = cap.read()
if not ret:
print("Frame read failed.")
break
frame_proc = zoom_frame(frame, ZOOM)
frame_ocr = preprocess(frame_proc)
if auto_mode and (time.time() - last_ocr_time) >= OCR_INTERVAL:
display, texts = ocr_image(ocr, frame_ocr)
last_ocr_time = time.time()
if texts:
print("OCR:", " | ".join(t for t, _ in texts))
else:
if display is None:
display = frame_proc
display = display.copy()
cv2.putText(display, f"AUTO: {'ON' if auto_mode else 'OFF'} ZOOM: {ZOOM:.1f}", (10, 20),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2, cv2.LINE_AA)
cv2.imshow(WINDOW_NAME, display)
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
elif key == ord(" "):
annotated, texts = ocr_image(ocr, frame_ocr)
display = annotated
if texts:
print("-" * 40)
for t, s in texts:
print(f"{t} ({s:.2f})")
print("-" * 40)
else:
print("No text found. Try: get closer, more light, press z to zoom.")
elif key == ord("c"):
auto_mode = not auto_mode
display = None
print(f"Auto mode -> {'ON' if auto_mode else 'OFF'}")
elif key == ord("z"):
ZOOM = min(ZOOM + 0.5, 4.0)
display = None
print(f"Zoom -> {ZOOM}")
elif key == ord("x"):
ZOOM = max(ZOOM - 0.5, 1.0)
display = None
print(f"Zoom -> {ZOOM}")
elif key == ord("s"):
path = os.path.join(OUTPUT_DIR,
f"shot_{time.strftime('%Y%m%d_%H%M%S')}.jpg")
cv2.imwrite(path, frame)
print(f"Screenshot saved: {path}")
finally:
cap.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
3.4 运行测试
使用海康工业相机进行实测,正确识别出目标文字。验证了快速编码实现路线的可行性。

图3-8 海康工业相机OCR运行测试(识别“纯悦 550ml”)
4 IoTDA中转空间构建
构建设备接入中转空间,完成产品模型定义与设备实例化。实现温湿度计与吸顶灯两类设备的接入与双向通信。
4.0 IoTDA构造
开通设备接入IoTDA服务并创建myIoTDA实例。作为设备与业务应用之间的中转空间,支撑海量设备接入。

图4-1 IoTDA实例(myIoTDA)创建完成并运行中
4.1 产品及其模型构建
完成云账号凭证准备与产品创建。分别定义温湿度计与吸顶灯的产品模型。

图4-2 华为云账号API凭证查看(IAM用户与项目列表)

图4-3 IoTDA实例(myIoTDA)与产品创建
4.1.1 温湿度计
定义T&H服务,包含温度、湿度两个属性。用于温湿度数据的上报。

图4-4 添加服务与新增属性(T&H:temperature/Humidity)
4.1.2 吸顶灯
定义Light服务与Color服务,包含属性与命令。支持状态上报与开关、调光等控制命令下发。

图4-5 吸顶灯产品模型定义(Light服务+Color服务)
4.2 设备实例化应用
在对应产品下注册具体设备,完成设备实例化。生成设备身份三元组,用于MQTT接入鉴权。
4.2.1 温湿度计设备注册及模拟测试
通过MQTT连接平台并上报温湿度数据。平台侧实时显示上报结果,验证数据上报链路。

图4-6 温湿度计设备MQTT连接配置(MQTT.fx)

图4-7 温湿度计属性上报数据(temperature/Humidity)
4.2.2 吸顶灯设备注册及模拟测试
完成设备连接、属性上报与命令下发调试。验证了双向通信与远程控制能力。

图4-8 吸顶灯设备MQTT连接配置(MQTT.fx)

图4-9 吸顶灯属性上报消息跟踪(properties/report)

图4-10 吸顶灯设备详情(luminance/power/color)

图4-11 吸顶灯命令下发在线调试(Light/Color)
5 CodeArts智慧路灯快速构建与部署
完成智慧路灯应用的构建、部署与运行验证。覆盖项目管理、代码托管、编译构建与部署全流程。
5.1 应用项目创建
在CodeArts项目管理中创建Scrum项目。作为后续开发与部署的统一载体。

图5-1 创建Scrum项目(mySmartLightCZD)
5.2 代码托管操作
创建代码仓库并托管智慧路灯源码。实现代码的云端版本管理。

图5-2 按模板新建代码仓库(选择IoT_Streetlight_Demo模板)

图5-3 代码仓库Master创建成功
5.3 构建任务设立
新建编译构建任务并配置Maven构建。设置软件包归档路径,为自动化构建做准备。

图5-4 新建任务(代码源选择Repo)

图5-5 新建编译构建任务(基本信息)

图5-6 选择Maven构建模板

图5-7 Maven构建步骤配置并保存执行
5.4 项目构建实现
执行构建任务并下载软件包。验证代码可正常编译并产出可部署制品。

图5-8 构建执行成功并下载软件包(huawei-0.0.1-SNAPSHOT.jar)
5.5 项目部署运行
配置Java环境并启动智慧路灯应用。实现从构建到部署运行的完整交付闭环。

图5-9 配置Java环境变量(Path添加java\bin)

图5-10 验证Java运行环境(java -version)

图5-11 运行智慧路灯应用(java -jar启动Spring Boot)
鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐


所有评论(0)