声振论坛

 找回密码
 我要加入

QQ登录

只需一步,快速开始

查看: 5480|回复: 14

[GUI界面] 图像保存问题,欢迎讨论!

[复制链接]
发表于 2007-7-20 09:26 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?我要加入

x
在做gui界面的时候遇到一个这样的问题:我fig里有2个axes,一个用于显示原始图像,一个用来显示每个步骤处理结果。想通过一个菜单或者按键来实现保存处理结果的功能,也就是说只要用户点击保存的时候。系统会读取axes2里的图像数据,然后写成文件。因为保存路径和文件名可供用户选择,所以很自然想到uiputfile和saveas(看过很多人写的程序都是这样的)。由于保存程序和处理程序不在一个callback里所以牵扯到数据的传递问题,此问题困扰我好久了,今天总算给解决了。拿来分享一下,同时又发现了新问题,高手们来帮忙哈。
因为在多个axes情况下,显示不同的图像实现的代码记得是eight兄给的:
   axes(handles.axes1);
   这以后的绘图或者显示函数都是针对axes1的
   axes(handles.axes2);
   这以后的绘图或者显示函数都是针对axes2的
   .......................................
   更多的一次类推.....
那么如果向保存axes2的图像该怎么实现呢?受上边的启发我用了下边的代码:
   [sFileName sFilePath]=uiputfile({'*.jpg','JPEG-Files (*.jpg)'; ...
            '*.*','All Files (*.*)'},'保存图像文件','untitled.jpg');
   if ~isequal([sFileName,sFilePath],[0,0])
      sFileFullName=[sFilePath sFileName];
      axes(handles.axes2);
      saveas(gca,sFileFullName,'jpg');
   else
      msgbox('你按了取消键!','保存失败');
   end
程序运行正常,可惜结果不对。保存的图像是整个fig的左下角的一部分,而不是axes2里显示的图像。
猜测可能是数据传递有问题,结果把我搜集的参数传递方式试了一个遍:
      handles.Timg=imshow(J);%某论坛一个版主给的方法
      handles.Timg=J;%常用的保存方法
事实证明这2种方法传递的句柄保存的结果都不太正常,而且和我上边使用的方法结果完全相同!
无奈之下,想到高手常用的另一种传递方法setappdata和getappdata
      setappdata(gcf,'Timg',J);
保存里callback里:
      data=getappdata(gcf,'Timg');
      saveas(Timg,sFileFullName,'jpg');
结果程序出错:
??? Error using ==> saveas
Invalid handle.
Error in ==> preprocess>saveas_Callback at 206
    saveas(data,sFileFullName,'jpg');
Error in ==> gui_mainfcn at 75
        feval(varargin{:});
Error in ==> preprocess at 42
    gui_mainfcn(gui_State, varargin{:});
??? Error while evaluating uimenu Callback.
无效的句柄,查看saveas的help文档,发现saveas保存的都是句柄对象。getappdata获得是图像数据,原来是因为saveas不支持保存图像数据,所以想到了imwrite
    data=getappdata(gcf,'Timg');
    imwrite(gca,sFileFullName,'jpg');
嘿嘿程序完全正常了,经常见到uiputfile和saveas一起用。和imwrite一起用的倒是没见过,可能是我见识太少了。后来发现当使用imwrite保存的时候,在处理的callback里可以用handles.Timg=J替换setappdata(gcf,'Timg',J);
   虽然达到了保存的目的但是,问题仍在:如何用saveas得到正确的结果?3种不同的句柄出传递方法得到相同不正确的结果,说明问题不在句柄保存本身上,那么到底是在哪儿呢?还往高手们多讨论一下,把多axes的图像的可选路径保存问题弄个一目了然!
   附图是用imwrite和saveas的保存结果,以后整个figure的图像。
下面的小程序是用来测试imwrite和saveas保存图像的区别:
==================================================================================
I=imread('lena.bmp');
data=imadjust(I);
imshow(data);
pause;
%%下面是只有单个绘图窗口的情形
[sFileName sFilePath]=uiputfile({'*.jpg','JPEG-Files (*.jpg)'; ...
            '*.*','All Files (*.*)'},'保存图像文件','untitled.jpg');
if ~isequal([sFileName,sFilePath],[0,0])
    sFileFullName=[sFilePath sFileName];
    imwrite(data,sFileFullName,'jpg');
end
pause;
[sFileName sFilePath]=uiputfile({'*.jpg','JPEG-Files (*.jpg)'; ...
            '*.*','All Files (*.*)'},'保存图像文件','untitled.jpg');
if ~isequal([sFileName,sFilePath],[0,0])
    sFileFullName=[sFilePath sFileName];
    saveas(gca,sFileFullName,'jpg');
end
pause;
%下面是多个绘图窗口的情形(以2个为例)
subplot(121),Ta=imshow(data);title('原图')
[counts,x] = imhist(data);
subplot(122),Tb=plot(x,counts);title('直方图')
saveas(Tb,'直方图.jpg');
%这里的保存结果是整个fig,需要的是子图2里的直方图。
==================================================================================
直观上看有2点不同
(1)saveas保存的图像是整个fig,图像以外的部分全部用白像素代替了。
(2)图像的大小不一样:
        saveas: 1201*900*24b jpeg  72.3k
        imwrite:256*256*256  jpeg  12.6k
(我的lena.bmp是重新在网上下载的,系统里的没了。所以具体的数据会有差别,在此只是为了说明2者保存同种类型图像时的区别)
最后归纳一下待解决的问题:
(1)如何在gui里用saveas正确的保存不同axes里的图像?
(2)在多窗口绘图里(使用subplot的情形),如果正确保存子图里的图像?

[ 本帖最后由 eight 于 2007-7-20 14:54 编辑 ]

整个fig界面

整个fig界面

不同的保存结果

不同的保存结果

评分

1

查看全部评分

回复
分享到:

使用道具 举报

发表于 2007-7-20 14:47 | 显示全部楼层
原帖由 花如月 于 2007-7-20 09:26 发表
在做gui界面的时候遇到一个这样的问题:我fig里有2个axes,一个用于显示原始图像,一个用来显示每个步骤处理结果。想通过一个菜单或者按键来实现保存处理结果的功能,也就是说只要用户点击保存的时候。系统会读 ...



saveas、print 应该不能实现各个子图的保存功能,因为它们的操作对象仅仅是整个figure:

You can pass the handle of any Handle Graphics object to saveas,
which then saves the parent figure to the object you specified should h not
be a figure handle. This means that saveas cannot save
a subplot without also saving all subplots in its parent figure

至于为何出现保存左下角的问题,我想是这样的:调用这两个函数保存图片时,系统先检测axes,一旦检测到某个axes对象,就马上输出该axes的内容,直到figure的底部

[ 本帖最后由 eight 于 2007-7-20 15:03 编辑 ]
发表于 2007-7-20 15:05 | 显示全部楼层
原帖由 花如月 于 2007-7-20 09:26 发表
在做gui界面的时候遇到一个这样的问题:我fig里有2个axes,一个用于显示原始图像,一个用来显示每个步骤处理结果。想通过一个菜单或者按键来实现保存处理结果的功能,也就是说只要用户点击保存的时候。系统会读 ...



三种参数传递的方式我都试了,貌似没有问题,得到的图片都是一样的
 楼主| 发表于 2007-7-20 15:14 | 显示全部楼层

回复 #3 eight 的帖子

谢谢eight兄的回复,那么我的第一问题看来只能用uiputfile和imwrite来实现了。
(2)在多窗口绘图里(使用subplot的情形),如果正确保存子图里的图像?反正是讨论,大家就都发表一下自己的想法。(除了使用抓图工具)
发表于 2007-7-20 15:15 | 显示全部楼层
原帖由 花如月 于 2007-7-20 09:26 发表
在做gui界面的时候遇到一个这样的问题:我fig里有2个axes,一个用于显示原始图像,一个用来显示每个步骤处理结果。想通过一个菜单或者按键来实现保存处理结果的功能,也就是说只要用户点击保存的时候。系统会读 ...



imwrite 和 saveas 两者保存的图片是不同的,因为前者保存的对象只是图象的数据,而后者是窗口的句柄,因此,前者生成图片的大小与原始矩阵大小一致,比较准确些,而后者保存的对象窗口的客户区部分,并且保存时会拉伸到某个固定大小,因此当图片比较大的时候,用 saveas 或者 print 保存会出现“图片缩小保存”的警告语句。
发表于 2007-7-20 16:08 | 显示全部楼层
原帖由 花如月 于 2007-7-20 15:14 发表
谢谢eight兄的回复,那么我的第一问题看来只能用uiputfile和imwrite来实现了。
(2)在多窗口绘图里(使用subplot的情形),如果正确保存子图里的图像?反正是讨论,大家就都发表一下自己的想法。(除了使用抓 ...


如果 subplot 中画的是图片,则通过 CData 属性就可以使用 imwrite 保存了:

  1. a=get(gca);
  2. b=get(a.Children);
  3. imwrite(b.CData, filename);
复制代码
如果画的并非图片,例如在你的例子中使用 plot 作的图,则我暂时想不到如何保存下来
 楼主| 发表于 2007-7-20 16:31 | 显示全部楼层

回复 #6 eight 的帖子

非常感谢eight兄,又学了一招:loveliness:
 楼主| 发表于 2007-7-21 20:37 | 显示全部楼层

回复 #6 eight 的帖子

刚才试了一下,发现这种方法保存的都是最后一个子图。中间的子图是不是也没有办法保存?
发表于 2007-7-23 11:50 | 显示全部楼层
原帖由 花如月 于 2007-7-21 20:37 发表
刚才试了一下,发现这种方法保存的都是最后一个子图。中间的子图是不是也没有办法保存?


不是啊,你试试以下代码:

  1. function Untitled9
  2. I=imread('cameraman.tif');
  3. data=imadjust(I);

  4. subplot(121),ta = imshow(data);title('原图')
  5. filename = 'org.jpg';
  6. mysaveas(filename,ta);

  7. [counts,x] = imhist(data);
  8. subplot(122), tb = plot(x,counts);title('直方图')
  9. filename = 'hist.jpg';
  10. mysaveas(filename,tb);

  11. function mysaveas(filename,h)
  12. a=get(gca);
  13. b=get(a.Children);
  14. if isfield(b, 'CData')
  15.     imwrite(b.CData, filename);
  16. else
  17.    
  18. end
复制代码


else 那里是 plot 出来的图片保存问题,还没有想到解决方法。其实此时 b 虽然没有 CData 域,但是却在 XData, YData 中保存了 plot 的数据,不知道能否作为图片save下来

评分

1

查看全部评分

 楼主| 发表于 2007-10-25 22:16 | 显示全部楼层
发现这种情形,似乎没有办法得到更多子图的数据:
freqs(1,[1 1])
a=get(gca);
b=get(a.Children);
figure,loglog(b.XData,b.YData);
只画出了第一个子图,第二个子图没法得到数据。不知到还有没有别的办法?虽然意义不大,不过有时还是会碰到别人保存好的fig图形。如果有多个子图,又需要读出数据。那么能找到直接读的方法就最好不过了
发表于 2007-12-18 18:14 | 显示全部楼层
GUI保存图片我一般用PRINT语句。
建立一个隐藏的FIGURE。通过设置FIGURE大小,设置保存图片大小
可以通过COPY AXES的办法实现隐藏的FIGURE到任意子图的映射。
此方法可以方便建立一如SaveAxes(AxesHandle,Filename)的函数。

评分

1

查看全部评分

发表于 2008-3-9 19:03 | 显示全部楼层
'''''function Untitled9
I=imread('cameraman.tif');
data=imadjust(I);

subplot(121),ta = imshow(data);title('原图')
filename = 'org.jpg';
mysaveas(filename,ta);

[counts,x] = imhist(data);
subplot(122), tb = plot(x,counts);title('直方图')
filename = 'hist.jpg';
mysaveas(filename,tb);

function mysaveas(filename,h)
a=get(gca);
b=get(a.Children);
if isfield(b, 'CData')
    imwrite(b.CData, filename);
else
   
end''
%%%%%%%%%%%%%%%%%%%%%%%%%%555
%%%%%%%%%%%%%%%%%%%%%%55
以上eight院长的程序
我试了一下
在我的版本上保存有点问题
下面是我保存gui界面上axes中图形的思路
虽然路子有点弯
但功能基本能够实现
与大家讨论
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
由于saveas保存的是figure中的图形,所以在gui界面中axes显示的图形保存的话,我用的版本上老出现问题

自己就想了别的招:先获得axes中图形的:label、labeltick、axis、title、data、view等值
新建figure
绘图
保存
pause
关闭
就能完成axes当前图形的保存,走了弯路但可以解决问题。
%%%%%%%%%%%%%%%%%%%%%5
发表于 2008-11-5 10:11 | 显示全部楼层

我觉得junzifei的方法可用于保存plot命令的图片

rt,如果在读入的图片上做图,这样就会生成一个内部矩阵,如果能得到这个矩阵及其相关参数,我觉得就可以保存下用plot命令做出的图,不知道各位的是否同意?
发表于 2012-7-20 12:47 | 显示全部楼层
路过,学习了!
发表于 2012-12-21 00:24 | 显示全部楼层
GUI中axes1中的图像怎么保存? saveas(gca,sFileFullName,'jpg');好像只能保存右下角,而data=getappdata(gcf,'Timg');imwrite(gca,sFileFullName,'jpg');却什么都没有。。。这是为什么,求指导啊,谢谢大大
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

QQ|小黑屋|Archiver|手机版|联系我们|声振论坛

GMT+8, 2024-11-10 22:47 , Processed in 0.081195 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表