[转] 利用Matlab提取图片中曲线数据
原文地址 网易博客
前一段时间看到一篇文章"利用Matlab提取图图片中的数据",觉得思路挺好,遂下载下来研究了一番,发现作者所编写的程序没有考虑原始图片非水 平放置的情况,而实际扫描图片时,将图片完全放置水平难度较大... 同时作者也没有考虑对数坐标的情况,且程序GUI界面不太人性化,操作有点不习惯。因此借着作者良好意愿,对其程序进行了改进~
2011-6-9
考虑一张非水平无变形的曲线图,现将其曲线数据取出来,步骤如下:
- 在坐标轴上取三点以定位坐标系。如图中红色点所示。
- 在曲线上选取若干个点,如图中蓝色点所示。
- 设定坐标轴选取点x和y的实际值。
- 选取坐标系类型。
- 变换。
- 保存数据。
- 数据后处理。
在 变换过程中程序首先计算(xi,yi)到(x1,y1)和(x2,y2)所组成的y轴的距离Δx,同样的方法计算Δy,当然Δx和Δy是图片的像素值。接 下来计算每个像素点所对应实际坐标值。对于线性x轴,比例系数为(Xmax-Xmin)/(sqrt((x1-x0)^2)+(y1-y0)^2),同样 对于线性y轴,比例系数(Ymax-Ymin)/(sqrt((x0-x2)^2)+(y0-y2)^2)。这样即可求出每个点的实际坐标值
Xi=Δx *(Xmax-Xmin)/(sqrt((x1-x0)^2)+(y1-y0)^2)+Xmin
Yi=Δy *(Ymax-Ymin)/(sqrt((x0-x2)^2)+(y0-y2)^2)+Ymin
对数坐标的变换关系类似
Xi=10^(log10(Xmin)+Δx *(log10(Xmax)-log10(Xmin))/(sqrt((x1-x0)^2)+(y1-y0)^2))
Yi= 10^(log10(Ymin)+Δy *(log10(Ymax)-log10(Ymin))/(sqrt((x0-x2)^2)+(y0-y2)^2))
具体操作说明
1.导入图片。
2.定位坐标系。按del键可删除上一个点
3.定位曲线。
4.设置变换参数。
5.变换。单击[变换]按钮后,弹出变换后的结果。
6.保存数据。
- 数据后处理
导入数据,假定导入后变量名为test
在Matlab Command窗口中输入 x=test(:,1);y=test(:,2); cftool;弹出曲线拟合工具箱
创建数据集
拟合数据
程序流程
数据初始化程序段:
|
handles.optMode='zoom'; handles.linedata=[]; handles.dataCount=0; handles.datah=[]; handles.axesdata=[]; handles.axesCount=0; handles.axesh=[]; handles.newdata=[]; himage=findobj('tag','axes1'); axes(himage); |
选定图片程序段:
|
[file,path]=uigetfile({'*.jpg','图片文件(*.jpg)';'*.*','所有文件'},'请选择待分析图片...'); if ~isequal(file, 0) cd(path); set(handles.fileEdit,'String',[path file]); end |
导入图像程序段:
|
handles.dataCount=0; handles.axesCount=0; image_temp=imread(get(handles.fileEdit,'string')); imshow(image_temp); %read and show handles.ximage=size(image_temp,2); handles.yimage=size(image_temp,1); guidata(hObject,handles); % 更新状态栏 h=findobj('tag','edit7'); set(h,'String',num2str(handles.dataCount)); ZoomPB_Callback(hObject, eventdata, handles); |
点选取程序段:
|
p=get(gca,'CurrentPoint'); switch handles.optMode case ('pickdata') if p(end,1)>0&&p(end,1)<handles.ximage&&p(end,2)>0&&p(end,2)<handles.yimage handles.dataCount=handles.dataCount+1; handles.linedata(handles.dataCount,:)=p(end,1:2); set(handles.countEdit,'String',num2str(handles.dataCount)); hold on; handles.datah(handles.dataCount,1)=plot(p(end,1),p(end,2),'b*'); guidata(hObject, handles); end case ('pickaxes') if p(end,1)>0&&p(end,1)<handles.ximage&&p(end,2)>0&&p(end,2)<handles.yimage&&handles.axesCount<3 handles.axesCount=handles.axesCount+1; handles.axesdata(handles.axesCount,:)=p(end,1:2); set(handles.countEdit,'String',num2str(handles.axesCount)); hold on; handles.axesh(handles.axesCount,1)=plot(p(end,1),p(end,2),'r+'); guidata(hObject, handles); end end |
点删除程序段:
|
switch get(gcf,'CurrentKey') case('space') PickDataPB_Callback(hObject, eventdata, handles); case('z') ZoomPB_Callback(hObject, eventdata, handles); case('m') PanPB_Callback(hObject, eventdata, handles); case('delete') switch handles.optMode case ('pickdata') if(handles.dataCount>0) delete(handles.datah(handles.dataCount,1)); handles.dataCount=handles.dataCount-1; set(handles.countEdit,'String',num2str(handles.dataCount)); guidata(hObject, handles); end case ('pickaxes') if(handles.axesCount>0) delete(handles.axesh(handles.axesCount,1)); handles.axesCount=handles.axesCount-1; set(handles.countEdit,'String',num2str(handles.axesCount)); guidata(hObject, handles); end end end |
坐标轴定标及坐标变换:
|
%提取坐标信息 xmin=str2double(get(handles.xminEdit,'string')); xmax=str2double(get(handles.xmaxEdit,'string')); ymin=str2double(get(handles.yminEdit,'string')); ymax=str2double(get(handles.ymaxEdit,'string')); xType=get(handles.xTypePM,'value'); yType=get(handles.yTypePM,'value'); %数据分类整理 tmpaxes=handles.axesdata; ct=6; [c,r]=max(tmpaxes(:,1)); axesxP=tmpaxes(r,:); ct=ct-r; [c,r]=min(tmpaxes(:,2)); axesyP=tmpaxes(r,:); ct=ct-r; originP=handles.axesdata(ct,:); Data=zeros(handles.dataCount,2); data_new=zeros(handles.dataCount,2); %起点归零和坐标调整 for i=1:handles.dataCount Data(i,2)=det([originP-axesxP;handles.linedata(i,:)-axesxP])/norm(originP-axesxP); Data(i,1)=-det([originP-axesyP;handles.linedata(i,:)-axesyP])/norm(originP-axesyP); end switch xType data_new(:,1)=Data(:,1)/pdist([originP;axesxP]); %坐标归一化 data_new(:,1)=xmin+data_new(:,1)*(xmax-xmin); %数据还原 data_new(:,1)=Data(:,1)/pdist([originP;axesxP]); %坐标归一化 data_new(:,1)=10.^(log10(xmin)+data_new(:,1)*(log10(xmax)-log10(xmin))); end switch yType data_new(:,2)=Data(:,2)/pdist([originP;axesyP]); data_new(:,2)=ymin+data_new(:,2)*(ymax-ymin); case 2' data_new(:,2)=Data(:,2)/pdist([originP;axesyP]); %坐标归一化 data_new(:,2)=10.^(log10(ymin)+data_new(:,2)*(log10(ymax)-log10(ymin))); %数据还原 end figure(3); if xType==2 if yType==2 loglog(data_new(:,1),data_new(:,2),'b*'); else semilogx(data_new(:,1),data_new(:,2),'b*'); end else if yType==2 semilogy(data_new(:,1),data_new(:,2),'b*'); else plot(data_new(:,1),data_new(:,2),'b*'); end end handles.newdata=data_new; guidata(hObject,handles); |
数据保存代码段:
|
[file,path]=uiputfile({'*.txt','文本文件(*.txt)';'*.*','所有文件'},'请选择待分析图片...'); if ~isequal(file, 0) idata=handles.newdata; save([path file],'idata','-ascii'); end |
参考文献:
[转] 利用Matlab提取图片中曲线数据的更多相关文章
- 用matlab提取jpg曲线数据或者jpg图片重新复原
I = imread('111.jpg');%读取处理好的图片,必须是严格坐标轴线为边界的图片 I=rgb2gray(I); %灰度变化 I(I>200)=255; %二值化 I(I<=2 ...
- MATLAB 提取图片中的曲线数据重新画图
注意: 本代码是由[MATLAB R2015b win 32位]编写. 先上代码: %% 清空变量 clear all; clc; %% 取点之后趋势是对的,也就是点与点之间的比例是对的,但是每个点的 ...
- 利用matlab自带函数快速提取二值图像的图像边缘 bwperim函数
clear all;close all;clc; I = imread('rice.png'); I = im2bw(I); J = bwperim(I); % 提取二值图像图像边缘 figure ...
- 模式识别:利用MATLAB生成模式类
近期開始了模式识别的学习,在此之前须要对模式和模式类的概念有一个了解,这里使用MATLAB实现一些模式类的生成.在此之前,引用百科上对于模式识别和模式类的定义.也算加深以下了解: 模式识别(Patte ...
- 利用AMPScript获取Uber用户数据的访问权限
现代项目开发和资产管理方法正在不停地快速变化.在这场创新和扩张的竞赛中,新资产被迅速部署并暴露于公共互联网,已有资产也在不断发展. 要跟上这个不断变化的攻击面是很难的,更不用说保护这些应用程序和系统了 ...
- Android 利用二次贝塞尔曲线模仿购物车加入物品抛物线动画
Android 利用二次贝塞尔曲线模仿购物车加入物品抛物线动画 0.首先.先给出一张效果gif图. 1.贝塞尔曲线原理及相关公式參考:http://www.jianshu.com/p/c0d7ad79 ...
- Python利用xlutils统计excel表格数据
假设有像上这样一个表格,里面装满了各式各样的数据,现在要利用模板对它进行统计每个销售商的一些数据的总和.模板如下: 代码开始: 1 #!usr/bin/python3 2 # -*-coding=ut ...
- 利用Matlab快速绘制栅格地图
代码演示 % 基于栅格地图的机器人路径规划算法 % 第1节:利用Matlab快速绘制栅格地图 clc clear close all %% 构建颜色MAP图 cmap = [1 1 1; ... % ...
- CANN算子:利用迭代器高效实现Tensor数据切割分块处理
摘要:本文以Diagonal算子为例,介绍并详细讲解如何利用迭代器对n维Tensor进行基于位置坐标的大批量数据读取工作. 本文分享自华为云社区<CANN算子:利用迭代器高效实现Tensor数据 ...
随机推荐
- 从一段字符串中去除数字的shell方法
- 【BZOJ】1571: [Usaco2009 Open]滑雪课Ski
[算法]动态规划 [题解]yy出了O(1w log 1w)的算法. 将雪坡排序预处理出g[i]表示能力值为i的最短时长雪坡. 这样就可以定义work(t,c)表示时长t能力c的最多滑雪数量,work( ...
- NGINX: 限制连接的实践 (Defense DDOS)
参考: [ nginx防止DDOS攻击配置 ] 关于限制用户连接,Nginx 提供的模块: [ ngx_http_limit_req_module ] [ ngx_http_limit_conn_mo ...
- 生成器版本的文件MD5校验
生成器是一个可迭代的对象,可以对可迭代的对象进行便利,比如字符串.列表等,都是可迭代对象 def f(n): for i in range(n): yield i 特点: 1.当调用这个函数的 ...
- 【反演复习计划】【COGS2431】爱蜜莉雅的求助
出题人怎么这么不认真啊==明明官方译名是爱蜜莉雅…… 而且我们爱蜜莉雅碳是有英文名哒!是Emilia.你那个aimiliya我实在是无力吐槽…… 不过抱图跑23333首先这很像约数个数和函数诶!但是唯 ...
- 聊聊C++模板函数与非模板函数的重载
前言 函数重载在C++中是一个很重要的特性.之所以有了它才有了操作符重载.iostream.函数子.函数适配器.智能指针等非常有用的东西. 平常在实际的应用中多半要么是模板函数与模板函数重载,或者是非 ...
- 【 Linux 】Keepalived实现双主模型高可用集群
要求: 1. 两台web服务器安装wordpress,数据库通过nfs共享 2. 使用keepalived实现双主模型 环境: 主机: 系统:CentOS6.7 x64 ...
- 《Java编程思想》笔记 第六章 访问权限控制
1.编译单元 一个 编译单元即 .java 文件 内只能有一个 public 类 且该文件名必须与public 类名 完全一致. 编译单元内也可以没有public类 文件名可随意. 2. 包:库单元 ...
- easyUI之datagrid
对于easyUI中的datagrid组件,继承自pannel...,因此有其自己的组件,还有继承过来的属性. 1.width:指定其宽度 2.title:指定标题 3.iconCls:指定图标.见上图 ...
- HDU 多校1.11