1 工效组合展示

本次实训围绕“具身智能工业视觉分析与物联监护应用”展开,利用昇腾开发板、网络摄像机与华为云物联网平台等软硬件资源,依次完成工业视觉获取与分析、中文 OCR 快速编码、IoTDA 设备接入监护以及 CodeArts 智慧路灯应用的构建部署,形成“感知—分析—监护—应用”的完整实训链路。

实训工效组合如下:开发终端采用 MobaXterm 作为远程操作终端,海康 MVS 作为机器视觉客户端工具,Ascend-devkit-imager 提供昇腾系统终端支持;昇腾开发板通过 Jupyter 运行工业视觉示例,实时展现人员、手机等目标的检测识别效果。

通过上述工具组合,实现边缘侧视觉采集分析、应用侧快速编码、云端侧物联监护与部署的一体化协同作业,为工业视觉与物联网融合应用演练奠定基础。

2 具身智能工业视觉获取与分析应用

2.1 工具软件安装

本次实训所需工具软件如下:MobaXterm_Portable_v22.2(远程操作终端,用于 SSH 连接昇腾开发板);MVS_STD_4.3.2_240705(海康机器视觉 VM 客户端工具,用于工业相机连接与视觉调试);Ascend-devkit-imager_latest_win-x86(昇腾系统终端,用于开发板系统镜像制作与终端管理)。将上述工具软件安装或解压到本地后,逐一验证其可正常启动。

完成工具安装后,配置开发主机与昇腾开发板之间的网络:在“设备管理器—网络适配器”中确认 USB RNDIS6 适配器已正确识别;进入“网络和 Internet→更改适配器选项”,打开该适配器属性,在“Internet 协议版本 4 (TCP/IPv4)”中手动设置 IP 地址为 192.168.137.1、子网掩码为 255.255.255.0,使主机与开发板处于同一网段,为后续 SSH 远程登录与视觉数据交互提供网络基础。

2.2 工业视觉环境构建与应用

打开 MobaXterm,新建 SSH 会话,远程主机填写 192.168.131.100、用户名 root、端口 22,点击 OK 建立连接;首次连接时接受主机密钥并输入登录密码。连接成功后进入昇腾开发板系统(Atlas 200 DK),系统基于 Ubuntu 22.04.5 LTS,终端显示 Ascend-devkit 欢迎信息及软件许可协议提示,工业视觉运行环境构建完成,后续即可在开发板上部署和运行工业视觉应用。

2.3 昇腾工业视觉终端应用展现

在昇腾开发板终端启动工业视觉示例应用(Jupyter Notebook 服务),通过浏览器访问开发板提供的 Jupyter 页面运行目标检测示例。画面中,人员、手机等目标被绿色检测框实时标注,并显示类别与置信度(如 person 0.89、cell phone 0.89 等),验证昇腾工业视觉终端在边缘侧具备实时目标检测与识别展现能力。

3 具身智能工业视觉识别快速编码实现

3.1 IMA-DS借力

给出关于python虚拟环境OCR文字识别的编码及其运行过程,包括汉字,windows环境,非COnDA,使用本机连接的网络摄像机 使用windowsCPU,

本次编码任务借助 IMA-DS 快速编码思路,在 Windows 非 Conda 的 Python 虚拟环境中,使用本机连接的网络摄像机、基于 Windows CPU 完成包含汉字的中文 OCR 文字识别。运行过程分为四步:

(1)建立虚拟环境(非 Conda):在项目目录执行 python -m venv venv 创建虚拟环境,并在 PowerShell 中执行 .\venv\Scripts\activate.ps1 激活(CMD 使用 venv\Scripts\activate.bat);

(2)安装依赖:使用清华镜像源执行 python -m pip install -r requirements.txt 安装所需依赖,加快下载速度;

(3)测试摄像机地址:运行 test_stream.py 验证网络摄像机取流地址(RTSP 如 rtsp://admin:123456@192.168.1.64:554/Streaming/Channels/101,HTTP 如 http://IP:8080/video.mjpg)是否可用;

(4)运行中文识别:执行 python ocr_camera.py 并指定摄像机地址与识别间隔,实时对画面中的汉字进行 OCR 识别并输出结果。

3.2 运行环境构造

运行环境构造步骤如下:(1)进入项目目录,执行 python -m venv venv 创建非 Conda 的 Python 虚拟环境;(2)激活虚拟环境(PowerShell:.\venv\Scripts\Activate.ps1;CMD:venv\Scripts\activate.bat);(3)使用清华镜像源安装依赖:python -m pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple;(4)安装完成后执行 pip list 核对 PaddleOCR、opencv-python、numpy、Pillow 等依赖已就绪。

3.3 编码实现

# -*- coding: utf-8 -*-

"""

摄像头 OCR 文字识别(中文)

================================

运行环境:

- Windows 系统

- Python 虚拟环境 venv(非 Conda)

- PaddleOCR 中文识别(纯 CPU)

支持的摄像头:

1. 本机 USB 摄像头 / 笔记本自带摄像头:--source 0(或 1、2...)

2. 网络摄像机(RTSP / HTTP):--source "rtsp://admin:12345@192.168.1.64:554/..."

用法示例:

# 用本机摄像头(默认第 0 个)

python ocr_camera.py

# 用本机第 1 个摄像头

python ocr_camera.py --source 1

# 用网络摄像机

python ocr_camera.py --source "rtsp://admin:12345@192.168.1.64:554/Streaming/Channels/101"

"""

import argparse

import os

import sys

import time

import cv2

import numpy as np

from PIL import Image, ImageDraw, ImageFont

# 让 RTSP 走 TCP 传输,Windows 下更稳定(只对网络摄像机生效,不影响 USB 摄像头)

os.environ.setdefault("OPENCV_FFMPEG_CAPTURE_OPTIONS", "rtsp_transport;tcp")

from paddleocr import PaddleOCR # noqa: E402

# Windows 下常见中文字体(用于把识别结果画回画面)

FONT_PATHS = [

r"C:\Windows\Fonts\msyh.ttc", # 微软雅黑

r"C:\Windows\Fonts\simhei.ttf", # 黑体

r"C:\Windows\Fonts\simsun.ttc", # 宋体

]

# 识别框可选颜色(BGR,供 OpenCV cv2.rectangle 使用)

BOX_COLORS = {

"green": (0, 255, 0),

"red": (0, 0, 255),

"blue": (255, 0, 0),

"yellow": (0, 255, 255),

"cyan": (255, 255, 0),

"white": (255, 255, 255),

}

def load_font(size: int = 20) -> ImageFont.FreeTypeFont:

"""加载中文字体,找不到时退回默认字体(此时中文会显示为方框)。"""

for path in FONT_PATHS:

if os.path.exists(path):

try:

return ImageFont.truetype(path, size)

except Exception:

continue

return ImageFont.load_default()

def parse_ocr_results(raw) -> list:

"""

把 PaddleOCR 的结果统一解析成 [(box, text, score), ...]。

兼容 PaddleOCR 2.x(ocr.ocr)与 3.x(ocr.predict / ocr.ocr)的返回结构。

"""

items = []

if raw is None:

return items

if isinstance(raw, list):

for page in raw:

if page is None:

continue

# 3.x 的 predict() 返回 dict 对象

if isinstance(page, dict):

texts = page.get("rec_texts", [])

scores = page.get("rec_scores", [])

polys = page.get("dt_polys", []) or page.get("rec_polys", [])

for i, text in enumerate(texts):

box = None

if i < len(polys):

try:

box = np.array(polys[i]).reshape(-1, 2).astype(int)

except Exception:

box = None

score = float(scores[i]) if i < len(scores) else 1.0

items.append((box, str(text), score))

continue

# 2.x 的 ocr.ocr():page = [ [box, (text, score)], ... ]

if isinstance(page, list):

for line in page:

try:

box = np.array(line[0]).reshape(-1, 2).astype(int)

text = str(line[1][0])

score = float(line[1][1])

items.append((box, text, score))

except Exception:

continue

return items

def draw_ocr_results(frame: np.ndarray, items: list, font,

box_color_bgr=(0, 255, 0)) -> np.ndarray:

"""

把识别出的文字用方框框出来(OpenCV 画框,保证可见),

再用 PIL 把中文文字画到画面上(OpenCV 不支持中文)。

"""

if not items:

return frame

# 1) 用 OpenCV 画方框(最稳,BGR 颜色)

for box, text, score in items:

if box is None or len(box) < 4:

continue

xs = [int(p[0]) for p in box]

ys = [int(p[1]) for p in box]

x1, y1 = min(xs), min(ys)

x2, y2 = max(xs), max(ys)

cv2.rectangle(frame, (x1, y1), (x2, y2), box_color_bgr, 3)

# 2) 用 PIL 画中文文字标签(黑底 + 黄字)

pil_img = Image.fromarray(cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))

draw = ImageDraw.Draw(pil_img)

for box, text, score in items:

if box is None or len(box) < 4:

continue

xs = [int(p[0]) for p in box]

ys = [int(p[1]) for p in box]

x1, y1 = min(xs), min(ys)

label = f"{text} {score:.2f}"

try:

tb = draw.textbbox((x1, y1), label, font=font)

text_w, text_h = tb[2] - tb[0], tb[3] - tb[1]

except Exception:

text_w, text_h = len(label) * 12, 24

draw.rectangle([x1, y1 - text_h - 4, x1 + text_w + 4, y1], fill=(0, 0, 0))

draw.text((x1 + 2, y1 - text_h - 2), label, fill=(255, 255, 0), font=font)

return cv2.cvtColor(np.asarray(pil_img), cv2.COLOR_RGB2BGR)

def is_local_camera(source: str) -> bool:

"""判断 source 是不是本机摄像头编号(纯数字)。"""

return source.strip().isdigit()

def open_camera(source: str, retries: int = 3):

"""打开摄像头:数字=本机摄像头,字符串=网络摄像机地址。失败自动重试。"""

local = is_local_camera(source)

idx = int(source) if local else None

for i in range(retries):

if local:

# CAP_DSHOW 是 Windows 上最适合 USB 摄像头的后端

cap = cv2.VideoCapture(idx, cv2.CAP_DSHOW)

else:

cap = cv2.VideoCapture(source, cv2.CAP_FFMPEG)

if cap.isOpened():

return cap

desc = f"本机摄像头 {idx}" if local else source

print(f"[警告] 第 {i + 1} 次打开 {desc} 失败,重试中...")

cap.release()

time.sleep(2)

return None

def main():

parser = argparse.ArgumentParser(description="摄像头中文 OCR 识别")

parser.add_argument(

"--source", default="0",

help="摄像头来源:本机摄像头编号(0/1/2...) 或 网络摄像机地址(rtsp://... / http://...)。默认 0",

)

parser.add_argument("--interval", type=float, default=0.5,

help="两次识别之间的间隔秒数(默认 0.5)")

parser.add_argument("--max-size", type=int, default=1280,

help="送入 OCR 前画面的最大边长(默认 1280)")

parser.add_argument("--save", action="store_true",

help="保存识别结果的截图和文本")

parser.add_argument("--out-dir", default="output",

help="保存目录(默认 output)")

parser.add_argument("--box-color", default="green",

choices=list(BOX_COLORS.keys()),

help="识别框颜色,可选 green/red/blue/yellow/cyan/white(默认 green)")

args = parser.parse_args()

print("正在初始化 PaddleOCR(首次运行会自动下载模型,请保持联网)...")

ocr = PaddleOCR(use_angle_cls=True, lang="ch", show_log=False)

font = load_font(22)

box_color = BOX_COLORS[args.box_color]

print("OCR 初始化完成。")

if args.save:

os.makedirs(args.out_dir, exist_ok=True)

cap = open_camera(args.source)

if cap is None:

print(f"[错误] 无法打开摄像头:{args.source}")

print("本机摄像头请检查:1) 摄像头是否插好/被占用 2) 尝试 --source 1 或 2")

print("网络摄像机请检查:1) 地址 2) 用户名密码 3) 是否同一局域网")

sys.exit(1)

print("摄像头已连接。按 'q' 键退出。")

last_ocr_time = 0.0

last_items = [] # 保存最近一次识别结果,持续显示在画面上

try:

while True:

ret, frame = cap.read()

if not ret:

print("[提示] 读取画面失败,尝试重连...")

cap.release()

cap = open_camera(args.source)

if cap is None:

print("[错误] 重连失败,退出。")

break

continue

now = time.time()

do_ocr = (now - last_ocr_time) >= args.interval

display = frame.copy()

if do_ocr:

last_ocr_time = now

h, w = frame.shape[:2]

scale = 1.0

if max(h, w) > args.max_size:

scale = args.max_size / max(h, w)

small = cv2.resize(frame, (int(w * scale), int(h * scale)))

else:

small = frame

raw = ocr.ocr(small, cls=True)

items = parse_ocr_results(raw)

for i, (box, text, score) in enumerate(items):

if box is not None and scale != 1.0:

box = (box / scale).astype(int)

items[i] = (box, text, score)

result_text = " | ".join(t for _, t, _ in items)

last_items = items

if items:

print(f"[识别] {result_text}")

else:

print("[识别] 当前画面未检测到文字")

# 每一帧都绘制最近一次识别结果,让方框持续显示(而不是只闪一帧)

display = draw_ocr_results(display, last_items, font, box_color)

# 保存带方框的截图和文本

if do_ocr and args.save and last_items:

ts = time.strftime("%Y%m%d_%H%M%S")

cv2.imwrite(os.path.join(args.out_dir, f"{ts}.jpg"), display)

with open(os.path.join(args.out_dir, f"{ts}.txt"), "w",

encoding="utf-8") as f:

for _, text, score in last_items:

f.write(f"{score:.3f}\t{text}\n")

cv2.imshow("Camera OCR - press q to quit", display)

if cv2.waitKey(1) & 0xFF == ord("q"):

break

finally:

cap.release()

cv2.destroyAllWindows()

print("已退出。")

if __name__ == "__main__":

main()

上述代码实现基于 PaddleOCR 的摄像头中文文字识别程序:支持本机 USB 摄像头与网络摄像机(RTSP/HTTP)两类画面来源;识别结果用 OpenCV 以方框标出文字位置,并用 PIL 将中文文字及置信度绘制回画面;程序按设定间隔自动识别,并支持将带框截图与识别文本保存到指定目录。

编码完成后,在命令行执行 python ocr_camera.py(本机摄像头)或 python ocr_camera.py --source "rtsp://..."(网络摄像机)即可启动识别,运行测试过程见 3.4 节。

3.4 运行测试

在 D:\dtctOCR 目录下执行 python ocr_camera.py,程序提示“正在初始化 PaddleOCR”并自动下载模型,随后显示“OCR 初始化完成”与“摄像头已连接”。

将摄像头对准带有汉字标识的物体(如“扬天”字样),终端持续输出 [识别] 扬天,画面中以绿色方框标出文字并显示置信度(扬天 1.00);按 q 键退出程序。测试结果表明,中文 OCR 识别在 Windows CPU 环境下运行正常,识别稳定。

4 IoTDA中转空间构建

4.0 IoTDA构造

登录华为云控制台,在“我的凭证—API凭证”页面查看账号 ID、IAM 用户名及项目列表(华东-上海一 cn-east-1、华北-北京四 cn-north-4),确认账号具备访问 IoTDA 的权限;随后进入“设备接入 IoTDA”服务,创建或选择标准版实例(华东-上海一),实例状态为“运行中”,完成 IoTDA 中转空间(实例)的构建。IoTDA 平台提供“创建产品、定义产品模型、注册设备、设备侧开发”四步标准流程,后续实训按该流程完成产品与设备构建。

4.1 产品及其模型构建

在 IoTDA 实例中依次创建“温湿度计”与“智能吸顶灯”两个产品:协议类型选择 MQTT,数据格式选择 JSON,所属行业为智能家居(子行业智能家居)。产品创建完成后,在实例“产品”列表中可查看产品名称、产品 ID、资源空间等信息,接下来分别对两个产品进行模型定义。

4.1.1 温湿度计

产品信息: - 产品名称:温湿度计 - 协议类型:MQTT - 数据格式:JSON - 所属行业:智能家居 - 所属子行业:智能家居

温湿度计产品模型定义步骤:(1)进入产品详情,在“模型定义”中点击“添加服务”,新建服务 T&H(服务类型 T&H);(2)在 T&H 服务的属性列表中添加属性 temperature(数据类型 decimal 小数、访问方式可读可写)与 humidity(数据类型 decimal 小数、访问方式可读可写);(3)保存后模型定义完成,产品信息如上所示,用于后续温湿度数据上报与命令下发。

4.1.2 吸顶灯

产品信息: -- 产品名称:智能吸顶灯 -- 协议类型:MQTT -- 数据格式:JSON -- 所属行业:智能家居 -- 所属子行业:智能家居

智能吸顶灯产品模型定义步骤:(1)在“模型定义”中分别添加服务 light 与 color;(2)light 服务下新增属性 luminance、power(decimal 小数、可读可写),并新增命令 turn_power;(3)color 服务下新增属性 cntcolor(string 字符串、可读),并新增命令 cntcolor;(4)保存后完成吸顶灯产品模型定义,产品信息如上所示。

4.2 设备实例化应用

进入 IoTDA 实例“设备—所有设备”页面,查看设备实例化情况:当前设备总数 2(智能吸顶灯两台),其中在线设备 1 台。设备列表中可查看设备状态、设备名称、设备标识符、设备 ID、所属资源空间、所属产品、节点类型等信息,并支持“注册设备、删除、刷新、批量导入”等管理操作,为设备注册及模拟测试做准备。

4.2.1 温湿度计设备注册及模拟测试

温湿度计设备注册及模拟测试步骤:(1)在“所有设备”页面点击“注册设备”,选择温湿度计产品并填写设备信息完成注册,注册成功后设备状态变为“在线”;

(2)使用 MQTT.fx 客户端连接 IoTDA,向设备属性上报 Topic 发布数据 {"temperature": 25.6, "humidity": 68.2};(3)回到控制台“设备详情—物模型数据”,可看到 temperature=25.6、humidity=68.2,最新更新时间同步刷新;(4)在“在线调试”中下发命令 SetTemperature(参数 {"temperature": 25.6, "humidity": 68.2}),通过“平台消息跟踪”查看设备上报、影子更新等日志,模拟测试成功。

4.2.2 吸顶灯设备注册及模拟测试

智能吸顶灯设备注册及模拟测试步骤:(1)在“所有设备”页面注册智能吸顶灯设备,记录设备密钥用于客户端连接;

(2)使用 MQTT.fx 向设备 Topic 发布消息,services 中包含 service_id "light"、属性 color "red" 及 event_time 时间戳;(3)控制台“设备详情—物模型数据”中 color 属性更新为 "red",设备状态“在线”;(4)在“在线调试”中设置服务 ID 为 light、方法为 set、参数 color=red,点击发送调试指令,调试输出与平台消息跟踪显示指令下发成功,模拟测试完成。

5 CodeArts智慧路灯快速构建与部署

5.1 应用项目创建

登录华为云 CodeArts(DevCloud)控制台,进入项目首页点击“新建项目”;在“新建项目”页面选择 Scrum(系统)模板——一种增量迭代式的敏捷研发流程模板;随后填写项目名称、项目代号与项目描述,点击确认完成应用项目创建,为智慧路灯应用提供项目管理与协作空间。

5.2 代码托管操作

在 CodeArts“代码托管”(CodeHub)中选择“按模板新建”创建代码仓库:在模板筛选栏搜索 IoT 相关模板,选择 IoT_Streetlight_Demo(智慧路灯示例)模板;

进入“填写基本信息”页面,设置代码仓库名称 mydemotemplate,可见范围选择“私有(仓库仅对仓库成员可见)”,并按需勾选“自动创建代码检查任务(免费)”;

确认创建后,系统基于所选模板自动生成智慧路灯示例代码并完成仓库初始化,代码托管操作完成,后续构建与部署均基于该仓库进行。

5.3 构建任务设立

在 CodeArts“编译构建”(CodeCI)中点击“新建构建任务”:基本信息中填写任务名称 mysonartight-23723316、所属项目,任务分组保持“未分组”,代码源选择 Repo 并选择对应代码仓,默认分支 master;在“选择模板”页选择推荐模板“使用 Apache Maven 构建 Java 应用”;随后在构建步骤中配置 Maven 构建——工具链选择 maven3.3.9-p8-open,脚本内容默认执行 mvn clean package(可跳过单元测试、强制更新快照等),完成后保存构建任务。

5.4 项目构建实现

在构建任务页面点击“保存并执行”启动构建,进入构建历史查看构建日志;

构建过程中自动拉取代码、下载 Maven 依赖并执行编译打包,日志中可查看各构建步骤的执行状态与输出;

构建成功后生成项目构建产物(如 huawei-0.0.1-SNAPSHOT.jar),构建状态显示成功,项目构建实现完成。

5.5 项目部署运行

项目部署运行步骤:(1)确认本地 Java 运行环境,在 CMD 中执行 java -version,显示 Java 版本 1.8.0_102(JDK 1.8),满足运行要求;

(2)打开 PowerShell,进入 jar 包所在目录(D:\Java),执行 java -jar .\huawei-0.0.1-SNAPSHOT.jar;(3)程序启动后终端显示 Spring Boot v2.1.3.RELEASE 启动信息,智慧路灯应用部署并运行成功。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐