尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
MATLAB 图像标注实战:用 textarrow 与 annotation 精准标记数据点
1. 为什么 MATLAB 科研绘图需要代码化标注做科研绘图时很多人习惯用 Data Cursor 手动点一下曲线把关键点的坐标读出来再截图放进论文或笔记里。这个流程在单张图上没问题但一旦遇到下面几种情况就会很痛苦图要批量生成、图要反复修改、图要用 MATLAB 自带的 Publish 导出成带说明的文档或者图要交给合作者复现。手动标注没法写进脚本换一台机器、换一组数据就得重新点一遍。textarrow和annotation就是解决这个问题的。它们属于 MATLAB 的 annotation 系列函数作用是在 figure 的归一化坐标系里画箭头、文本框、椭圆、矩形等注释对象。和text()直接按数据坐标放文字不同annotation用的是 figure 归一化坐标范围固定在 0 到 1 之间横纵都相对整个绘图窗口所以它不会随坐标轴缩放而漂移适合做“钉死”在画面某个位置的标注。这篇内容面向的是需要把标注写进代码、能一键复现的科研绘图场景。核心要解决三件事箭头位置怎么定、textarrow参数怎么填、标注偏了怎么调。我会给出一套可以直接复制的代码骨架再演示怎么验证箭头是否真的指向了目标数据点。如果你平时用 MATLAB 画 sin、实验曲线、频谱图并需要标出峰值或特定采样点这套方法能直接套用。2. 前置准备TaoToken 与 MATLAB 环境标注本身是纯 MATLAB 功能不需要联网。但如果你在写脚本、查文档、让模型帮你生成或改写标注代码时想更顺手可以先把 TaoToken 的接入配好。它的官网是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 。下面这些 deep link 在需要时可以直接用模型对话https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewriteCoding Planhttps://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite控制台https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewriteAPI Keyshttps://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite接入文档https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewriteClaudeCodeAnthropichttps://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecodeutm_campaignrewriteMATLAB 这边只需要基础环境R2016b 及以上都支持annotation(textarrow,...)我实测 R2021b 和 R2023a 行为一致。不需要额外工具箱annotation属于 MATLAB 核心图形函数。建议把 figure 的Units保持默认避免归一化坐标和像素坐标混用导致箭头跑偏。3. 可复制配置textarrow 标注代码骨架先给一个最小可运行骨架。思路是画曲线找到要标注的数据点索引算出它在 figure 归一化坐标里的位置再用annotation(textarrow, x, y, String, ...)画箭头。close all; x 0:0.01:2*pi; y sin(x); figure(Color,w); plot(x, y, LineWidth, 1.5); grid on; % 目标点x 2.66 处的采样点 targetX 2.66; index find(abs(x - targetX) 1e-6, 1); px x(index); py y(index); % 把数据坐标转成 figure 归一化坐标 ax gca; axPos ax.Position; % 坐标轴在 figure 中的位置 [left bottom width height] xNorm axPos(1) axPos(3) * (px - ax.XLim(1)) / diff(ax.XLim); yNorm axPos(2) axPos(4) * (py - ax.YLim(1)) / diff(ax.YLim); % 箭头起点稍微偏移避免压住曲线 arrowStart [xNorm 0.08, yNorm 0.10]; annotation(textarrow, ... [arrowStart(1), xNorm], ... [arrowStart(2), yNorm], ... String, sprintf(x %.2f, y %.3f, px, py), ... FontSize, 11, ... Color, r);这段代码的关键在坐标转换。annotation的坐标不是数据坐标而是 figure 归一化坐标所以不能直接把px、py丢进去。ax.Position给出坐标轴在 figure 里的位置ax.XLim、ax.YLim给出数据范围两者一组合就能把任意数据点映射到 0 到 1 的归一化空间。这样即使你改了坐标轴范围或 figure 大小箭头依然指向同一个数据点。textarrow的前两个参数分别是 x 和 y 的坐标数组格式是[起点, 终点]。终点就是箭头尖指向的位置起点是文字框所在的位置。String是显示在起点附近的文本。把起点放在终点的右上方箭头就会从右上指向左下视觉上比较自然。4. 验证请求与成功结果跑完上面的代码你会看到一条正弦曲线在 x 约等于 2.66 的位置有一个红色箭头箭头尖精确落在曲线上旁边显示x 2.66, y 0.457。这就是成功结果。验证标注是否准确可以用一个简单办法在箭头终点位置再画一个标记点看两者是否重合。hold on; plot(px, py, ko, MarkerSize, 8, LineWidth, 1.5);如果黑色圆圈和箭头尖完全重合说明坐标转换没问题。如果箭头尖偏了通常是两个原因一是ax.Position在plot之后被改动过二是用了axis tight或axis equal改变了坐标轴比例。解决办法是在所有坐标轴设置完成之后再计算归一化坐标顺序不能反。再给一个多标注点的例子标出正弦曲线的峰值和零点close all; x 0:0.01:2*pi; y sin(x); figure(Color,w); plot(x, y, LineWidth, 1.5); grid on; ax gca; axPos ax.Position; points [pi/2, 1; pi, 0; 3*pi/2, -1]; labels {峰值 y1, 零点 y0, 谷值 y-1}; for k 1:size(points, 1) px points(k, 1); py points(k, 2); xNorm axPos(1) axPos(3) * (px - ax.XLim(1)) / diff(ax.XLim); yNorm axPos(2) axPos(4) * (py - ax.YLim(1)) / diff(ax.YLim); annotation(textarrow, ... [xNorm 0.06, xNorm], ... [yNorm 0.08, yNorm], ... String, labels{k}, ... FontSize, 10, ... Color, [0.85 0.1 0.1]); end运行后三个箭头分别指向峰值、零点和谷值文字不重叠。如果文字框互相压住可以给每个点设置不同的起点偏移量比如峰值往右上、谷值往右下。5. 本篇常见错排查第一个高频错误是箭头位置整体偏移。原因通常是annotation在plot之前调用或者ax.Position读取的是旧值。正确顺序是先plot再grid、axis、xlim、ylim全部设置完最后读ax.Position并计算归一化坐标。只要坐标轴还在变归一化坐标就得重算。第二个错误是textarrow报“坐标超出范围”。annotation的坐标必须在 0 到 1 之间如果你直接把数据坐标传进去比如[2.66, 2.66]就会报错或箭头跑到画面外。记住一定要做归一化转换。第三个坑是String里的数值格式。用num2str默认会输出很多位小数图里显得很乱。建议用sprintf(%.2f, value)控制精度。如果标注的是整数采样点用%d更干净。第四个问题是箭头被坐标轴裁剪。annotation对象默认在 figure 层不会被 axes 裁剪但如果起点坐标算到了 0 以下或 1 以上箭头就看不见了。检查方法是把起点坐标打印出来确认都在 0 到 1 之间。第五个常见误解是以为textarrow会随数据缩放自动更新。不会。annotation是静态的你改了xlim或ylim之后必须重新计算并重画。如果图要频繁改范围建议把标注逻辑封装成函数每次改完范围调用一次。6. 继续深入把标注写进可复用函数实际科研里标注逻辑最好封装起来避免每次手算坐标。下面这个函数接收数据点坐标和标签自动完成归一化和标注function addTextArrow(ax, px, py, label, offset) if nargin 5 offset [0.06, 0.08]; end axPos ax.Position; xNorm axPos(1) axPos(3) * (px - ax.XLim(1)) / diff(ax.XLim); yNorm axPos(2) axPos(4) * (py - ax.YLim(1)) / diff(ax.YLim); annotation(textarrow, ... [xNorm offset(1), xNorm], ... [yNorm offset(2), yNorm], ... String, label, ... FontSize, 10, ... Color, [0.85 0.1 0.1]); end调用时先画图、设好坐标轴再传gca和目标点close all; x 0:0.01:2*pi; y sin(x); figure(Color,w); plot(x, y, LineWidth, 1.5); grid on; xlim([0, 2*pi]); ylim([-1.2, 1.2]); addTextArrow(gca, pi/2, 1, 峰值); addTextArrow(gca, pi, 0, 零点, [0.06, -0.12]); addTextArrow(gca, 3*pi/2, -1, 谷值, [0.06, -0.10]);这样每次只需要传数据点和标签坐标转换和箭头绘制都自动完成。如果标注点很多还可以把points和labels做成数组循环调用。实测下来这套骨架在批量生成几十张图时特别省事改数据不用重新点标注。如果你在写脚本时需要让模型帮忙生成或改写这类标注代码可以用模型对话入口 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 快速验证长期做科研编码和 Agent 工作流的话Coding Plan https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 更合适需要管理密钥就去 API Keys https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 接入细节看文档 https://taotoken.net/api?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。
RELATED

相关推荐

IntelliJ IDEA 2026.1 EAP 3 紧急发布:AI 能力再加强,回收站终于有了!

IntelliJ IDEA 2026.1 EAP 3 紧急发布:AI 能力再加强,回收站终于有了!

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/9/29 20:40:44
【小白也能轻松用】OpenClaw v2.7.9 部署实战:Windows 下用 TaoToken 统一 Key 打通 API 通道(含最新安装包)

【小白也能轻松用】OpenClaw v2.7.9 部署实战:Windows 下用 TaoToken 统一 Key 打通 API 通道(含最新安装包)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/9/29 20:40:44
数据流架构:AI芯片的范式革命与工程落地指南

数据流架构:AI芯片的范式革命与工程落地指南

1. 为什么HotChips成了AI芯片架构师的“年度体检报告”去年在HotChips 35现场,我坐在台下听Groq的LPU架构演讲时,后排两位工程师的对话让我记到现在:“这哪是芯片发布会,分明是IC设计圈的CT扫描——照一次,就知道你家数…

📅 2026/9/29 20:40:44
MORE NEWS

更多资讯

📰

多模态大模型怎么用于测试?只回答“看截图找Bug”,面试基本就说浅了:用 TaoToken 统一 Key 打通 Playwright 视觉回归链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

SpringBoot+Vue前后端分离雪具商城实战:从部署到联调全流程

前阵子帮学生改了一套前后端分离的雪具销售系统,技术栈就是SpringBootVueMyBatisMySQL。改完代码又顺手把部署流程从头跑了一遍,结果发现很多拿着源码就能写CRUD的同学,卡在部署和联调上:本地启动连不上MySQL、前后端接口对不齐、…

📰

选茶壶不踩坑:紫砂石瓢、德化白瓷、粗陶煮茶壶三款实用推荐

选茶壶这事,说难不难,说简单也不简单。我经手过挺多茶器,也替朋友选过不少送人的壶,这行当里看多了,反而觉得“闭眼入”三个字是最难做到的——市面上的壶,从几十块的机制壶到几万块的手工壶,中…

📰

Cabinet终极指南:AI优先的自托管知识库与创业操作系统全景解析

Cabinet终极指南:AI优先的自托管知识库与创业操作系统全景解析 【免费下载链接】cabinet AI-first knowledge base and startup OS 项目地址: https://gitcode.com/gh_mirrors/cabinet3/cabinet 🗄️ Cabinet 是一个 AI 优先(AI-first…

📰

ArcGIS 10.1 Python 编程秘籍(二):用 arcpy 游标与地理处理构建可复用脚本骨架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

流量入口迁移到 AI 之后:GEO 优化的五个实操要点

过去两年,内容团队最常问的问题从“怎么排到百度第一页”变成了“怎么被 ChatGPT 提到”。这两个问题看似只差一个平台,背后却是完全不同的分发机制:搜索引擎给的是十来条蓝色链接,用户自己挑;生成式引擎给的是一段整合…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬