Wednesday, September 21, 2005

 

Some notes on Matlab Image Processing - 1

1.
用matlab读取16位、14位、12位灰度bmp图像

By darnshong
From http://www.52blog.net/user1/4566/archives/2004/72461.shtml

16位、14位、12位灰度bmp图像(*.bmp)并不是标准的格式,bmp图像只有16位的彩色图像而没有16位的灰度图像之说。所以,对于16位、14位、12位灰度bmp图像,一般是当做16位的彩色图像写入的,由于这个原因,计算机上看到的这些16位、14位、12位灰度bmp图像看起来都是彩色的,虽然我们写数据的时候写的是灰度的信息。
  用matlab可以读取16位的bmp图像,但是得到的数据是matlab解析过的彩色数据信息,RGB三个分量都是uint8,且matlab已经把RGB三分量的范围映射到0~255。这些并不是我们想要的bmp图像里的16位数据信息,必须经过适当的处理之后才能得到。只要得到了bmp图像里的16位数据信息,也就得到了那些非标准格式的灰度bmp图像(16位、14位、12位灰度bmp图像)的灰度信息。

  倘若想保存16位、14位、12位灰度图像而又不让计算机解析成彩色图像,可以保存为*.png、*.tiff格式,这两种格式都支持16位的灰度图像。

  另外还要提一下的是,由于我们现在所使用的计算机一般最高级也就24位的真彩色(RGB各8位),而要显示灰度图像,RGB三分量必须都相等,也就是说,用来显示灰度的其实只有8位,对于8位以上(不含8位)的灰度图像,计算机是没法正确显示的,无怪乎你若是把原来16位的灰度图像从bmp格式转化成png格式,图像反而不清楚了,因为16位灰度bmp格式时,计算机显示的是彩色图像,而16灰度png格式时,计算机显示的是灰色图像。

  16位的bmp图像格式有两种,一种是R5G5B5,最高位不用,另一种是R5G6B5。

  以下是matlab实现上述过程的源代码:

function b=read16graybmp(filename)
%usage: read16graybmp(filename)
%designed by darnshong ioe,cas
if(nargin~=1)
error('Need 1 parameters!');
end;
i=0:2^5-1;index5=floor(i*255.99/(2^5-1));%for 5bits
%index5=[0 8 16 24 33 41 49 57 66 74 82 90 99 107 115 123 132 140 148 156 165 173 181 189 198 206 214 222 231 239 247 255];
value5(index5+1)=0:2^5-1;
j=0:2^6-1;index6=floor(j*255.99/(2^6-1));%for 6bits
value6(index6+1)=0:2^6-1;
minfo=imfinfo(filename);
%if(strcmp(minfo.CompressionType,'none'))%for 555 format R5G5B5
a=imread(filename);
b1=value5(a(:,:,1)+1);
b2=value5(a(:,:,2)+1);
b3=value5(a(:,:,3)+1);
b=bitshift(uint16(b1),10)+bitshift(uint16(b2),5)+uint16(b3);
% else % for 565 format R5G6B5 ,matlab not supported!
%a=imread(filename);
%b1=value5(a(:,:,1)+1);
%b2=value6(a(:,:,2)+1);
% b3=value5(a(:,:,3)+1);
% b=bitshift(uint16(b3),11)+bitshift(uint16(b2),5)+uint16(b1);
%end;

2.
普通文件与图像文件的相互转化

By darnshong
From http://www.52blog.net/user1/4566/archives/2004/51659.shtml

时下,好些论坛都提供贴图服务,也就是说,你可以把你喜欢的图像上传,与他人共享。但是如果是其他非图像和文本的文件的共享就不是很好办了。为此,我用matlab写了几个函数,用于把普通的文件(一切文件格式)转化成某些特定格式的图像文件(*.bmp,*.png,*.ras,*.tif,*.tiff)。通过这些转化而来的图像文件,你就可以与他人共享你的一切文件。对方只要保存了这个转化而来的图像文件,就可用我所写的函数完整地恢复原来的文件的面目,从而达到通过图像文件来共享一切文件的目的。

以下是我写的几个函数(file2imgdata、file2img、imgdata2file、img2file):

function dat=file2imgdata(filename,imgwidth)
%%dat=file2imgdata(filename,imgwidth)
%convert the common file to image data
%%--------------------the image map-------------------
% |-----------------the image width-------------------|
% |'csz'(3)+extension(20)+patch with '0'+file size(?)-|
% |the uint8 format data,acquired from the source file|
% |...................................................|
% |....................no data,patch with uint8(0)----|
% designed by darnshong,ioe,cas
if(~exist(filename,'file'))
error('The file does not exist!');
end;
[fpath,fname,fileext]=fileparts(filename);% get the file'extension
fileext=fileext(2:numel(fileext));
extnum=uint8(fileext);
if(numel(extnum)<20)
temp=zeros(1,20);
temp(1:numel(extnum))=extnum;
temp((numel(extnum)+1):20)=uint8('.');
extnum=temp;
else
error('the length of the file extension is large than 20');
end;
%%%%%%% get the source file size

s=dir(filename);
fsize=s.bytes;%get the file size.
fsize=num2str(uint32(fsize),'%d');
fsize=uint8(fsize);
extralen=imgwidth-3-20;
if(numel(fsize)<=extralen)
temp=zeros(1,extralen);
temp(1:extralen-numel(fsize))=uint8('0');
temp((extralen+1-numel(fsize)):extralen)=fsize;
fsize=temp;
else
error('the length of the file size is too large!');

end;
dat=[];
dat(1,:)=[uint8('czs'),extnum,fsize];
fsrc=fopen(filename,'r');
totalline=uint32(ceil(s.bytes/imgwidth));
for i=1:totalline-1
dat(end+1,:)=fread(fsrc,imgwidth);
end;
temp=fread(fsrc,imgwidth); %not enough data,so patch with 0;
temp1=zeros(1,imgwidth);
temp1(1:numel(temp))=temp;
dat(end+1,:)=temp1;
fclose(fsrc);
dat=uint8(dat);

%%%%%%%%%%%%%%%%%%%%%%%%%%%

function yy=file2img(commonfile,imgfile,imgwidth)
%yy=file2img(commonfile,imgfile,imgwidth)
%convert the common file like .exe,.doc,to the image file.
%thus you can post your common file as a image file.
% designed by darnshong,ioe,cas
if(nargin~=3)
error('Input parameters error!Require 3 parameters!');
end;
yy=file2imgdata(commonfile,imgwidth);
finddot=find(imgfile=='.');
imgext=imgfile(finddot(1)+1:end);
if~(strcmp(imgext,'bmp') || strcmp(imgext,'png') || strcmp(imgext,'ras') ||...
strcmp(imgext,'tif') || strcmp(imgext,'tiff'))
error('Not support image format!The image file format should be *.bmp,*.png,*.ras,*.tif,*.tiff');
end;
imwrite(yy,imgfile);

%%%%%%%%%%%%%%%%%%%%%%%%%%

function imgdata2file(dat,filenoext)
%%%% imgdata2file(dat,filenoext)
% ----dat,the image data
% convert the imagedata to the common file
%%dat=file2imgdata(filename,imgwidth)
%%--------------------the image map-------------------
% |-----------------the image width-------------------|
% |'csz'(3)+extension(20)+patch with '0'+file size(?)-|
% |the uint8 format data,acquired from the source file|
% |...................................................|
% |....................no data,patch with uint8(0)----|
% designed by darnshong,ioe,cas

testczs=dat(1,1:3);%test if the image data is valid.
testczs=char(testczs);
if(~strcmp(testczs,'czs'))
error('wrong image data!');
end
imgwidth=size(dat,2);
finddot=find(dat(1,:)==uint8('.'));
ext=dat(1,4:finddot(1)-1);%get the common file's extension
ext=char(ext);
fsize=dat(1,(finddot(end)+1):imgwidth);%get the common file's size

fsize=str2double(char(fsize));
dstfile=strcat(filenoext,'.',ext);
fdst=fopen(dstfile,'w');
totalline=uint32(ceil(fsize/imgwidth));
for i=2:totalline,
fwrite(fdst,dat(i,:),'uint8');
end;
lastline=dat(totalline+1,1:(fsize-imgwidth*(totalline-1)));
fwrite(fdst,lastline,'uint8');
fclose(fdst);

%%%%%%%%%%%%%%%%%%%%%%%%%%

function yy=img2file(imgfile,commonfilenoext)
%%% yy=img2file(imgfile,commonfilenoext)
% convert the image file to the common file
% thus you can restore the common file from the image file.
% designed by darnshong,ioe,cas
if(nargin~=2)
error('Input parameters error!Require 2 parameter!');
end;
finddot=find(imgfile=='.');
imgext=imgfile(finddot(1)+1:end);
if~(strcmp(imgext,'bmp') || strcmp(imgext,'png') || strcmp(imgext,'ras') ||...
strcmp(imgext,'tif') || strcmp(imgext,'tiff'))%only support some image format
error('Not support image format!The image file format should be *.bmp,*.png,*.ras,*.tif,*.tiff');
end; %%%% because the *.jpg image format is lossy compression,it can't be used.
yy=imread(imgfile);
imgdata2file(yy,commonfilenoext);

%%%%%%%%%%%%%%%%%%%%%%%%%%

3.
发现matlab不支持16位bmp图像的几种特殊格式

By darnshong
From http://www.52blog.net/user1/4566/archives/2005/153011.shtml

今天用photoshop做了几幅不同格式的16位bmp图像,包括X1R5G5B5格式、R5G6B5格式和X4R4G4B4格式。然后我用matlab的imread函数来读取,只有X1R5G5B5可以正确读取,其他两种格式无法读取,一读取就出错。我的matlab是7.01版本的,看来还是不支持R5G6B5和X4R4G4B4这两种格式的16位bmp图像!

4.
将图像转化成avi格式电影

By darnshong
From http://www.52blog.net/user1/4566/archives/2005/153011.shtml

  导师那有好些系列图像,想弄成电影。查了一下matlab的帮助,轻松地实现了,转化成avi格式电影!以下是代码:

function produceavifrompic(pfrom,pto,pext,navi)
aviobj = avifile(navi);
aviobj.Quality = 100;
aviobj.compression='None';
cola=0:1/255:1;
cola=[cola;cola;cola];%%黑白图像
cola=cola';
aviobj.colormap=cola;
for i=pfrom:pto
fname=strcat(num2str(i),pext)
adata=imread(fname);
aviobj = addframe(aviobj,uint8(adata));
end
aviobj=close(aviobj);

以上是将一系列8位黑白图像转化成avi格式电影,如果是彩色图像,则如下

function produceavifrompic(pfrom,pto,pext,navi)
aviobj = avifile(navi);
aviobj.Quality = 100;
aviobj.compression='None';
for i=pfrom:pto
fname=strcat(num2str(i),pext)
adata=imread(fname);
aviobj = addframe(aviobj,uint8(adata));
end
aviobj=close(aviobj);

挺简单的吧!快去试试!

5.
从avi文件中提取图片

By darnshong
From http://www.52blog.net/user1/4566/archives/2005/190925.shtml

function avi2pic(avifile,pickind)
%function avi2pic(avifile,pickind)
% avifile-- the avi filename,like 'darnshong.avi','ioe.avi',etc;
% pickind-- the kind of image format,like 'jpg','bmp',etc
% supported export image
% format:'jpg','jpeg','bmp','tiff','tif','gif','png',etc
mov=aviread(avifile);
temp=size(mov);
fnum=temp(2);
for i=1:fnum,
strtemp=strcat(int2str(i),'.',pickind);
imwrite(mov(i).cdata(:,:,:),mov(i).colormap,strtemp);
end,

6.
ZIGZAG扫描的MATLAB实现
From http://blog.csdn.net/hunnish/archive/2004/10/29/158885.aspx

转自阿须数码,用MATLAB实现MPEG中的 ZIG-ZAG 扫描。觉得有点研究价值,实现的方法也很巧妙。

下面给一个参照MPEG提供的方法:

===
function b=zigzag(a)
% 这是参照 University of California 提供的 MPEG 源代码的基础上编制的。
% Copyright (c) 1995 The Regents of the University of California.

[n,m]=size(a);
if(n~=8 & m~=8)
error('Input array is NOT 8-by-8');
end

% Set up array for fast conversion from row/column coordinates to
% zig zag order. 下标从零开始,因为是从MPEG的C代码拷贝过来的
zigzag = [ 0, 1, 8, 16, 9, 2, 3, 10, ...
17, 24, 32, 25, 18, 11, 4, 5, ...
12, 19, 26, 33, 40, 48, 41, 34, ...
27, 20, 13, 6, 7, 14, 21, 28, ...
35, 42, 49, 56, 57, 50, 43, 36, ...
29, 22, 15, 23, 30, 37, 44, 51, ...
58, 59, 52, 45, 38, 31, 39, 46, ...
53, 60, 61, 54, 47, 55, 62, 63];

zigzag = zigzag + 1; % 下标加1,符合MATLAB的下标习惯
aa = reshape(a,1,64); % 将输入块变成1x64的向量
b = aa(zigzag); % 对 aa 按照查表方式取元素,得到 zig-zag 扫描结果

===


程序运行结果:

?a=magic(8)
a =
64 2 3 61 60 6 7 57
9 55 54 12 13 51 50 16
17 47 46 20 21 43 42 24
40 26 27 37 36 30 31 33
32 34 35 29 28 38 39 25
41 23 22 44 45 19 18 48
49 15 14 52 53 11 10 56
8 58 59 5 4 62 63 1

?b=zigzag(a)
b =
Columns 1 through 12
64 9 2 3 55 17 40 47 54 61 60 12
Columns 13 through 24
46 26 32 41 34 27 20 13 6 7 51 21
Columns 25 through 36
37 35 23 49 8 15 22 29 36 43 50 57
Columns 37 through 48
16 42 30 28 44 14 58 59 52 45 38 31
Columns 49 through 60
24 33 39 19 53 5 4 11 18 25 48 10
Columns 61 through 64
62 63 56 1



<< Home

This page is powered by Blogger. Isn't yours?