三种实现非标准分解的方法: <BR>第一种:2.2.3介绍的矩阵A变成 256X256的照片矩阵, 1:2的矩阵下标变成1:64, 1:4 变成1:128, 其它不变,保存系数 AR1,AC1,AR2,AC2,AR3,AC3为PNG格式,就是图3-26所需要的照片,只不过下1级没有显示上一级的细节系数(h v d)部分。使用合成技术类似这样的语句c=[ca cv ; ch cd]应该很方便得出。当然采用附录2中的程序可以更直接,更快速地实现老师的范例。 <BR><BR>第二种:按照第3章伪代码形式使用MATLAB一维离散小波变换函数dwt编写。 <BR><BR>dwt的用法: [ca cd] = dwt(I, wname); I是你要分解的一维向量,wname是字符串,使用单引号扩起来,如’db9’或’haar’。返回系数ca是低频近似系数,cd是高频细节系数。 <BR><BR>由于db9的滤波系数长度为18,dwt需要扩展以减少边界误差,重构函数idwt能够保证恢复到原来的尺寸。所以可以采用不同的扩展边界模式来使用,缺省值是’sym’,它在分解后会使ca和cd的长度变为 (LI + LF-1)/2, LI是向量I的长度,LF是小波滤波系数的长度。也可以改变边界扩展模式,如使用’per’,具体方法是[ca cd]=dwt(I,wname,’mode’,’per’).它的ca 和cd的长度为 LI/2,但是它可能带来边界误差。 <BR><BR>我编写了2维非标准分解nsdwt2和重构nsidwt2函数,可参见附录3。 <BR><BR>第三种:直接使用MATLAB卷积函数conv2,即仿照dwt2的函数编写。 <BR><BR>此处不再详细讨论,有兴趣者参见附录1 <BR><BR>这三种方式在MATLAB下计算速度最快的是第一种,最慢的是第二种,第三种速度与第一种速度比相差不大。在笔者PIII733上运行分解wbarb图像过程所用时间(使用TIC,TOC)分别为 0.10, 0.28, 7.23秒。 <BR><BR>常见问题: <BR>如何读取、转换和保存图像文件? <BR><BR>[X, map] = imread(‘文件名’) ; %文件名必须带后缀。 <BR><BR>使用size(X)来判断图像矩阵的维数,如果是256 256就是2维的,那么map就是它的色板文件,可以使用imshow(X,map)来显示它。如果256 256 3就是3维真彩色图像(True color Image),使用imshow(X)来显示。一般我们把2维的彩色图片称为伪彩色图像(Indexed color image)。 <BR><BR>一般来说,不管图像文件是不是PNG格式, 最好首先使用MATLAB的imwrite方式重新保存: <BR><BR>对于真彩色文件,imwrite(X, ‘新文件名’) ; <BR><BR>对于伪彩色文件,imwrite(X, map,‘新文件名’); <BR><BR>由imread读出的图像文件采用uint8的类型,必须转换成double类型之后方可进行运算。转换方法: X=doubl(X); <BR><BR>经过小波变换和重构的X是double类型,在保存图像前需要转换成uint8类型,如果处理不好,会产生截断误差,许多同学反映阈值为0时的文件大小和原始文件大小不一致可能就是出现在这里,转换方法: <BR><BR>Y=uint8(round(X)); 这里的round是就近取整,这样7.99999999就会变成8而不会被截断变为7。 <BR><BR>如何处理Indexed color 文件? <BR><BR>原则说,只要可以转换成double类型我们就可以开始小波变换。但是由于伪彩色图片的色板map保存了每个象素值对应的r g b的颜色值,因此,如果map中的颜色值不连续,就不能保证小波转换的效果。可以使用imshow(X,map);colorbar;来显示图片的色板是否连续。如果不连续,可以使用MATLAB提供的方法转换成灰度图像处理。这是林老师在“教师答疑”中贴出的MATLAB帮助文件Image Conversion,我把它转换成一个小程序,可以修改使用。Anna指出ind2gray和ind2rgb也能完成同样的任务。 <BR><BR>[X,map]=imread('你的伪彩色图片文件'); <BR><BR>X=double(X); <BR><BR>if min(min(X))==0 <BR><BR>X=X+1; <BR><BR>end <BR><BR>image(X) <BR><BR>title('Original Color Indexed Image') <BR><BR>colormap(map); colorbar <BR><BR>R = map(X,1); R = reshape(R,size(X)); <BR><BR>G = map(X,2); G = reshape(G,size(X)); <BR><BR>B = map(X,3); B = reshape(B,size(X)); <BR><BR>Xrgb = 0.2990*R + 0.5870*G + 0.1140*B; <BR><BR>n = 255; % Number of shades in new indexed image <BR><BR>X = round(Xrgb*(n-1)) + 1; <BR><BR>map2 = gray(n); <BR><BR>image(X), title('Processed Gray Scale Indexed Image') <BR><BR>colormap(map2), colorbar <BR><BR>baboon= X; <BR><BR>map = map2; <BR><BR>imwrite(X,map,'gray.png'); %保存为灰度图像,文件名为gray.png <BR><BR>如何处理真彩色文件? <BR><BR>有几种方法,在MATLAB的Image Conversion中有叙述,但许多同学采用了单独处理它的3个颜色的2维矩阵。设X为三维矩阵(256,256,3) , X(:,:,1)代表红颜色的2维矩阵 X(:,:,2)代表绿2维矩阵, X(:,:,3)代表绿2维矩阵。 <BR><BR>[X, map]=imread(‘真彩色文件’); <BR><BR>r=double(X(:,:,1)); %r是256 x 256的红色信息矩阵 <BR><BR>g=double(X(:,:,2)); %g是256 x 256的绿色信息矩阵 <BR><BR>b=double(X(:,:,3)); %b是256 x 256的兰色信息矩阵 <BR><BR>%开始对r g b分别作小波变换,并分别形成各自的小波系数矩阵 <BR><BR>…… <BR><BR>%把3个变换的系数矩阵合并成图像文件 <BR><BR>Y(:,:,1)=uint8(round( r )); <BR><BR>Y(:,:,2)=uint8(round( g )); <BR><BR>Y(:,:,1)=uint8(round( b )); <BR><BR>可以参照3.1的simplecmp.m程序来使用。 <BR><BR>如何完成使用小波变换压缩图像的任务 <BR><BR>由于压缩的目的在于比较使用不同小波压缩后重构图像的失真度视觉效果和使用PNG文件保存时的文件大小,如果我们自己编写的小波变换程序存在小的遗漏,可能对压缩结果判断错误,所以我认为至少应当使用MATLAB为我们提供的压缩函数记录结果,以便与自己设计的阈值处理程序进行比较。一般来说,两种处理结果应该差别很小,甚至无差别。 <BR><BR>直接使用wdencmp: <BR>这是我使用wdencmp编写的简单压缩处理程序simplecmp,可以直接再运行时输出图像、0的个数、PNG文件的大小以及计算时间。如果你的图片为 a.png,不管是真彩色、伪彩色,使用: <BR><BR>simplecmp(‘a.png’,’haar’,3) %进行haar小波的三级分解压缩合成 <BR><BR>simplecmp(‘a.png’,’db9’,3) %进行db9小波的三级分解压缩合成 <BR><BR>下面是具体程序清单。我只对高频细节系数部分进行硬阈值设置。 <BR><BR>function simplecmp(fname,wname,level) <BR><BR>[rgb,map]=imread(fname); <BR><BR>fig=figure;colorbar;axis on;axis equal; <BR><BR>set(fig,'position',[10 20 790 580],'name','压缩程序演示') <BR><BR>if length(size(rgb))==3 <BR><BR>rgbcmp(rgb,wname,level); <BR><BR>else <BR><BR>indcmp(rgb,map,wname,level); <BR><BR>end <BR><BR>%--------------------------------------------------- <BR><BR>function rgbcmp(rgb,wname,level) <BR><BR>%这是压缩真彩色图像 <BR><BR>rgb=double(rgb); <BR><BR>THR=[0 5 10 20]; <BR><BR>otxt=sprintf('%s_zeros.txt',wname); <BR><BR>fid=fopen(otxt,'w'); <BR><BR>fprintf(fid,'%20s%15s%15s%15s\n','文件名','大小','阈值','0数'); <BR><BR>for T=THR <BR><BR>TIC; <BR><BR>[rgb(:,:,1),cxc,lxc,perf0,perfl2]=wdencmp('gbl',rgb(:,:,1),wname,level,T,'h',1); <BR><BR>num0=length(find(abs(cxc) < 0.0000001)); <BR><BR>[rgb(:,:,2),cxc,lxc,perf0,perfl2]=wdencmp('gbl',rgb(:,:,2),wname,level,T,'h',1); <BR><BR>num0=num0+length(find(abs(cxc) < 0.0000001)); <BR><BR>[rgb(:,:,3),cxc,lxc,perf0,perfl2]=wdencmp('gbl',rgb(:,:,3),wname,level,T,'h',1); <BR><BR>num0=num0+length(find(abs(cxc) < 0.0000001)); <BR><BR>x=uint8(round(rgb)); <BR><BR>oname=sprintf('%s_%d.png',wname,T); <BR><BR>imwrite(x,oname); <BR><BR>tmp=imfinfo(oname); <BR><BR>fs=tmp.FileSize; <BR><BR>fprintf(fid,'%20s%15d%15d%15d\n',oname,fs,T,num0); <BR><BR>e_t=TOC; <BR><BR>sTitle=sprintf('%s阈值%d的文件大小%d,0数%u,用时%f,任意键继续...',wname,T,fs,num0,e_t); <BR><BR>image(x) <BR><BR>title(sTitle); <BR><BR>pause <BR><BR>end <BR><BR>fclose(fid); <BR><BR>%--------------------------------------------------- <BR><BR>function indcmp(x,map,wname,level) <BR><BR>%这是压缩伪彩色图像 <BR><BR>THR=[0 5 10 20]; <BR><BR>x=double(x); <BR><BR>otxt=sprintf('%s_zeros.txt',wname); <BR><BR>fid=fopen(otxt,'w'); <BR><BR>fprintf(fid,'%20s%15s%15s%15s\n','文件名','大小','阈值','0数'); <BR><BR>for T=THR <BR><BR>TIC; <BR><BR>[y,cxc,lxc,perf0,perfl2]=wdencmp('gbl',x,wname,level,T,'h',1); <BR><BR>num0=length(find(abs(cxc) < 0.0000001)); <BR><BR>y=uint8(round(y)); <BR><BR>oname=sprintf('%s_%d.png',wname,T); <BR><BR>imwrite(y,map,oname); <BR><BR>tmp=imfinfo(oname); <BR><BR>fs=tmp.FileSize; <BR><BR>fprintf(fid,'%20s%15d%15d%15d\n',oname,fs,T,num0); <BR><BR>e_t=TOC; <BR><BR>sTitle=sprintf('%s阈值%d的文件大小%d,0数%u,用时%f,任意键继续...',wname,T,fs,num0,e_t); <BR><BR>imshow(y,map) <BR><BR>title(sTitle); <BR><BR>pause <BR><BR>end <BR><BR>fclose(fid); <BR><BR>自己编写阈值设置函数: <BR>可以使用wthresh(X,’h’,T),X是要进行阈值设置的矩阵,’h’表示使用硬阈值处理方式, 阈值T=5,如对X=[6,-6 5 2 -2]进行阈值设置的结果是[6 6 0 0 0],如果设置软’s’,结果是 [1 1 0 0 0],大于T的,也被缩小。 <BR><BR>注意:低频系数是对图像重构质量最重要的系数,一般不需要设置。 |