<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>博客 &#8211; Antonio</title>
	<atom:link href="/category/blog/feed/" rel="self" type="application/rss+xml" />
	<link>https://nstar.ltd</link>
	<description></description>
	<lastBuildDate>Sat, 04 Apr 2026 06:43:32 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>AI视觉机械臂_项目框架与流程</title>
		<link>/ai%e8%a7%86%e8%a7%89%e6%9c%ba%e6%a2%b0%e8%87%82_%e9%a1%b9%e7%9b%ae%e6%a1%86%e6%9e%b6%e4%b8%8e%e6%b5%81%e7%a8%8b/</link>
					<comments>/ai%e8%a7%86%e8%a7%89%e6%9c%ba%e6%a2%b0%e8%87%82_%e9%a1%b9%e7%9b%ae%e6%a1%86%e6%9e%b6%e4%b8%8e%e6%b5%81%e7%a8%8b/#respond</comments>
		
		<dc:creator><![CDATA[Antonio]]></dc:creator>
		<pubDate>Tue, 31 Mar 2026 16:41:47 +0000</pubDate>
				<category><![CDATA[博客]]></category>
		<category><![CDATA[电子设计]]></category>
		<guid isPermaLink="false">/?p=294</guid>

					<description><![CDATA[AI 视觉机械臂 — 项目框架与实施流程 本文档依据毕业论文《AI 视觉机械臂》，并结合本仓库中的 Maixc [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h1 class="wp-block-heading">AI 视觉机械臂 — 项目框架与实施流程</h1>



<p>本文档依据毕业论文《AI 视觉机械臂》，并结合本仓库中的 <strong>Maixcam</strong> 与 <strong>Project</strong> 代码工程整理，用于说明系统分层、主流程步骤及所需技术栈。</p>



<p><a href="https://github.com/pieceofApple/AI-vision-robotic-arm.git">https://github.com/pieceofApple/AI-vision-robotic-arm.git</a></p>



<figure class="wp-block-image"><img fetchpriority="high" decoding="async" width="2560" height="1920" src="/wp-content/uploads/2026/04/机械臂实物图_标注-scaled.jpg" alt="" class="wp-image-298" srcset="/wp-content/uploads/2026/04/机械臂实物图_标注-scaled.jpg 2560w, /wp-content/uploads/2026/04/机械臂实物图_标注-300x225.jpg 300w, /wp-content/uploads/2026/04/机械臂实物图_标注-1024x768.jpg 1024w, /wp-content/uploads/2026/04/机械臂实物图_标注-768x576.jpg 768w, /wp-content/uploads/2026/04/机械臂实物图_标注-1536x1152.jpg 1536w, /wp-content/uploads/2026/04/机械臂实物图_标注-2048x1536.jpg 2048w" sizes="(max-width: 2560px) 100vw, 2560px" /></figure>



<p></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">1. 项目定位与目标</h2>



<ul class="wp-block-list">
<li><strong>定位</strong>：基于边缘计算的「视觉感知 + 机械臂执行」一体化平台，在成本可控前提下实现物体识别、目标定位与抓取类任务。</li>



<li><strong>论文方案</strong>：<strong>Maixcam</strong>（视觉与 AI 推理） + <strong>ESP32</strong>（运动控制与中继） + <strong>4 轴机械臂</strong>（5 路 PWM 舵机驱动），视觉与控制器之间采用 <strong>UDP</strong> 实时通信。</li>



<li><strong>核心链路</strong>：单目图像 → 目标检测 → 像素坐标到棋盘格世界坐标（透视变换）→ 将 ((x,y,z)) 等指令下发 ESP32 → <strong>逆运动学</strong> 解算关节角 → <strong>PWM</strong> 驱动舵机；辅以梯形速度规划、线性插值轨迹以平滑运动。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">2. 总体架构（三层）</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>层次</th><th>职责</th><th>论文对应</th><th>本仓库代码参考</th></tr></thead><tbody><tr><td><strong>感知层</strong></td><td>采集图像、畸变校正、棋盘格角点、YOLO 检测、世界坐标换算</td><td>第三章 3.2</td><td><code>Project/Maixcam/main.py</code>、<code>Maixcam/纸团-demo/main.py</code></td></tr><tr><td><strong>通信层</strong></td><td>Maixcam <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2194.png" alt="↔" class="wp-smiley" style="height: 1em; max-height: 1em;" /> ESP32 的 UDP 文本指令（如坐标、<code>rst</code>、<code>stop</code> 等）</td><td>3.1.3</td><td><code>main.py</code> 中 <code>udp_communication</code>；ESP 端 <code>WiFiUDP</code></td></tr><tr><td><strong>执行层</strong></td><td>逆运动学、工作空间校验、轨迹/速度规划、5 路 PWM</td><td>3.3</td><td><code>Project/robot_arm_5PWM/robot_arm_5PWM.ino</code></td></tr></tbody></table></figure>



<p><strong>说明</strong>：论文中视觉侧强调将训练好的 <strong>YOLOv5s</strong> 转为 <strong>int8 / cvimodel</strong> 以适配 TPU；当前工程中的在线推理多采用 <strong>Maix 官方 <code>nn.YOLOv5</code> + <code>.mud</code> 模型</strong>（MaixHub 部署路径），原理一致，均为边缘侧 YOLO 推理。仓库 <code>Maixcam/模型文件/</code> 下另有 <strong>YOLO11 OBB</strong> 等 <code>.mud</code>，可用于旋转框等扩展场景，与论文正文以 v5s 为主略有差异，选型时以实际任务为准。</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">3. 硬件框架</h2>



<ul class="wp-block-list">
<li><strong>Maixcam</strong>：GC4653 摄像头、Wi‑Fi/蓝牙；算力侧含 NPU（论文中用于加速 YOLO）。</li>



<li><strong>ESP32</strong>：连接同一局域网，监听 UDP；运行逆运动学与 PWM 输出。</li>



<li><strong>机械臂</strong>：论文为 <strong>4 轴结构、5 路 PWM</strong>（多一路如夹爪）；臂长参数见论文表 4.1（如 P、A1～A4），与 <code>robot_arm_5PWM.ino</code> 中宏定义一致。</li>



<li><strong>标定场地</strong>：棋盘格（论文示例 6×8 格、中心为原点）；摄像头置于棋盘上方，视野覆盖工作区。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">4. 软件模块与目录对应</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>模块</th><th>内容</th><th>路径提示</th></tr></thead><tbody><tr><td>端侧视觉主程序</td><td>采集、<code>lens_corr</code>、棋盘格、<code>getPerspectiveTransform</code>、YOLO 检测、逆透视得世界坐标、UDP</td><td><code>Project/Maixcam/main.py</code></td></tr><tr><td>应用描述</td><td>Maix 应用元数据</td><td><code>Project/Maixcam/app.yaml</code></td></tr><tr><td>纯检测 Demo</td><td>无标定与网络，便于验模</td><td><code>Maixcam/纸团-demo/main.py</code></td></tr><tr><td>PC 标定与可视化</td><td>OpenCV 标定、坐标映射等（论文 PC 端标定）</td><td><code>Project/Maixcam/PC_cv2/*.py</code>、<code>论文代码/相机标定.py</code></td></tr><tr><td>机械臂固件</td><td>WiFi、UDP、逆运动学、状态机、PWM</td><td><code>Project/robot_arm_5PWM/robot_arm_5PWM.ino</code></td></tr><tr><td>备份/试验</td><td>历史 UDP 测试等</td><td><code>Project/save_backup/</code></td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">5. 主流程步骤（建议实施顺序）</h2>



<h3 class="wp-block-heading">5.1 研发与标定阶段</h3>



<ol class="wp-block-list">
<li><strong>数据集与训练（PC）</strong>：按论文构建场景数据（如小纸团），用 <strong>YOLOv5s</strong> 训练；再按 <strong>Sophgo / Maix 工具链</strong> 导出为设备可用的 <strong>int8</strong>（论文）或按 Maix 流程导出 <strong><code>.mud</code></strong>（工程现状）。</li>



<li><strong>PC 相机标定（可选但推荐）</strong>：用棋盘格求内参与畸变，与端上 <code>lens_corr</code> 或粗略校正配合；参考 <code>PC_cv2/</code> 与论文 2.3、3.2.1。</li>



<li><strong>部署模型到 Maixcam</strong>：将模型放到设备约定路径（如 <code>main.py</code> 中的 <code>nn.YOLOv5(model=...)</code>）。</li>
</ol>



<h3 class="wp-block-heading">5.2 运行阶段（端侧闭环）</h3>



<ol class="wp-block-list">
<li><strong>初始化</strong>：摄像头分辨率与模型输入一致；启动 <strong>目标检测线程</strong> 与 <strong>UDP 线程</strong>（<code>threading</code>）。</li>



<li><strong>每帧视觉</strong>：
<ul class="wp-block-list">
<li>读图 → <code>lens_corr</code>；</li>



<li>转 OpenCV 灰度 → <code>findChessboardCorners</code> + <code>cornerSubPix</code>；</li>



<li>成功则计算世界四角与图像四角 → <strong>透视矩阵 M</strong>（异常时用上一帧 <code>last_M</code> 兜底）；</li>



<li><strong>YOLO 检测</strong> → 目标中心像素坐标 → <code>cv2.perspectiveTransform</code>（配合 (M^{-1})）得到 <strong>世界坐标 (cm 级)</strong>。</li>
</ul>
</li>



<li><strong>通信</strong>：ESP32 侧按协议发请求或接收指令；Maixcam 将 <code>x,y,z,flag</code> 或论文表 3.1 所列格式发往 ESP32（具体字符串以固件解析为准）。</li>



<li><strong>执行</strong>：ESP32 <strong>逆运动学</strong> → 关节角 → <strong>梯形规划 + 线性插值</strong> → <strong>PWM</strong>；完成抓取/放置/复位等状态切换。</li>
</ol>



<h3 class="wp-block-heading">5.3 联调与测试</h3>



<ul class="wp-block-list">
<li>论文第四章：检测准确率、坐标映射误差、实时性、重复定位、整机拾放等；环境为稳定 Wi‑Fi、统一光照与棋盘摆放。</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">6. 技术栈汇总</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>类别</th><th>技术</th></tr></thead><tbody><tr><td><strong>视觉 / AI</strong></td><td>Python 3（Maix 设备）、<strong>maix</strong>（camera、display、image、nn、app）、<strong>OpenCV（opencv-python）</strong>、<strong>NumPy</strong>；<strong>YOLOv5s</strong> 训练（PyTorch 生态，PC 端）；模型部署：<strong>TPU/NPU 量化 int8</strong>（论文）或 <strong>Maix <code>.mud</code></strong>（工程）</td></tr><tr><td><strong>几何与标定</strong></td><td>棋盘格角点、<strong>透视变换 / 单应性</strong>、亚像素角点；可选传统相机标定</td></tr><tr><td><strong>通信</strong></td><td><strong>UDP</strong>（<code>socket</code>）、<strong>Wi‑Fi</strong>；多线程 <strong><code>threading</code></strong>、<strong>queue</strong></td></tr><tr><td><strong>控制</strong></td><td><strong>ESP32</strong>、<strong>Arduino 框架</strong>、<strong>WiFi / WiFiUDP</strong>、<strong>math</strong>；<strong>逆运动学（几何法）</strong>、<strong>梯形速度规划</strong>、<strong>线性插值轨迹</strong>、<strong>PWM 舵机</strong></td></tr><tr><td><strong>工具</strong></td><td><strong>Arduino IDE</strong> + ESP32 板支持；PC 上 Python 标定脚本；可选 <strong>SolidWorks / 3D 打印</strong>（臂体，论文描述）</td></tr></tbody></table></figure>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">7.小结</h2>



<p>本项目在论文层面是 <strong>「Maixcam 边缘视觉 + ESP32 实时控制 + 单目透视定位」</strong> 的完整闭环；在仓库层面，<strong><code>Project/Maixcam/main.py</code></strong> 与 <strong><code>Project/robot_arm_5PWM/robot_arm_5PWM.ino</code></strong> 分别对应感知通信与执行两大核心，<strong><code>Maixcam/纸团-demo</code></strong> 用于快速验证检测模型，<strong><code>PC_cv2</code></strong> 与 <strong><code>论文代码</code></strong> 支撑标定与坐标映射开发。实施时以论文第三章、第四章为理论依据，以当前工程中的 IP、端口、指令字符串和模型路径为运行配置依据。</p>



<h2 class="wp-block-heading">8.演示视频</h2>



<figure class="wp-block-video"><video controls src="https://chevereto.nstar.ltd/images/2025/04/19/5d01974067923df7cb7df9d88a5f40ae.mp4"></video></figure>
]]></content:encoded>
					
					<wfw:commentRss>/ai%e8%a7%86%e8%a7%89%e6%9c%ba%e6%a2%b0%e8%87%82_%e9%a1%b9%e7%9b%ae%e6%a1%86%e6%9e%b6%e4%b8%8e%e6%b5%81%e7%a8%8b/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		<enclosure url="https://chevereto.nstar.ltd/images/2025/04/19/5d01974067923df7cb7df9d88a5f40ae.mp4" length="260063561" type="video/mp4" />

			</item>
		<item>
		<title>AFFINE AI——一个完美替代Notion AI的本地部署笔记软件</title>
		<link>/affine-ai-%e4%b8%80%e4%b8%aa%e5%ae%8c%e7%be%8e%e6%9b%bf%e4%bb%a3notion-ai%e7%9a%84%e6%9c%ac%e5%9c%b0%e9%83%a8%e7%bd%b2%e7%ac%94%e8%ae%b0%e8%bd%af%e4%bb%b6/</link>
					<comments>/affine-ai-%e4%b8%80%e4%b8%aa%e5%ae%8c%e7%be%8e%e6%9b%bf%e4%bb%a3notion-ai%e7%9a%84%e6%9c%ac%e5%9c%b0%e9%83%a8%e7%bd%b2%e7%ac%94%e8%ae%b0%e8%bd%af%e4%bb%b6/#respond</comments>
		
		<dc:creator><![CDATA[Antonio]]></dc:creator>
		<pubDate>Thu, 11 Dec 2025 17:28:06 +0000</pubDate>
				<category><![CDATA[博客]]></category>
		<category><![CDATA[软件推荐]]></category>
		<guid isPermaLink="false">/?p=281</guid>

					<description><![CDATA[引言：AppFlowy-Cloud踩坑，原先是想用appflowy的，无奈cloud本地部署踩坑太多，此前对于 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>引言：AppFlowy-Cloud踩坑，原先是想用appflowy的，无奈cloud本地部署踩坑太多，此前对于docker-compose配置不太熟悉，故AI咋说我咋做，一做一个不吱声<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f62d.png" alt="😭" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>首先：认识docker-compose</p>



<p>可以通过docker-compose文件直接将所需的docker镜像安装、配置部署。</p>



<p>具体教程可直接参考：</p>



<p><a href="https://blog.lcayun.com/4277.html">Docker 一键部署 AFFiNE 教程：开源 Notion + Miro 替代，打造私有知识库</a></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">1 <strong>搭建方式</strong></h2>



<h3 class="wp-block-heading">1.1 <strong>安装docker和docker-compose</strong></h3>



<h3 class="wp-block-heading">1.2 <strong>获取 Docker Compose 文件和.env文件</strong></h3>



<pre class="wp-block-code"><code>#定义了 AFFiNE 容器、端口映射和卷挂载
wget -O docker-compose.yml https://github.com/toeverything/affine/releases/latest/download/docker-compose.yml</code></pre>



<pre class="wp-block-code"><code>#自动下载示例 .env 文件
wget -O .env https://github.com/toeverything/affine/releases/latest/download/default.env.example</code></pre>



<h3 class="wp-block-heading">1.3 修改docker-compose.yml和.env配置</h3>



<p>通用配置：</p>



<p>（仅需要添加DB数据库密码配置即可）</p>



<p>.env文件</p>



<pre class="wp-block-code"><code># select a revision to deploy, available values: stable, beta, canary
AFFINE_REVISION=stable

# set the port for the server container it will expose the server on
PORT=3010

# set the host for the server for outgoing links
# AFFINE_SERVER_HTTPS=true
# AFFINE_SERVER_HOST=affine.yourdomain.com
# or 
# AFFINE_SERVER_EXTERNAL_URL=https://affine.yourdomain.com

# position of the database data to persist
DB_DATA_LOCATION=~/.affine/self-host/postgres/pgdata
# position of the upload data(images, files, etc.) to persist
UPLOAD_LOCATION=~/.affine/self-host/storage
# position of the configuration files to persist
CONFIG_LOCATION=~/.affine/self-host/config

# database credentials
DB_USERNAME=affine
DB_PASSWORD=affine
DB_DATABASE=affine
</code></pre>



<p>docker-compose.yml文件</p>



<pre class="wp-block-code"><code>name: affine
services:
  affine:
    image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
    container_name: affine_server
    ports:
      - '${PORT:-3010}:3010'
    depends_on:
      redis:
        condition: service_healthy
      postgres:
        condition: service_healthy
      affine_migration:
        condition: service_completed_successfully
    volumes:
      # custom configurations
      - ${UPLOAD_LOCATION}:/root/.affine/storage
      - ${CONFIG_LOCATION}:/root/.affine/config
    env_file:
      - .env
    environment:
      - REDIS_SERVER_HOST=redis
      - DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine}
      - AFFINE_INDEXER_ENABLED=false
    restart: unless-stopped

  affine_migration:
    image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
    container_name: affine_migration_job
    volumes:
      # custom configurations
      - ${UPLOAD_LOCATION}:/root/.affine/storage
      - ${CONFIG_LOCATION}:/root/.affine/config
    command: &#91;'sh', '-c', 'node ./scripts/self-host-predeploy.js']
    env_file:
      - .env
    environment:
      - REDIS_SERVER_HOST=redis
      - DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine}
      - AFFINE_INDEXER_ENABLED=false
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy

  redis:
    image: redis
    container_name: affine_redis
    healthcheck:
      test: &#91;'CMD', 'redis-cli', '--raw', 'incr', 'ping']
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  postgres:
    image: pgvector/pgvector:pg16
    container_name: affine_postgres
    volumes:
      - ${DB_DATA_LOCATION}:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: ${DB_DATABASE:-affine}
      POSTGRES_INITDB_ARGS: '--data-checksums'
      # you better set a password for you database
      # or you may add 'POSTGRES_HOST_AUTH_METHOD=trust' to ignore postgres security policy
      POSTGRES_HOST_AUTH_METHOD: trust
    healthcheck:
      test:
        &#91;'CMD', 'pg_isready', '-U', "${DB_USERNAME}", '-d', "${DB_DATABASE:-affine}"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped
</code></pre>



<h3 class="wp-block-heading">1.4 启动dokcer</h3>



<pre class="wp-block-code"><code># 启动docker
docker compose up -d

# 重启docker
docker compose stop
docker compose start

# 升级docker
docker compose down
docker compose pull
docker compose up -d</code></pre>



<h3 class="wp-block-heading">1.5<strong> 访问AFFiNE</strong></h3>



<figure class="wp-block-image size-full"><img decoding="async" width="1024" height="484" src="/wp-content/uploads/2025/12/image-1.png" alt="" class="wp-image-283" srcset="/wp-content/uploads/2025/12/image-1.png 1024w, /wp-content/uploads/2025/12/image-1-300x142.png 300w, /wp-content/uploads/2025/12/image-1-768x363.png 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>然后自行创建用户</p>



<p>(设置中文)</p>



<p>更多使用跟介绍可以看看官方文档：<a href="https://docs.affine.pro/self-host-affine/administer/indexer">https://docs.affine.pro/self-host-affine/administer/indexer</a></p>



<h3 class="wp-block-heading">遗留问题</h3>



<p>用户无法通过自行通过邮箱注册账号，只能在管理员界面新建用户</p>



<p>发送验证码邮件时，affine-sever日志会显示<strong>SMTP——500</strong>的错误码</p>



<h1 class="wp-block-heading">迁移Affine服务</h1>



<ol class="wp-block-list">
<li>需备份好以下三个文件夹，然后迁移：</li>
</ol>



<figure class="wp-block-image size-full"><img decoding="async" width="179" height="121" src="/wp-content/uploads/2025/12/image.png" alt="" class="wp-image-282"/></figure>



<ol class="wp-block-list">
<li>需保持数据库账号密码一致，否则无法访问（其他默认）</li>



<li>新服务器登录直接使用原来设置的账号</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>AI服务：</p>



<p>当前使用国内转接：poloai。参考以下配置gemini：</p>



<pre class="wp-block-code"><code>{
"model":"gemini-2.0-flash",
"apiKey":"sk-************",
"baseURL":"https://poloai.top/v1"
}</code></pre>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>/affine-ai-%e4%b8%80%e4%b8%aa%e5%ae%8c%e7%be%8e%e6%9b%bf%e4%bb%a3notion-ai%e7%9a%84%e6%9c%ac%e5%9c%b0%e9%83%a8%e7%bd%b2%e7%ac%94%e8%ae%b0%e8%bd%af%e4%bb%b6/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>分享一段word转图片的python脚本</title>
		<link>/%e5%88%86%e4%ba%ab%e4%b8%80%e6%ae%b5word%e8%bd%ac%e5%9b%be%e7%89%87%e7%9a%84python%e8%84%9a%e6%9c%ac/</link>
					<comments>/%e5%88%86%e4%ba%ab%e4%b8%80%e6%ae%b5word%e8%bd%ac%e5%9b%be%e7%89%87%e7%9a%84python%e8%84%9a%e6%9c%ac/#respond</comments>
		
		<dc:creator><![CDATA[Antonio]]></dc:creator>
		<pubDate>Fri, 04 Jul 2025 17:30:29 +0000</pubDate>
				<category><![CDATA[博客]]></category>
		<guid isPermaLink="false">http://antonioz.asia/?p=261</guid>

					<description><![CDATA[以下代码用于将word转换为jpg图片，默认为A4纸尺寸]]></description>
										<content:encoded><![CDATA[
<p>以下代码用于将word转换为jpg图片，默认为A4纸尺寸</p>



<pre class="wp-block-code"><code>import os
import tempfile
from PIL import Image
import comtypes.client
import fitz  # PyMuPDF库，用于PDF处理

def word_to_images(input_file, output_folder=None, dpi=300):
    """
    将Word文档转换为图片，保持原始尺寸。

    参数:
        input_file (str): Word文档路径
        output_folder (str, optional): 输出图片文件夹路径，默认为None(创建临时文件夹)
        dpi (int, optional): 图片DPI，默认为300

    返回:
        list: 生成的图片路径列表
    """
    # 创建输出文件夹
    if output_folder is None:
        output_folder = tempfile.mkdtemp()
    os.makedirs(output_folder, exist_ok=True)

    # 获取文件名(不带扩展名)
    base_name = os.path.splitext(os.path.basename(input_file))&#91;0]

    try:
        # 第一步：将Word转换为PDF
        pdf_path = os.path.join(tempfile.gettempdir(), f"{base_name}.pdf")
        
        # 创建Word应用实例
        word = comtypes.client.CreateObject('Word.Application')
        word.Visible = False

        # 打开文档
        doc = word.Documents.Open(os.path.abspath(input_file))
        
        # 保存为PDF
        doc.SaveAs(pdf_path, FileFormat=17)  # 17代表PDF格式
        
        # 关闭文档和应用
        doc.Close()
        word.Quit()
        
        # 第二步：从PDF生成图片
        image_paths = &#91;]
        
        # 打开PDF
        pdf_document = fitz.open(pdf_path)
        
        # 处理每一页
        for page_num in range(len(pdf_document)):
            page = pdf_document.load_page(page_num)
            pix = page.get_pixmap(matrix=fitz.Matrix(dpi/72, dpi/72))  # 设置DPI
            
            # 创建图片路径
            image_path = os.path.join(output_folder, f"{base_name}_page{page_num+1}.png")
            
            # 保存图片
            pix.save(image_path)
            image_paths.append(image_path)
            print(f"已生成图片: {image_path}")
            
            # 检查图片尺寸是否为A4
            is_a4 = check_a4_size(image_path, dpi)
            size_info = "A4尺寸" if is_a4 else "非A4尺寸"
            print(f"  - 图片尺寸: {size_info}")
        
        # 关闭PDF文档
        pdf_document.close()
        
        # 删除临时PDF文件
        os.remove(pdf_path)
        
        return image_paths

    except Exception as e:
        print(f"致命错误: {str(e)}")
        # 确保清理资源
        try:
            if 'word' in locals() and word:
                word.Quit()
            if 'pdf_document' in locals() and pdf_document:
                pdf_document.close()
            # 删除可能残留的临时文件
            if os.path.exists(pdf_path):
                os.remove(pdf_path)
        except:
            pass
        return &#91;]

def check_a4_size(image_path, dpi=300, tolerance=0.02):
    """
    检查图片是否符合A4尺寸标准
    
    参数:
        image_path (str): 图片路径
        dpi (int): 图片DPI，默认为300
        tolerance (float): 容差范围，默认为0.02 (2%)
        
    返回:
        bool: 如果图片尺寸在A4标准范围内返回True，否则返回False
    """
    # A4纸的标准尺寸(mm)
    a4_width_mm = 210
    a4_height_mm = 297
    
    # 计算A4纸在指定DPI下的像素尺寸
    a4_width_px = round((a4_width_mm / 25.4) * dpi)
    a4_height_px = round((a4_height_mm / 25.4) * dpi)
    
    # 打开图片获取尺寸
    with Image.open(image_path) as img:
        width, height = img.size
    
    # 计算允许的误差范围
    width_min = a4_width_px * (1 - tolerance)
    width_max = a4_width_px * (1 + tolerance)
    height_min = a4_height_px * (1 - tolerance)
    height_max = a4_height_px * (1 + tolerance)
    
    # 检查图片尺寸是否在允许的误差范围内
    # 考虑到图片可能被旋转
    return (
        (width_min &lt;= width &lt;= width_max and height_min &lt;= height &lt;= height_max) or
        (width_min &lt;= height &lt;= width_max and height_min &lt;= width &lt;= height_max)
    )

if __name__ == "__main__":
    # 使用示例
    input_file = "Doc1.docx"  # 替换为你的Word文档路径
    output_folder = "word_images"  # 替换为你想要的输出文件夹
    dpi = 300  # 设置DPI值
    
    images = word_to_images(input_file, output_folder, dpi)
    
    if images:
        print(f"成功生成 {len(images)} 张图片")
    else:
        print("转换失败")</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>/%e5%88%86%e4%ba%ab%e4%b8%80%e6%ae%b5word%e8%bd%ac%e5%9b%be%e7%89%87%e7%9a%84python%e8%84%9a%e6%9c%ac/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Maixcam使用</title>
		<link>/maixcam%e4%bd%bf%e7%94%a8/</link>
					<comments>/maixcam%e4%bd%bf%e7%94%a8/#respond</comments>
		
		<dc:creator><![CDATA[Antonio]]></dc:creator>
		<pubDate>Sat, 15 Mar 2025 18:44:28 +0000</pubDate>
				<category><![CDATA[博客]]></category>
		<category><![CDATA[电子设计]]></category>
		<category><![CDATA[笔记]]></category>
		<guid isPermaLink="false">http://antonioz.asia/?p=218</guid>

					<description><![CDATA[Maixcam使用 注意： 模型转换时，分辨率需保持一致，若为640X640训练的模型，则后面onnx模型转换 [&#8230;]]]></description>
										<content:encoded><![CDATA[<h1>Maixcam使用</h1>
<h2>注意：</h2>
<ol>
<li>模型转换时，分辨率需保持一致，若为640X640训练的模型，则后面onnx模型转换为. cvimodel模型时需要保持参数一致！！！（适用于Maixcam的分辨率参数是320X224）</li>
<li>遇到如下问题，先升级ONNXRuntime—pip install &#8211;upgrade onnxruntime -i <a href="https://pypi.tuna.tsinghua.edu.cn/simple">https://pypi.tuna.tsinghua.edu.cn/simple</a></li>
</ol>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-219" src="/wp-content/uploads/2025/03/tpc-yolo_error.png" alt="" width="1232" height="136" srcset="/wp-content/uploads/2025/03/tpc-yolo_error.png 1232w, /wp-content/uploads/2025/03/tpc-yolo_error-300x33.png 300w, /wp-content/uploads/2025/03/tpc-yolo_error-1024x113.png 1024w, /wp-content/uploads/2025/03/tpc-yolo_error-768x85.png 768w" sizes="auto, (max-width: 1232px) 100vw, 1232px" /></p>
<p>一般升级后错误消失</p>
<ol>
<li>在文件夹里放置的图片要求：<br />
1.是数据集集里面的<br />
2.大小必须一致<br />
3.边长一定是32的倍数。如果不是32的倍数，就一定不符合模型的输入张量。补救的方法是用python脚本给他填充成32的倍数也行</li>
</ol>
<hr />
<p>用于yolo11n-obb模型：</p>
<p>OBB是什么？——和普通的识别框相比，OBB的识别框可以随物体的姿态转动，更好地标识出物体！你运行Maixvision自带案例中的ai_vision/nn_yolo11n_obb.py试试，看看这框真帅吧！而下图是我自己训练的模型效果：</p>
<p><img decoding="async" src="https://maixhub.com/public/sharing/39207-b7887866d2d04d3bbf2f9bed5e41d8c0.png" alt="" /></p>
<p>有人会问：只看Maixpy官方文档的那个YOLO11-obb部署与识别教程可以吗？——可以，但是大概率会踩不少坑。你也许会遇到识别框无法旋转、INT8模型无法转换成功、运行模型后相机卡死、导入模型失败……等一系列烦人的事。所以，请将官方文档和我这篇文章结合起来食用效果更佳。</p>
<p>所用开发环境是Linux ubuntu22.04。若你是在Windows也没关系，其核心思想万变不离其宗。</p>
<p>如有更好的提议请告诉我，谢谢！</p>
<h1><strong>查看相机Maixpy版本</strong></h1>
<p>在相机内打开设置——设备信息，查看你的MaixPy版本。MaixPy不仅有电脑pip安装的，相机内部也有自己的MaixPy。要确保MaixPy是比较新的版本。</p>
<p>在Maixpy的github仓库中可以看到，自4.9.3开始才支持YOLO11-OBB检测（没找到YOLOV8-OBB是什么时候，所以最好用YOLO11来进行OBB检测）。如果你需要升级相机的maixpy版本，就要准备一个读卡器，烧录教程看maixcam官方文档的即可，很详细我这里就不说了。</p>
<h1><strong>采集数据集</strong></h1>
<p>大多数人常用相机里那个Maixhub客户端来在线设备采集，然而这种设备采集的曝光时间、增益值是自动的，如果你对数据集曝光要求比较严格，那就需要自己写个拍摄的程序。</p>
<p>例如我编写的是下面的采集程序。启动程序后，每秒拍摄4张图片储存在相机SD卡中。你可以随意修改它的曝光，设为-1代表自动。</p>
<pre><code class="language-python">from maix import camera, display, app, time
import os

# 设置摄像头分辨率
cam = camera.Camera(660, 280)
disp = display.Display()

cam.skip_frames(200)# 延时，等待相机稳定

exposure=cam.exposure(value = 3000)
gain=cam.gain(value = 3300)

# 保存文件夹路径。这是关于相机内的路径，和电脑路径无关
save_folder = "/root/photo"
if not os.path.exists(save_folder):
    os.makedirs(save_folder)

# 设置拍摄频率（每秒4张）
capture_interval = 0.25# 每张图片间隔时间
last_capture_time = time.time()

while not app.need_exit():
    img = cam.read()
    disp.show(img)# 显示图片

    current_time = time.time()
    if current_time - last_capture_time &gt;= capture_interval:
# 生成文件名
        timestamp = int(current_time * 1000)# 使用时间戳作为文件名
        file_path = os.path.join(save_folder, f"{timestamp}.jpg")

# 保存图片
        img.save(file_path)
        print(f"Saved: {file_path}")

# 更新上次拍摄时间
        last_capture_time = current_time

    time.sleep(0.01)# 稍微延迟一下，避免占用过多CPU</code></pre>
<h1><strong>下载、配置yolo11训练工程</strong></h1>
<p>给它单独开一个conda环境，我用的python 3.10。</p>
<p>从<a href="https://github.com/ultralytics/ultralytics"><strong>https://github.com/ultralytics/ultralytics</strong></a>下载源码，不用选版本，直接下就行。下载好后执行 pip install -r ultralytics transformers -i <a href="https://pypi.tuna.tsinghua.edu.cn/simple。之后如果报错缺少XX包，你就pip安装什么包。另外注意pip包之间容易有版本冲突，所以不能无脑下载，而是应该提前去百度包和包、包和环境之间的版本对应关系">https://pypi.tuna.tsinghua.edu.cn/simple。之后如果报错缺少XX包，你就pip安装什么包。另外注意pip包之间容易有版本冲突，所以不能无脑下载，而是应该提前去百度包和包、包和环境之间的版本对应关系</a>。</p>
<h1><strong>准备数据集</strong></h1>
<p>（1）数据集文件介绍</p>
<p>制作好的数据集的文件夹分布是这样的：</p>
<p><img decoding="async" src="https://maixhub.com/public/sharing/39207-51430ef88f0f45dbaa17934b82118510.png" alt="" /></p>
<p>images/train 里面放训练图片，labels/train 里面放训练txt。</p>
<p>images/val 里面放验证图片，labels/val 里面放验证txt。</p>
<p>test里面可以是空的。</p>
<p>（2）txt格式介绍</p>
<p>用上海交通大学交龙战队开源的那个就行<a href="https://github.com/xinyang-go/LabelRoboMaster"><strong>https://github.com/xinyang-go/LabelRoboMaster</strong></a>，它生成的txt格式完全符合标准。标注的方法看它的readme。</p>
<blockquote><p>关于训练图片，最好是每张图片分辨率完全一样！！虽说理论上任何大小的图片都可以用于训练。但是训练的图片最好不要有的图片width过大、有的图片hight过大，因为之后训练的时候程序会给它们填充灰边使其统一大小。</p>
<p>（3）整理好的数据集放在哪都行，我习惯放在Ultralytics工程目录下。</p></blockquote>
<h1><strong>获取yolo11n-obb.pt文件</strong></h1>
<p>从这个链接可以下载所有的官方pt权重文件<a href="https://github.com/ultralytics/assets/releases"><strong>https://github.com/ultralytics/assets/releases</strong></a>。注意我们要的不是普通的yolo11n.pt，而是yolo11n-obb.pt ！！它俩结构不一样，只有后者用于检测旋转矩形。</p>
<blockquote><p>使用yolo11s-obb乃至其他字母的行吗？——我的建议是一定要基于yolo11n-obb进行训练。我曾经试过 s 的，但是一开始推理相机就卡死、掉线，必须重启，说明相机内存爆了！去官网查看pt文件的大小，n 文件大小为5MB，而 s 文件19MB体量太大，其他字母的更不用说了，一个比一个大根本不能用。</p></blockquote>
<h1><strong>必备的两个yaml（1）——路径与标签</strong></h1>
<p>在工程目录下创建myfile-obb.yaml，输入：</p>
<pre><code class="language-yaml">path: /home/wp/ultralytics-main/my_data# dataset root dirtrain: images/train
val: images/val
#test: images/testnames:
  0: apple</code></pre>
<p>简单解释一下：train和val是相对于path路径的。有个一劳永逸、安全但麻烦的方法是都使用绝对路径，当然我上面的代码可没有这样做。</p>
<p>这里我只写了一个类别。你可以随意更改类别的数目、内容。</p>
<h1><strong>必备的两个yaml（2）——网络定义</strong></h1>
<p>先声明一点：这个yaml是官方的，自己不用写，我们常说的“基于yolo…”就是选择的这个yaml。</p>
<p>在 ultralytics/cfg/models 下，你会看到从v3到v11所有版本的yaml，里面还细分了pose、obb、普通等各种模型，这个 yolo11-obb.yaml 就是我们想要的，复制一份放在工程目录下。</p>
<p><img decoding="async" src="https://maixhub.com/public/sharing/39207-cb168f32b0374401aee582e88ac3a738.png" alt="" /></p>
<blockquote><p>一定要重命名为yolo11n-obb.yaml，刚拿出来是不带s、n……这些字母的。</p></blockquote>
<p>内容只需要改标签类别(nc)这个数字。</p>
<p>网上有博主给你的，其网络结构大概率和官方的这个yaml内容一模一样，用vscode对比就能看出来。</p>
<h1><strong>编写训练器train.py</strong></h1>
<p>在工程目录下新建一个train.py，那个imgsz是缩放 / 填充预处理，如果你的图片小于这个数，就会填充黑边再训练。其余的改改路径就行：</p>
<p>而v8训练出来的模型识别框根本无法旋转，角度永远输出-1.0000。</p>
<p>可能出现的问题：明明我指定的是yolo11s的pt文件，但是训练前期非要给我下载yolo11n.pt</p>
<p>先说明一点——不要使用yolo11s训练。不过我们还是要解决这个问题：找到amp这个参数，将它关闭就行。在ultralytics-main官方文件中，amp参数在ultralytics/cfgdefault.yaml 中，以键值对的方式，默认为True，把它改为False就行了。</p>
<pre><code class="language-python">from ultralytics import YOLO

def main():
    model = YOLO('yolo11n-obb.yaml').load('/home/wp/ultralytics-main/yolo11n-obb.pt')# build from YAML and transfer weights
    model.train(data='myfile-obb.yaml', epochs=100, imgsz=416, batch=4, workers=4)
if __name__ == '__main__':
    main()</code></pre>
<h1><strong>检查训练结果，获得pt模型文件</strong></h1>
<p>训练好之后，在 runs/obb 下就能看到检测结果了。</p>
<h1><strong>pt转ONNX</strong></h1>
<p>工程目录下新建transform.py，代码如下。</p>
<blockquote><p>这里的 width、height 一定要设置成32的倍数。如&gt;果你没有设置为32的倍数，程序会悄悄设置成32的倍数，之后可能不符合你的预期而浪费时间。</p></blockquote>
<p>转换成功后，在pt文件的同目录下就生成了。</p>
<pre><code class="language-python">from ultralytics import YOLO

net_name = "/home/wp/ultralytics-main/runs/obb/train5/weights/best.pt"
input_width = 864# 一定是32的倍数
input_height = 288

model = YOLO(net_name)
path = model.export(format="onnx", imgsz=[input_height, input_width], dynamic=False, simplify=True, opset=17)# export the model to ONNX formatprint(path)</code></pre>
<h1><strong>ONNX转mud和cvimodel</strong></h1>
<p>（1）确定ONNX模型的输出节点</p>
<p>上https://netron.app/查看ONNX文件的结构图。按ctrl+F分别搜索：/model.23/dfl/conv/Conv_output_0，/model.23/Sigmoid_1_output_0，/model.23/Sigmoid_output_0。看看有没有这三个节点，如果缺少了说明模型错了。</p>
<p>（2）部署并配置算能的tpu-mlir</p>
<ul>
<li>先装好docker吧，用小鱼ROS命令装很轻松。终端输入：按照小鱼的指引一步步来就行。（Windows用其他方式安装）</li>
</ul>
<pre><code>wget http://fishros.com/install -O fishros &amp;&amp; . fishros</code></pre>
<ul>
<li>终端执行命令 wget <a href="https://sophon-file.sophon.cn/sophon-prod-s3/drive/24/06/14/12/sophgo-tpuc_dev-v3.2_191a433358ad.tar.gz">https://sophon-file.sophon.cn/sophon-prod-s3/drive/24/06/14/12/sophgo-tpuc_dev-v3.2_191a433358ad.tar.gz</a> 下载它的压缩包，下载好后执行docker load -i sophgo-tpuc_dev-v3.2_191a433358ad.tar.gz 。</li>
<li>在home目录下新建文件夹MaixCAM，在此文件夹下打开终端，执行 docker run &#8211;privileged &#8211;name MaixCAM -v $PWD:/workspace -it sophgo/tpuc_dev:v3.2 ，创建来一个MaixCAM的容器。没问题，然后关闭终端。</li>
<li>前往<a href="https://github.com/sophgo/tpu-mlir/releases"><strong>https://github.com/sophgo/tpu-mlir/releases</strong></a>，下载一个tpu_mlir-1.15b0-py3-none-any.whl，下载好后将它移动到MaixCAM，在文件夹内打开终端，输入 docker start MaixCAM &amp;&amp; docker attach MaixCAM 打开容器，执行 pip install tpu_mlir-1.15b0-py3-none-any.whl ，完成后如下图所示。（3）将你需要转换的onnx文件放到MaixCAM文件夹中，再将一些待会测试的图片放进去。这里注意，test.jpg和images文件夹里的所有图片有3点要求：1.这些图片来自于数据集。2.大小必须一致。补救的方法是用python脚本用(114,114,114)的灰色填充为大小一致。3.边长一定是32的倍数。如果不是32的倍数，就一定不符合模型的输入张量。补救的方法是用python脚本用(114,114,114)的灰色填充为32的倍数。<img decoding="async" src="https://maixhub.com/public/sharing/39207-ae8cf0bd22674376a2335cb26bcf2ec2.png" alt="" />
<p><img decoding="async" src="https://maixhub.com/public/sharing/39207-930151844bee4c9483bf450f50792938.png" alt="" /></li>
</ul>
<blockquote><p>这里的test.jpg的作用是什么？用于程序内部预处理验证、模型测试。从数据集中选取一张与模型输入相同大小的图片即可。images里面的图像作用又是什么？你会发现这只是专为INT8的转换而传入的。因为模型从浮点类型转为int类型需要生成“校准表”，用来调整网络中各种阈值参数。这个过程可以看做小规模的数据集训练，最后得到程序所需的参数。你需要从训练集中尽可能挑选各种特色鲜明、非极端情况的图片100~1000张。详细原理看https://doc.sophgo.com/sdk-docs/v23.03.01/docs_latest_release/docs/tpu-mlir/developer_manual/html/07_calibration.html</p></blockquote>
<p>（4）建立转换脚本</p>
<p>新建 .sh 脚本，命名为convert_yolo11_to_cvimodel，里面输入下面的代码。</p>
<p>你需要修改的是：把net_name改成模型文件名字，宽和高改成模型输入口的大小。&#8211;output_names改成你自己的模型名称。</p>
<blockquote><p>可能出现的问题：在容器内报错：[ONNXRuntimeError] : 9 : NOT_IMPLEMENTED : Could not find an implementation for Reshape(19) node with name &#8216;/model.22/Reshape&#8217;</p>
<p>那就在容器内执行 pip install &#8211;upgrade onnxruntime -i <a href="https://pypi.tuna.tsinghua.edu.cn/simple">https://pypi.tuna.tsinghua.edu.cn/simple</a> 升级onnxruntime就行。</p></blockquote>
<pre><code>#!/bin/bash

set -e

net_name=my_obb
input_w=864
input_h=288

# mean: 0, 0, 0# std: 255, 255, 255# mean# 1/std# mean: 0, 0, 0# scale: 0.00392156862745098, 0.00392156862745098, 0.00392156862745098mkdir -p workspace
cd workspace

# convert to mlir
model_transform.py 
--model_name ${net_name} 
--model_def ../${net_name}.onnx 
--input_shapes [[1,3,${input_h},${input_w}]] 
--mean "0,0,0" 
--scale "0.00392156862745098,0.00392156862745098,0.00392156862745098" 
--keep_aspect_ratio 
--pixel_format rgb 
--channel_format nchw 
--output_names "/model.23/dfl/conv/Conv_output_0,/model.23/Sigmoid_1_output_0,/model.23/Sigmoid_output_0" 
--test_input ../test.jpg 
--test_result ${net_name}_top_outputs.npz 
--tolerance 0.99,0.99 
--mlir ${net_name}.mlir

# export bf16 model#   not use --quant_input, use float32 for easy coding
model_deploy.py 
--mlir ${net_name}.mlir 
--quantize BF16 
--processor cv181x 
--test_input ${net_name}_in_f32.npz 
--test_reference ${net_name}_top_outputs.npz 
--model ${net_name}_bf16.cvimodel

echo "calibrate for int8 model"
# export int8 model
run_calibration.py ${net_name}.mlir 
--dataset ../images 
--input_num 200 
-o ${net_name}_cali_table

echo "convert to int8 model"
# export int8 model#    add --quant_input, use int8 for faster processing in maix.nn.NN.forward_image
model_deploy.py 
--mlir ${net_name}.mlir 
--quantize INT8 
--quant_input 
--calibration_table ${net_name}_cali_table 
--processor cv181x 
--test_input ${net_name}_in_f32.npz 
--test_reference ${net_name}_top_outputs.npz 
--tolerance 0.9,0.6 
--model ${net_name}_int8.cvimodel</code></pre>
<p>（5）生成cvimodel文件，制作mud文件</p>
<p>在容器中执行 chmod +x convert_yolo11_to_cvimodel.sh &amp;&amp; ./convert_yolo11_to_cvimodel.sh 命令。如果没问题的话，在 workspace 就能生成cvimodel文件。</p>
<p>有2种精度，选一种拷贝一份出来（更推荐使用INT8，虽然精度低，但是非常快），改名为my_model.cvimodel，再新建my_mud.mud文件，内容如下，改一下模型名称，改一下标签。</p>
<pre><code>[basic]
type = cvimodel
model = my_model.cvimodel

[extra]
model_type = yolo11
input_type = rgb
mean = 0, 0, 0
scale = 0.00392156862745098, 0.00392156862745098, 0.00392156862745098
labels = apple</code></pre>
<p>很容易报如下图的错：这是因为文件夹中放置的用于INT8转换的图片不符合上述的3点要求，所以你再仔细检查检查。然而此时精度bf16的cvimodel文件已经输出了，你要是不用INT8，就可以不理会这个报错。</p>
<p><img decoding="async" src="https://maixhub.com/public/sharing/39207-89286b77c64146a19629eb3841124b8e.png" alt="" /></p>
<p>（6）模型导入MaixCAM，打包为软件</p>
<p>打开Maixvision，将相机连接。在文件管理器内，新建my_project文件夹，将cvimodel和mud文件同时导入。</p>
<p>在电脑上新建test.py输入下面的代码，Maixvision打开该文件然后运行。</p>
<pre><code class="language-python">from maix import camera, display, image, nn, app

detector = nn.YOLO11(model="/root/my_project/my_mud.mud", dual_buff = True)

cam = camera.Camera(detector.input_width(), detector.input_height(), detector.input_format())
disp = display.Display()

while not app.need_exit():
    img = cam.read()
    objs = detector.detect(img, conf_th = 0.7, iou_th = 0.65)# 阈值for obj in objs:

        points = obj.get_obb_points()
        msg = f'{detector.labels[obj.class_id]}: {obj.score:.2f}, {obj.angle * 180:.1f}'
        img.draw_string(points[0], points[1] - 4, msg, color = image.COLOR_RED)
        detector.draw_pose(img, points, 8 if detector.input_width() &gt; 480 else 4, image.COLOR_RED, close=True)
# 打印识别框的信息print(obj)
    disp.show(img)</code></pre>
<p>如果报错“&#8217;maix._maix.nn.Object&#8217; object has no attribute &#8216;get_obb_points&#8217;”未找到get_obb_points这个函数，说明你相机内部的MaixPy版本低于4.9.3，一定要升级。</p>
]]></content:encoded>
					
					<wfw:commentRss>/maixcam%e4%bd%bf%e7%94%a8/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>WEB服务器、图床、FRP内穿——大成！</title>
		<link>/web%e6%9c%8d%e5%8a%a1%e5%99%a8%e3%80%81%e5%9b%be%e5%ba%8a%e3%80%81frp%e5%86%85%e7%a9%bf-%e5%a4%a7%e6%88%90%ef%bc%81/</link>
					<comments>/web%e6%9c%8d%e5%8a%a1%e5%99%a8%e3%80%81%e5%9b%be%e5%ba%8a%e3%80%81frp%e5%86%85%e7%a9%bf-%e5%a4%a7%e6%88%90%ef%bc%81/#respond</comments>
		
		<dc:creator><![CDATA[Antonio]]></dc:creator>
		<pubDate>Wed, 12 Mar 2025 20:02:29 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[博客]]></category>
		<guid isPermaLink="false">http://antonioz.asia/?p=173</guid>

					<description><![CDATA[历经两天，终于完成了WEB服务器应用，它终究成为了我满意的样子👍👍👍。 时间线 小插曲： 插曲虽小，耗时不少。 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>历经两天，终于完成了WEB服务器应用，它终究成为了我满意的样子<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f44d.png" alt="👍" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f44d.png" alt="👍" class="wp-smiley" style="height: 1em; max-height: 1em;" /><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f44d.png" alt="👍" class="wp-smiley" style="height: 1em; max-height: 1em;" />。</p>



<h3 class="wp-block-heading">时间线</h3>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<ul class="wp-block-list">
<li>Orangepi zero2W wordpress部署，感慨加载速度极慢——弃用</li>



<li>原内网穿透方案不适用，花生壳不让白嫖了，开始在<mark data-darkreader-inline-bgcolor="" style="background-color: rgba(0, 0, 0, 0); --darkreader-inline-bgcolor: var(--darkreader-background-00000000, rgba(0, 0, 0, 0));" class="has-inline-color has-luminous-vivid-amber-color">免费方案</mark>的域名访问界面加入<strong><em><mark data-darkreader-inline-bgcolor="" style="background-color: rgba(0, 0, 0, 0); --darkreader-inline-bgcolor: var(--darkreader-background-00000000, rgba(0, 0, 0, 0));" class="has-inline-color has-luminous-vivid-orange-color">跳转广告</mark></em></strong>了，等待10s极慢——弃用</li>



<li>从香橙派迁移Wordpress至NAS中
<ul class="wp-block-list">
<li>部分备份、迁移插件真不好用哈，还收费<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f926-200d-2642-fe0f.png" alt="🤦‍♂️" class="wp-smiley" style="height: 1em; max-height: 1em;" />，推荐——<strong><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-pale-cyan-blue-color">WPvivid备份插件</mark></strong></li>
</ul>
</li>



<li>寻找内网穿透替代方案
<ul class="wp-block-list">
<li>购买阿里云轻量级服务器（68一年！）</li>



<li>选择宝塔实例，安装FRP服务（FRPS服务端）——内网穿透方案</li>



<li>NAS安装mysql（Docker）</li>



<li>NAS部署FRPC客户端（Docker）</li>



<li>实现NAS IP内网穿透</li>
</ul>
</li>



<li>思考良久，还是直接在云服务器部署Wordpress更方便，宝塔一键部署Wordpress！</li>



<li>将已经购买一直未使用的域名进行ICP备案（不到12小时就完成了，工信部好评！）</li>



<li>WordPress媒体库一般，图片不好管理，于是——开干！
<ul class="wp-block-list">
<li>NAS上装了一个chevereto图床，上传壁纸、图片</li>



<li>NAS内穿后的访问效率还是有点低，给的公网服务器带宽不太够<img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f605.png" alt="😅" class="wp-smiley" style="height: 1em; max-height: 1em;" /></li>



<li>算了，云服务也装一个吧</li>



<li>提示：chevereto图床上传最大2M——更改php.ini可以设置上传文件最大内存</li>
</ul>
</li>



<li>主题不好看？推荐Argon，美化一下效果旧很OK了，没那么多花里胡哨的东西。</li>
</ul>



<ul class="wp-block-list">
<li>准备进行网站公安局备案&#8230;（待进行） 2025/3/13</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">小插曲：</h3>



<p>插曲虽小，耗时不少。（差不多一半时间花这儿了）</p>



<p>偶然看到Hexo方案的开源主题精美<a href="https://github.com/theme-shoka-x/hexo-theme-shokaX" data-type="link" data-id="https://github.com/theme-shoka-x/hexo-theme-shokaX">（<em>shokax二次元</em>）</a>，遂考虑替换Wordpress方案，结果就是一系列bug，修bug。（吐槽一句，npm真难用，比apt、pnmp、yarn等包管理器难用多了）</p>



<p>终于完成的时候，发现shokax不太适合我这类懒人，很多功能、CCS效果等都需要自己改代码    <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f62b.png" alt="😫" class="wp-smiley" style="height: 1em; max-height: 1em;" />！</p>



<p>于是——弃用！</p>
]]></content:encoded>
					
					<wfw:commentRss>/web%e6%9c%8d%e5%8a%a1%e5%99%a8%e3%80%81%e5%9b%be%e5%ba%8a%e3%80%81frp%e5%86%85%e7%a9%bf-%e5%a4%a7%e6%88%90%ef%bc%81/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Openmediavault-树莓派4B</title>
		<link>/openmediavault-%e6%a0%91%e8%8e%93%e6%b4%be4b/</link>
					<comments>/openmediavault-%e6%a0%91%e8%8e%93%e6%b4%be4b/#respond</comments>
		
		<dc:creator><![CDATA[Antonio]]></dc:creator>
		<pubDate>Fri, 06 Dec 2024 15:04:18 +0000</pubDate>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[博客]]></category>
		<guid isPermaLink="false">http://192.168.31.64/?p=154</guid>

					<description><![CDATA[树莓派4B NAS Jellyfin SMB文件服务器：]]></description>
										<content:encoded><![CDATA[
<h1 class="wp-block-heading">树莓派4B NAS Jellyfin</h1>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>不要让你的树莓派吃灰啦，搭一个简易NAS、文件服务器，让你的文件处理更加丝滑吧！ </p>



<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>



<p>基于树莓派stable lite系统搭建的OMV系统：</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1918" height="956" data-id="136" src="/wp-content/uploads/2024/12/屏幕截图-2024-12-06-223154.png" alt="" class="wp-image-136"/></figure>
</figure>



<p></p>



<p>家庭多媒体影院 Jellyfin：</p>
</blockquote>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1916" height="953" src="/wp-content/uploads/2024/12/屏幕截图-2024-12-06-223505.png" alt="" class="wp-image-138"/></figure>



<p></p>



<p>SMB文件服务器：</p>



<ul class="wp-block-list">
<li>手机端可直接下载CX文件处理器 通过SMB协议访问</li>



<li>PC端可直接通过windows文件管理器 网络 访问</li>
</ul>



<pre class="wp-block-code"><code>\\主机名.域名\共享文件夹名\
\\IP地址\共享文件夹名\</code></pre>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-2 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="690" height="440" data-id="139" src="/wp-content/uploads/2024/12/屏幕截图-2024-12-06-223732.png" alt="" class="wp-image-139"/></figure>
</figure>
]]></content:encoded>
					
					<wfw:commentRss>/openmediavault-%e6%a0%91%e8%8e%93%e6%b4%be4b/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Markdown！</title>
		<link>/markdown%ef%bc%81/</link>
					<comments>/markdown%ef%bc%81/#respond</comments>
		
		<dc:creator><![CDATA[Antonio]]></dc:creator>
		<pubDate>Sat, 21 Sep 2024 19:55:34 +0000</pubDate>
				<category><![CDATA[博客]]></category>
		<guid isPermaLink="false">http://192.168.31.64/?p=118</guid>

					<description><![CDATA[不到10个语法，让你的爱上写笔记 参考：Markdown 基本语法 &#124; Markdown 官方教程]]></description>
										<content:encoded><![CDATA[
<h1 class="wp-block-heading">不到10个语法，让你的爱上写笔记</h1>



<p>参考：<a href="https://markdown.com.cn/basic-syntax/">Markdown 基本语法 | Markdown 官方教程</a></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<pre class="wp-block-code"><code># Markdown语法指南

## 标题
使用 # 符号，后跟空格：
# 一级标题
## 二级标题
### 三级标题

也可以使用 = 或 - 来创建一级和二级标题：
一级标题
=========
二级标题
---------

## 段落和换行
段落之间空一行。
行末加两个空格
实现换行。

## 强调
*斜体* 或 _斜体_
**粗体** 或 __粗体__
***粗斜体*** 或 ___粗斜体___

## 引用
> 这是一个引用
>> 这是嵌套引用

> - 引用中的列表项

## 列表
无序列表：
- 项目1
- 项目2
  - 子项目2.1
  - 子项目2.2

有序列表：
1. 第一项
2. 第二项
   1. 子项2.1
   2. 子项2.2

## 代码
行内代码：`code`

代码块：
```python
def hello_world():
    print("Hello, World!")
</code></pre>
]]></content:encoded>
					
					<wfw:commentRss>/markdown%ef%bc%81/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>RTOS（计划中）</title>
		<link>/rtos%ef%bc%88%e8%ae%a1%e5%88%92%e4%b8%ad%ef%bc%89/</link>
					<comments>/rtos%ef%bc%88%e8%ae%a1%e5%88%92%e4%b8%ad%ef%bc%89/#respond</comments>
		
		<dc:creator><![CDATA[Antonio]]></dc:creator>
		<pubDate>Sun, 25 Aug 2024 13:59:51 +0000</pubDate>
				<category><![CDATA[博客]]></category>
		<category><![CDATA[笔记]]></category>
		<guid isPermaLink="false">http://9544061et3ky.vicp.fun/?p=92</guid>

					<description><![CDATA[实时操作系统： 概念：进程、线程、栈、堆、信号量、互斥量、互斥锁 RT-Thread 1.移植流程： 2.常用 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>实时操作系统：</p>



<p>概念：进程、线程、栈、堆、信号量、互斥量、互斥锁</p>



<h2 class="wp-block-heading">RT-Thread</h2>



<p>1.移植流程：</p>



<ul class="wp-block-list">
<li>下载RT-Thread源码</li>



<li>&#8230;</li>



<li></li>
</ul>



<p>2.常用函数</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>/rtos%ef%bc%88%e8%ae%a1%e5%88%92%e4%b8%ad%ef%bc%89/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>一些常用算法（LeetCode.面）</title>
		<link>/%e4%b8%80%e4%ba%9b%e5%b8%b8%e7%94%a8%e7%ae%97%e6%b3%95%ef%bc%88leetcode-%e9%9d%a2%ef%bc%89/</link>
					<comments>/%e4%b8%80%e4%ba%9b%e5%b8%b8%e7%94%a8%e7%ae%97%e6%b3%95%ef%bc%88leetcode-%e9%9d%a2%ef%bc%89/#respond</comments>
		
		<dc:creator><![CDATA[Antonio]]></dc:creator>
		<pubDate>Sat, 17 Aug 2024 15:12:35 +0000</pubDate>
				<category><![CDATA[博客]]></category>
		<category><![CDATA[笔记]]></category>
		<category><![CDATA[leetcode]]></category>
		<category><![CDATA[算法]]></category>
		<guid isPermaLink="false">http://192.168.1.8/?p=80</guid>

					<description><![CDATA[罗列一些常用算法（不定期更新）： 1.双指针-快慢指针 2.摩尔投票算法（求众数）]]></description>
										<content:encoded><![CDATA[
<p>罗列一些常用算法（不定期更新）：</p>



<ul class="wp-block-list">
<li>双指针-快慢指针</li>



<li>摩尔投票算法</li>
</ul>



<p>1.双指针-快慢指针</p>



<pre class="wp-block-code"><code>// 时间复杂度：O(n)
// 空间复杂度：O(1)
class Solution {
public:
int removeElement(vector&lt;int>&amp; nums, int val) {
int slowIndex = 0;
for (int fastIndex = 0; fastIndex &lt; nums.size(); fastIndex++) {
if (val != nums&#91;fastIndex]) {
nums&#91;slowIndex++] = nums&#91;fastIndex];
 }
 }
return slowIndex;
 }
};</code></pre>



<p>2.摩尔投票算法（求众数）</p>



<pre class="wp-block-code"><code>// 摩尔投票算法
int majorityElement(int* nums, int numsSize) {
    int count = 0;
    int candidate = 0;

    for (int i = 0; i &lt; numsSize; i++) {
        if (count == 0) {
            candidate = nums&#91;i];
        }
        count += (nums&#91;i] == candidate) ? 1 : -1;
    }
    return candidate;
} </code></pre>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>/%e4%b8%80%e4%ba%9b%e5%b8%b8%e7%94%a8%e7%ae%97%e6%b3%95%ef%bc%88leetcode-%e9%9d%a2%ef%bc%89/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>XIAOMI10S搭配Google Camera拍摄</title>
		<link>/xiaomi10s%e6%90%ad%e9%85%8dgoogle-camera%e6%8b%8d%e6%91%84/</link>
					<comments>/xiaomi10s%e6%90%ad%e9%85%8dgoogle-camera%e6%8b%8d%e6%91%84/#respond</comments>
		
		<dc:creator><![CDATA[Antonio]]></dc:creator>
		<pubDate>Sun, 04 Aug 2024 11:27:21 +0000</pubDate>
				<category><![CDATA[博客]]></category>
		<category><![CDATA[说说]]></category>
		<guid isPermaLink="false">http://9544061et3ky.vicp.fun/?p=37</guid>

					<description><![CDATA[使用几年前的手机搭配谷歌相机的算法拍出来的效果依旧惊人：]]></description>
										<content:encoded><![CDATA[
<p>使用几年前的手机搭配谷歌相机的算法拍出来的效果依旧惊人：</p>



<p></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="881" src="/wp-content/uploads/2024/08/1722770282817-1024x881.jpg" alt="" class="wp-image-38" srcset="/wp-content/uploads/2024/08/1722770282817-1024x881.jpg 1024w, /wp-content/uploads/2024/08/1722770282817-300x258.jpg 300w, /wp-content/uploads/2024/08/1722770282817-768x661.jpg 768w, /wp-content/uploads/2024/08/1722770282817-1536x1322.jpg 1536w, /wp-content/uploads/2024/08/1722770282817-2048x1763.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="881" src="/wp-content/uploads/2024/08/1722770282825-1024x881.jpg" alt="" class="wp-image-54" srcset="/wp-content/uploads/2024/08/1722770282825-1024x881.jpg 1024w, /wp-content/uploads/2024/08/1722770282825-300x258.jpg 300w, /wp-content/uploads/2024/08/1722770282825-768x661.jpg 768w, /wp-content/uploads/2024/08/1722770282825-1536x1322.jpg 1536w, /wp-content/uploads/2024/08/1722770282825-2048x1763.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="881" src="/wp-content/uploads/2024/08/卡皮巴拉-1024x881.jpg" alt="" class="wp-image-56" srcset="/wp-content/uploads/2024/08/卡皮巴拉-1024x881.jpg 1024w, /wp-content/uploads/2024/08/卡皮巴拉-300x258.jpg 300w, /wp-content/uploads/2024/08/卡皮巴拉-768x661.jpg 768w, /wp-content/uploads/2024/08/卡皮巴拉-1536x1322.jpg 1536w, /wp-content/uploads/2024/08/卡皮巴拉-2048x1763.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="881" src="/wp-content/uploads/2024/08/1722770282811-1024x881.jpg" alt="" class="wp-image-57" srcset="/wp-content/uploads/2024/08/1722770282811-1024x881.jpg 1024w, /wp-content/uploads/2024/08/1722770282811-300x258.jpg 300w, /wp-content/uploads/2024/08/1722770282811-768x661.jpg 768w, /wp-content/uploads/2024/08/1722770282811-1536x1322.jpg 1536w, /wp-content/uploads/2024/08/1722770282811-2048x1763.jpg 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
]]></content:encoded>
					
					<wfw:commentRss>/xiaomi10s%e6%90%ad%e9%85%8dgoogle-camera%e6%8b%8d%e6%91%84/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
