原文地址 网易博客

前一段时间看到一篇文章"利用Matlab提取图图片中的数据",觉得思路挺好,遂下载下来研究了一番,发现作者所编写的程序没有考虑原始图片非水 平放置的情况,而实际扫描图片时,将图片完全放置水平难度较大... 同时作者也没有考虑对数坐标的情况,且程序GUI界面不太人性化,操作有点不习惯。因此借着作者良好意愿,对其程序进行了改进~

2011-6-9

shanyunh@QQ.com

考虑一张非水平无变形的曲线图,现将其曲线数据取出来,步骤如下:

  1. 在坐标轴上取三点以定位坐标系。如图中红色点所示。
  2. 在曲线上选取若干个点,如图中蓝色点所示。
  3. 设定坐标轴选取点x和y的实际值。
  4. 选取坐标系类型。
  5. 变换。
  6. 保存数据。
  7. 数据后处理。

    在 变换过程中程序首先计算(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.保存数据。

  8. 数据后处理

    导入数据,假定导入后变量名为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

参考文献:

1.基于Matlab的图像曲线数据提取方法

2.一种利用Matlab提取图像中曲线的新方法

[转] 利用Matlab提取图片中曲线数据的更多相关文章

  1. 用matlab提取jpg曲线数据或者jpg图片重新复原

    I = imread('111.jpg');%读取处理好的图片,必须是严格坐标轴线为边界的图片 I=rgb2gray(I); %灰度变化 I(I>200)=255; %二值化 I(I<=2 ...

  2. MATLAB 提取图片中的曲线数据重新画图

    注意: 本代码是由[MATLAB R2015b win 32位]编写. 先上代码: %% 清空变量 clear all; clc; %% 取点之后趋势是对的,也就是点与点之间的比例是对的,但是每个点的 ...

  3. 利用matlab自带函数快速提取二值图像的图像边缘 bwperim函数

      clear all;close all;clc; I = imread('rice.png'); I = im2bw(I); J = bwperim(I); % 提取二值图像图像边缘 figure ...

  4. 模式识别:利用MATLAB生成模式类

    近期開始了模式识别的学习,在此之前须要对模式和模式类的概念有一个了解,这里使用MATLAB实现一些模式类的生成.在此之前,引用百科上对于模式识别和模式类的定义.也算加深以下了解: 模式识别(Patte ...

  5. 利用AMPScript获取Uber用户数据的访问权限

    现代项目开发和资产管理方法正在不停地快速变化.在这场创新和扩张的竞赛中,新资产被迅速部署并暴露于公共互联网,已有资产也在不断发展. 要跟上这个不断变化的攻击面是很难的,更不用说保护这些应用程序和系统了 ...

  6. Android 利用二次贝塞尔曲线模仿购物车加入物品抛物线动画

    Android 利用二次贝塞尔曲线模仿购物车加入物品抛物线动画 0.首先.先给出一张效果gif图. 1.贝塞尔曲线原理及相关公式參考:http://www.jianshu.com/p/c0d7ad79 ...

  7. Python利用xlutils统计excel表格数据

    假设有像上这样一个表格,里面装满了各式各样的数据,现在要利用模板对它进行统计每个销售商的一些数据的总和.模板如下: 代码开始: 1 #!usr/bin/python3 2 # -*-coding=ut ...

  8. 利用Matlab快速绘制栅格地图

    代码演示 % 基于栅格地图的机器人路径规划算法 % 第1节:利用Matlab快速绘制栅格地图 clc clear close all %% 构建颜色MAP图 cmap = [1 1 1; ... % ...

  9. CANN算子:利用迭代器高效实现Tensor数据切割分块处理

    摘要:本文以Diagonal算子为例,介绍并详细讲解如何利用迭代器对n维Tensor进行基于位置坐标的大批量数据读取工作. 本文分享自华为云社区<CANN算子:利用迭代器高效实现Tensor数据 ...

随机推荐

  1. C#与数据库的连接的三种方式

    学习了.net的知识从C#一直到MVC,我一直觉得基础很重要,最近有复习一下数据库连接的三种方式 1 返回结果集的一张表 public static DataTable ExecuteDataTabl ...

  2. vc6.0里使用lib(静态库)的方法

    vc6.0 中使用lib文件 使用库的方法如下:1. 包含库的头文件(把库的头文件包含到项目中)在应用程序工程中使用#include "file path"file path可以为 ...

  3. Linux ssh的使用

    1.查看SSH客户端版本 有的时候需要确认一下SSH客户端及其相应的版本号.使用ssh -V命令可以得到版本号.需要注意的是,Linux一般自带的是OpenSSH: 下面的例子即表明该系统正在使用Op ...

  4. Linux 通过ssh传输文件

    一.scp是什么? scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.可能会稍微影响 ...

  5. 这个命令可以看到你的cpu到底集合

      cat /proc/cpuinfo  |grep processor|awk '{print $3}'|wc -l    改变虚拟机分辨率  xrandr -s 1024x768 -r 60  或 ...

  6. Linux ALSA介绍

    1. 介绍 ALSA(即Advanced Linux Sound Architecture), 是目前Linux的主流音频体系结构, 提供了音频和MIDI的支持, 其架构图如下所示 TIP: 笔者的代 ...

  7. 【 Linux 】lvs-dr模型实现HA,后端Nginx、PHP、MySQL分离 搭建wordpress站点

    要求:    1. wordpress程序通过nfs共享给各个realserver    2. 后端realserver中的nginx和php分离 网络结构图: 环境说明:    OS:centos6 ...

  8. 《Java编程思想》笔记 第二十章 注解

    1.注解 注解也称元数据,是在代码中添加信息的一种方式添加的信息提供给编译器或者工具类框架使用. SE5引入,可以提供用来完整描述程序所需要的信息,往往这些信息是无法用Java来表达的. 注解可以在编 ...

  9. 开发者应该了解的API技术清单!

    英文原文:API-Driven Development 作为一名开发者,诚然编写代码如同作家提笔挥毫,非常有成就感与乐趣,但同时我也觉得删除代码是件不相伯仲的美事.为什么呢?因为在进行删除工作时,意味 ...

  10. 阿里云ECS(Centos7.2 64bit)安装Docker

    购买了阿里云的ECS服务器后,一直在尝试安装Docker,使用过Ubuntu和CentOS系统,也一直在查找文档,但都是Docker安装完成后却无法访问,一直在ECS上不停的更换系统盘 再次按官方文档 ...