图像处理 图像格式转换

2017-12-19 14:03:57 lala_623625 阅读数 2611

在数字图像处理中,针对不同的图像格式有其特定的处理算法。所以,在做图像处理之前,我们需要考虑清楚自己要基于哪种格式的图像进行算法设计及其实现。本文基于这个需求,使用python中的图像处理库PIL来实现不同图像格式的转换。

对于彩色图像,不管其图像格式是PNG,还是BMP,或者JPG,在PIL中,使用Image模块的open()函数打开后,返回的图像对象的模式都是“RGB”。而对于灰度图像,不管其图像格式是PNG,还是BMP,或者JPG,打开后,其模式为“L”。

通过之前的博客对Image模块的介绍,对于PNG、BMP和JPG彩色图像格式之间的互相转换都可以通过Image模块的open()和save()函数来完成。具体说就是,在打开这些图像时,PIL会将它们解码为三通道的“RGB”图像。用户可以基于这个“RGB”图像,对其进行处理。处理完毕,使用函数save(),可以将处理结果保存成PNG、BMP和JPG中任何格式。这样也就完成了几种格式之间的转换。同理,其他格式的彩色图像也可以通过这种方式完成转换。当然,对于不同格式的灰度图像,也可通过类似途径完成,只是PIL解码后是模式为“L”的图像。

这里,我想详细介绍一下Image模块的convert()函数,用于不同模式图像之间的转换。

Convert()函数有三种形式的定义,它们定义形式如下:

im.convert(mode) ? image

im.convert(“P”, **options) ? image

im.convert(mode, matrix) ? image

使用不同的参数,将当前的图像转换为新的模式,并产生新的图像作为返回值。

通过博客“Python图像处理库PIL的基本概念介绍”,我们知道PIL中有九种不同模式。分别为1,L,P,RGB,RGBA,CMYK,YCbCr,I,F。

本文我采用的示例图像是图像处理中经典的lena照片。分辨率为512x512的lena图片如下:

\

一、模式“RGB”转换为其他不同模式

1、模式“1”

模式“1”为二值图像,非黑即白。但是它每个像素用8个bit表示,0表示黑,255表示白。下面我们将lena图像转换为“1”图像。

例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
>>>from PIL import Image
 
>>> lena =Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")
 
>>> lena.mode
 
'RGB'
 
>>> lena.getpixel((0,0))
 
(197, 111, 78)
 
>>> lena_1 = lena.convert("1")
 
>>> lena_1.mode
 
'1'
 
>>> lena_1.size
 
(512, 512)
 
>>>lena_1.getpixel((0,0))
 
255
 
>>> lena_1.getpixel((10,10))
 
255
 
>>>lena_1.getpixel((10,120))
 
0
 
>>>lena_1.getpixel((130,120))
 
255

图像lena_1的模式为“1”,分辨率为512x512,如下:

\

2、模式“L”

模式L”为灰色图像,它的每个像素用8个bit表示,0表示黑,255表示白,其他数字表示不同的灰度。在PIL中,从模式“RGB”转换为“L”模式是按照下面的公式转换的:

L = R * 299/1000 + G * 587/1000+ B * 114/1000

下面我们将lena图像转换为“L”图像。

例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
>>> from PIL importImage
 
>>> lena = Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")
 
>>> lena.mode
 
'RGB'
 
>>> lena.getpixel((0,0))
 
(197, 111, 78)
 
>>> lena_L =lena.convert("L")
 
>>> lena_L.mode
 
'L'
 
>>> lena_L.size
 
(512, 512)
 
>>>lena.getpixel((0,0))
 
(197, 111, 78)
 
>>>lena_L.getpixel((0,0))
 
132

对于第一个像素点,原始图像lena为(197, 111, 78),其转换为灰色值为:

197 *299/1000 + 111 * 587/1000 + 78 * 114/1000 = 132.952,PIL中只取了整数部分,即为132。

转换后的图像lena_L如下:

\

3、模式“P”

模式“P”为8位彩色图像,它的每个像素用8个bit表示,其对应的彩色值是按照调色板查询出来的。

下面我们使用默认的调色板将lena图像转换为“P”图像。

例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>>> from PIL importImage
 
>>> lena = Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")
 
>>> lena.mode
 
'RGB'
 
>>> lena.getpixel((0,0))
 
(197, 111, 78)
 
>>> lena_P =lena.convert("P")
 
>>> lena_P.mode
 
'P'
 
>>>lena_P.getpixel((0,0))
 
62

 

转换后的图像lena_P如下:

\

4、模式“RGBA”

模式“RGBA”为32位彩色图像,它的每个像素用32个bit表示,其中24bit表示红色、绿色和蓝色三个通道,另外8bit表示alpha通道,即透明通道。

下面我们将模式为“RGB”的lena图像转换为“RGBA”图像。

例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
>>> from PIL import Image
 
>>>lena = Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")
 
>>>lena.mode
 
'RGB'
 
>>>lena.getpixel((0,0))
 
(197,111, 78)
 
>>>lena_rgba = lena.convert("RGBA")
 
>>>lena_rgba.mode
 
'RGBA'
 
>>>lena_rgba.getpixel((0,0))
 
(197,111, 78, 255)
 
>>>lena_rgba.getpixel((0,1))
 
(196,110, 77, 255)
 
>>>lena.getpixel((0,0))
 
(197,111, 78)
 
>>>lena.getpixel((0,1))
 
(196,110, 77)

 

从实例中可以看到,使用当前这个方式将“RGB”图像转为“RGBA”图像时,alpha通道全部设置为255,即完全不透明。

转换后的图像lena_rgba如下:

\

5、模式“CMYK”

模式“CMYK”为32位彩色图像,它的每个像素用32个bit表示。模式“CMYK”就是印刷四分色模式,它是彩色印刷时采用的一种套色模式,利用色料的三原色混色原理,加上黑色油墨,共计四种颜色混合叠加,形成所谓“全彩印刷”。

四种标准颜色是:C:Cyan = 青色,又称为‘天蓝色’或是‘湛蓝’M:Magenta = 品红色,又称为‘洋红色’;Y:Yellow = 黄色;K:Key Plate(blacK) = 定位套版色(黑色)。

下面我们将模式为“RGB”的lena图像转换为“CMYK”图像。

例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
>>>from PIL import Image
 
>>> lena =Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")
 
>>> lena_cmyk =lena.convert("CMYK")
 
>>> lena_cmyk.mode
 
'CMYK'
 
>>>lena_cmyk.getpixel((0,0))
 
(58, 144, 177, 0)
 
>>> lena_cmyk.getpixel((0,1))
 
(59, 145, 178, 0)
 
>>>lena.getpixel((0,0))
 
(197, 111, 78)
 
>>>lena.getpixel((0,1))
 
(196, 110, 77)

 

从实例中可以得知PIL中“RGB”转换为“CMYK”的公式如下:

C = 255 - R
M = 255 - G
Y = 255 - B
K = 0

由于该转换公式比较简单,转换后的图像颜色有些失真。

转换后的图像lena_cmyk如下:

\

6、模式“YCbCr”

模式“YCbCr”为24位彩色图像,它的每个像素用24个bit表示。YCbCr其中Y是指亮度分量,Cb指蓝色色度分量,而Cr指红色色度分量。人的肉眼对视频的Y分量更敏感,因此在通过对色度分量进行子采样来减少色度分量后,肉眼将察觉不到的图像质量的变化。

模式“RGB”转换为“YCbCr”的公式如下:

Y= 0.257*R+0.504*G+0.098*B+16
Cb = -0.148*R-0.291*G+0.439*B+128
Cr = 0.439*R-0.368*G-0.071*B+128

下面我们将模式为“RGB”的lena图像转换为“YCbCr”图像。

例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>>from PIL import Image
 
>>> lena =Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")
 
>>> lena_ycbcr =lena.convert("YCbCr")
 
>>>lena_ycbcr.mode
 
'YCbCr'
 
>>>lena_ycbcr.getpixel((0,0))
 
(132, 97, 173)
 
>>>lena.getpixel((0,0))
 
(197, 111, 78)

 

按照公式,Y = 0.257*197+0.564*111+0.098*78+16= 136.877

Cb= -0.148*197-0.291*111+0.439*78+128= 100.785
Cr = 0.439*197-0.368*111-0.071*78+128 = 168.097

由此可见,PIL中并非按照这个公式进行“RGB”到“YCbCr”的转换。

转换后的图像lena_ycbcr如下:

\

7、模式“I”

模式“I”为32位整型灰色图像,它的每个像素用32个bit表示,0表示黑,255表示白,(0,255)之间的数字表示不同的灰度。在PIL中,从模式“RGB”转换为“I”模式是按照下面的公式转换的:

I = R * 299/1000 + G * 587/1000 + B * 114/1000

下面我们将模式为“RGB”的lena图像转换为“I”图像。

例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
>>> from PIL import Image
 
>>>lena = Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")
 
>>>lena.getpixel((0,0))
 
(197,111, 78)
 
>>>lena.getpixel((0,1))
 
(196,110, 77)
 
>>> lena_I =lena.convert("I")
 
>>> lena_I.mode
 
'I'
 
>>>lena_I.getpixel((0,0))
 
132
 
>>>lena_I.getpixel((0,1))
 
131
 
>>> lena_L =lena.convert("L")
 
>>>lena_L.getpixel((0,0))
 
132
 
>>>lena_L.getpixel((0,1))
 
131

从实验的结果看,模式“I”与模式“L”的结果是完全一样,只是模式“L”的像素是8bit,而模式“I”的像素是32bit。

8、模式“F”

模式“F”为32位浮点灰色图像,它的每个像素用32个bit表示,0表示黑,255表示白,(0,255)之间的数字表示不同的灰度。在PIL中,从模式“RGB”转换为“F”模式是按照下面的公式转换的:

F = R * 299/1000+ G * 587/1000 + B * 114/1000

下面我们将模式为“RGB”的lena图像转换为“F”图像。

例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
>>>from PIL import Image
 
>>> lena =Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")
 
>>>lena.getpixel((0,0))
 
(197, 111, 78)
 
>>>lena.getpixel((0,1))
 
(196, 110, 77)
 
>>> lena_F =lena.convert("F")
 
>>> lena_F.mode
 
'F'
 
>>>lena_F.getpixel((0,0))
 
132.95199584960938
 
>>>lena_F.getpixel((0,1))
 
131.95199584960938

模式“F”与模式“L”的转换公式是一样的,都是RGB转换为灰色值的公式,但模式“F”会保留小数部分,如实验中的数据。

2017-10-08 16:52:01 hjy0304 阅读数 31782

第一章 绪论

图形图像处理起源于20世纪20年代,当时通过海底电缆从英国伦敦到美国纽约采用数字压缩技术传输了第一幅数字照片,用来改善图像的质量。此后由于遥感等领域的应用,使得图形图像处理技术逐步得到发展。一直到20世纪50年代,随着大型数字计算机和太空科学研究计划的出现,人们才注意到图像处理的潜力。1964年在美国航空总署的喷气推进实验室开始用计算机技术改善从太空探测器获得的图像。当时利用计算机技术处理由太空船“徘徊者七号”(Ranger 7)发回的月球照片,以校正电视摄影机所存在的几何失真或响应失真。这标志着第三代计算机问世后数字图像处理开始得到普遍应用。

近年来随着计算机与信息技术的高速发展,数字图像处理技术也得到了快速的发展,目前已成为计算机科学、医学、生物学、工程学、信息科学等领域各学科之间学习和研究的对象。

1.1 数字图像

图像是用各种观测系统以不同形式和手段观测客观世界而获得的,可以直接或间接作用于人眼并进而产生视知觉的实体。其最广义的观点是指视觉信息。例如照片、图画、电视画面以及光学成像等。人类的大部分信息都是从图像中获得的。

用计算机进行图像处理的前提是图像必须以数字格式存储,人们把以数字格式存放的图像称之为数字图像。而我们常见的照片、海报、广告招贴画等都属于模拟图像。若要将模拟图像数字化后生成数字图像,需要使用诸如扫描仪之类的数字化设备。模拟图像经过扫描仪进行数字化后,或者由数码照相机拍摄的图片,在计算机中均是以数字格式存储的。

为了把图像数字化,必须进行在空间点阵上的抽样和灰度量化两个方面的工作。被抽样的点称为像素,抽样的精度随图像的种类而不同。这样一来,所谓数字图像就是灰度值的二维数组。一个单色静止图像可以用一个二维的光强度函数f(x,y)来表示,其中x与y表示空间坐标,而在任意点(x,y)的f值与在该点图像的亮度(或灰度)成正比。一个数字图像是图像f(x,y)在空间坐标和亮度上都数字化后的图像。可将数字图像视作一个矩阵,矩阵行与列的值决定一个点,而对应的矩阵元素值就是该点的灰度。这种矩阵的元素就是像素,所对应的灰度就是像素值。

表1.1是以数据结构的观点进行分类的图像种类。即在光谱方向、空间方向、时间轴方向上增加维数的图像,可以用多个二维数组来表示。在这里,不管是一个数组还是其集合,总是要组成用计算机容易处理的形式。因此在传送和复制时,只要在计算机内部进行处理,就不会被破坏而能保持完好的再现性。这是数字处理的一大优点。

表1.1 图像的种类

种 类

形 式

备 注

二值图像

f(x,y)=0,1

文字,曲线,指纹等

灰度图像

0≤f(x,y)≤2n-1

通常的照片,n=6~8是标准的

彩色图像

{fi(x,y)},i=R,G,B

根据三基色的表示

多光谱图像

{fi(x,y)},i=1,…,m

遥感图像用,m多为4~8

立体图像

fL,fR

从左右视点得到的一对图像,用于立体观测

运动图像(时间序列图像)

{ft(x,y)},t=t1,…,tn

动态分析,动画等

早期在英文里一般用picture代表图像,随着数字技术的发展,现在用image代表离散化的数字图像。图像中每个基本单元叫做图像元素,简称像素(picture element)。对于2-D图像,英文中常用pixel代表象素。对于3-D图像,英文中常用voxel代表其基本单元,简称体素(volume element)。

1.2 数字图像处理

1.2.1 数字图像处理的概念

所谓数字图像处理(digital image processing),就是利用计算机对图像进行去除噪声、增强、恢复、分割、提取特征等的理论、方法和技术。由于图像处理是利用计算机和实时硬件实现的,因此也被称为计算机图像处理(computer image processing)。

在计算机处理出现之前,图像处理都是光学、照相处理和视频信号处理等模拟处理。例如,在利用透镜或棱镜的光学演算中使用各种滤光镜,利用胶卷具有的特性曲线进行的处理,在电子回路中的视频信号的处理等,都属于这一范畴。

在人们的日常生活中,图像处理已经得到广泛的应用。例如,利用指纹、虹膜、面部特征等进行身份识别;自动售货机钞票的识别;电脑成像技术等。而在医学领域,计算机图像处理已经成为疾病诊断的重要的手段,譬如显微镜照片、X射线透视、X射线CT(Computer Tomograph,计算机断层摄像)等。

1.2.2 数字图像处理的目的

数字图像处理是利用计算机的计算,实现与光学系统模拟处理相同效果的过程。一般来说,数字图像处理具有如下的目的:

⑴提高图像的视觉质量,以达到赏心悦目的目的。例如,去除称之为噪声等图像质量的退化因素;改变图像的亮度、颜色;增强图像中的某些成份、抑制某些成份;对图像进行几何变换等,从而改善图像的质量,以达到各种想要的艺术效果。

⑵提取图像中所包含的某些特征或特殊信息,以便于计算机分析。如用作模式识别,计算机视觉的预处理等等。这些特征包括很多方面,如频域特性、纹理特性、灰度/颜色特性、边界/区域特性、形状/拓扑特性以及关系结构等。

⑶对图像数据进行变换、编码和压缩,以便于图像的存储和传输。

1.2.3 数字图像处理的内容

要有效解决众多的图像处理应用问题,必须研究出专门的图像处理方法,大致上可以将这些问题及其数字图像处理方式归纳为以下几类。

1. 图像获取、表示和表现(Image Acquisition, Representation and Presentation)

该过程主要是把模拟图像信号转化为计算机所能接受的数字形式,以及把数字图像显示和表现出来。这一过程主要包括摄取图像、光电转换及数字化等几个步骤。

2. 图像增强(Image Enhancement)

  图像增强是用来强调图像的某些特征,以便于作进一步的分析或显示。当无法得知图像退化有关的定量信息时,可以使用图像增强技术较为主观地改善图像的质量。所以,图像增强技术是用于改善图像视感质量所采取的一种重要手段。它所完成的工作包括去除图像噪声,增强图像对比度等。例如,对比度的增强是用来使对比度低的图像更容易显现其特征,而低对比度的可能原因包括光线不足、图像感应器的动态范围不够以及在图像摄取时光圈设定错误等。图像增强的过程本身并没有增加原始资料所包含的信息,仅仅是把图像某些部分的特征更加强调罢了。图像增强的算法通常是交互式的,而且与所考虑的应用有着密切的联系。

3. 图像恢复(Image Restoration)

  图像恢复是指在图像退化(图像品质下降)的原因已知时,对图像进行校正,重新获得原始图像的过程。使图像降质的因素有很多,包括感应器或拍摄环境的干扰,感应器的非线性几何失真,没有对焦精确所造成的模糊,摄象机与物体之间相对运动所造成的模糊等。图像恢复最关键的是对每一种退化都需要建立一个合理的模型。退化模型和特定数据一起描述了图像的退化,因此恢复技术是基于模型和数据的图像恢复,其目的是试图将受污染或降质的图像带回到原本不受污染的状况下所应得的干净图像,产生一个等价于理想成像系统获得的图像。虽然图像恢复与图像增强都会造成视觉上较佳的感受,但后者更关心的是图像特征增强或抽取,而不是去除退化或污染。

4. 图像重建(Image Reconstruction)

  图像重建的工作是由几个一维的图像投影来重建出更高维的物体图像。它与图像增强、图像恢复等不同。图像增强和图像恢复的输入都是图像,处理后输出的结果也是图像。而图像重建则是指从数据到图像的处理,即输入的是某种数据,经过处理后得到的结果是图像。一个图像的取得是以平行的X光或者其他的放射穿透光束照射物体,并在物体的背面接收此投影,接着在同一平面上改变光束照射的角度以获得不同的投影,再以某些重建算法将这些投影组合成物体的一个横剖面图像。这种技术主要用于医学图像、雷达图像处理、天文学星象观测、地质研究及无损压缩等。

5. 图像压缩(Image Compression)

图像压缩的目的是降低代表数字图像所需要的数据量,这样做的好处是可以减少图像传输时间以及存储空间。编码是实现图像压缩的重要手段。图像压缩编码主要是利用图像信号的统计特性以及人类视觉的生理学和心理学特性,对图像信号进行高效编码,即研究数据压缩技术,其目的是在保证图像质量的前提下压缩数据,以解决图像数据量大的矛盾。一般来说,图像编码的目的有三个:①减少数据存储量。②降低数据率以减少传输带宽。③压缩数据量,便于特征提取,为后续识别作准备。

从编码技术的发展来看,Kunt提出了第一代、第二代的编码概念。第一代编码是以去除冗余为基础的编码方法,如PCM、DPCM、ΔM、DCT、DFT、W-H变换编码以及以此为基础的混合编码法。第二代编码法多为20世纪80年代以后提出的,如Fractal编码法、金字塔编码法、小波变换编码法、模型基编码法、基于神经网络的编码法等等。这些编码方法有如下特点:①充分考虑人的视觉特性。②恰当地考虑对图像信号的分解与表述。③采用图像的合成与识别方案压缩数据。

6. 图像分割(Image Segmentation)

  图像分割就是把图像分成区域的过程。这是从处理到分析的转变关键,也是图像自动分析的第一步。图像中通常包含多个对象,图像处理为达到识别和理解的目的,几乎都必须按照一定的规则将图像分割成区域,每个区域代表被成像的一个部分。图像自动分割是图像处理中最困难的问题之一。人类视觉系统能将所观察的复杂景物中的对象分开,并识别出每个物体,但对于计算机来说却是个难题。目前,大部分图像的自动分割还需要人工提供必须的信息来帮助识别,只有一部分领域开始使用。例如印刷字符自动识别(OCR),指纹识别等。

7. 图像分析(Image Analysis)

  图像分析是试图从图像中分割、提取并描述某些特征,从而有利于计算机对图像的识别和理解,以产生有用的信息。图像处理应用的目标几乎都涉及到图像分析。要做图像分析,必须使计算机具有某种程度的智能。这些智能的特征包括:①能从含有许多不相干细节的背景中找到所需的信息。②能从范例中学习并将所学知识应用推广到其他状况中。③能从不完整的资料中推断出完整的信息。

1.3 图像工程

1.3.1 图像工程的内涵

图像技术在广义上来说是各种与图像有关的技术的总称。目前人们主要研究的是数字图像,主要应用的是计算机图像技术。这包括利用计算机和其它电子设备进行和完成的一系列工作,以及为完成各种功能而进行的硬件设计及制作等方面的技术。计算机图像技术的历史可以追溯到1946年世界上第一台电子计算机的诞生,但在20世纪50年代计算机主要还是用于数值计算。到20世纪60年代,第三代计算机的研制成功,以及快速傅立叶变换算法的发现和应用,使得对图像的某些计算得以实际实现。20世纪70年代,图像技术有了长足进步,而且第一本重要的图像处理专著(Rosenfeld 1976)也得以出版。进入20世纪80年代,各种硬件的发展使得人们开始处理3-D图像。

由于图像技术得到了极大的重视和长足的发展,人们需要对它们进行综合研究和集成应用,由此出现了图像工程。图像工程的概念在1982年首先提出,当时主要包括有关图像的理论技术,对图像数据的分析管理以及各种应用。图像工程的内容非常丰富,根据抽象程度和研究方法等的不同,可分为图像处理、图像分析和图像理解三个层次。换句话说,图像工程是既有联系又有区别的图像处理、图像分析及图像理解三者的有机结合,另外还包括它们的工程应用。

1. 图像处理

图像处理的重点是图像之间进行的变换。虽然人们常用图像处理泛指各种图像技术,但比较狭义的图像处理主要是对图像进行各种加工,以改善图像的视觉效果并为自动识别打基础,或对图像进行压缩编码以减少所需的存储空间。

2. 图像分析

图像分析主要是对图像中感兴趣的目标进行检测和测量,以获得它们的客观信息,从而建立对图像的描述。如果说图像处理是一个从图像到图像的过程,则图像分析则是一个从图像到数据的过程。这里的数据可以是目标特征的测量结果,或是基于测量的符号表示,它们描述了目标的特点和性质。

3. 图像理解

图像理解的重点是在图像分析的基础上,进一步研究图像中各目标的性质和它们之间的相互关系,并得出对图像内容含义的理解以及对原来客观场景的解释,从而指导决策。如果说图像分析主要是以观察者为中心来研究客观世界,那么图像理解在一定程度上就是以客观世界为中心,借助知识、经验等来把握整个客观世界。

综上所述,图像处理、图像分析和图像理解是处在三个抽象程度和数据量各有特点的不同层次上。图像处理是比较低层次的操作,它主要在图像像素级上进行处理,处理的数据量非常大。图像分析则进入了中层,分割和特征提取把原来以像素描述的图像转变成比较简洁的非图像形式的描述。图像理解主要是高层操作,基本上是对从描述抽象出来的符号进行运算,其处理过程和方法与人类的思维推理有许多相似之处。

1.3.2 相关学科和领域

图像工程是一门系统地研究各种图像理论、技术和应用的交叉学科。从它的研究方法来看,它可以与数字、物理学、生物学、心理学、电子学、计算机科学等许多学科相互借鉴。从它的研究范围来看,它与模式识别、计算机视觉、计算机图形学等多个专业相互交叉。图像工程的研究进展还与人工智能、神经网络、遗传算法、模糊逻辑等理论和技术有密切的联系。它的发展应用与医学、遥感、通信、文档处理和工业自动化等许多领域也是密不可分的。

图像工程与计算机图形学(Computer Graphics)、计算机视觉(Computer Vision)、模式识别(Pattern Recognition)等有着密切的关系。图形学原本是指用图形、图表、绘图等形式来表达数据信息的科学。而计算机图形学研究的就是用计算机技术生成这些形式的理论、方法和技术,即由非图像形式的数据描述来生成逼真的图像。它既可以生成现实世界中已经存在的物体的图形,也可以生成虚拟物体的图形,它和图像分析的对象和输出结果正好对调。从狭义上讲,模式识别指的是把基于特征的多维模式空间分成不同类别的识别理论。特别是指不依赖于图形和图像,适用于其他一般的模式分类的理论。模式识别和图形分析比较相似,只是前者试图把图像分解成可用符号较抽象地描述的类别。计算机视觉主要强调用计算机实现人的视觉功能,要用到图像工程三个层次的许多技术,目前的研究内容主要与图像理解相结合。

1.4 数字图像处理的应用

概括的说,数字图像处理技术的主要应用领域如下:

⑴通讯。包括图像传输、电视电话、电视会议等,主要是进行图像压缩甚至理解基础上的压缩。

⑵宇宙探测。由于太空技术的发展,需要用数字图像处理技术处理大量的星体照片。

⑶遥感。航空遥感和卫星遥感图像需要用数字技术加工处理,并提取有用的信息。主要用于地形地质分析,矿藏探勘,森林、海洋、水利、农业等资源调查,环境污染监测,自然灾害预测预报,气象卫星云图处理以及地面军事目标的识别等。由于数据量庞大,因此寻求处理及分析这些图像的自动方法,特别是图像对比度增强、分割及图像识别的技术显得极为重要。

⑷生物医学领域中的应用。图像处理在这一领域的应用非常广泛,无论是临床诊断还是病理研究都大量采用图像处理技术。它的直观、无创伤、安全方便等优点备受青睐。图像处理首先应用于细胞分类、染色体分类和放射图像等。20世纪70年代数字图像处理在医学上的应用有了重大突破。1972年,X射线断层扫描CT得到实用;1977年,白血球自动分类仪问世;1980年,人们实现了CT的立体重建。医学图像的种类包括X光图像、同位素图像、核磁共振图像、超声波图像、红外线图像以及显微图像等。对这些图像作对比度增强或伪彩色等的处理可帮助医生诊断疫病。

⑸工业生产中的应用。在生产线中对产品及其部件进行无损检测是图像处理技术的一个重要应用领域。这一领域的应用从20世纪70年代起取得了迅猛的发展,主要有产品质量检测;生产过程的自动控制;CAD和CAM等。

⑹军事、公安等方面的应用。例如军事目标的侦察、制导和警戒系统、自动灭火器的控制及反伪装;公安部门的现场照片、指纹、手迹、人像等的处理和辨识;历史文字和图片档案的修复和管理等。

⑺机器人视觉。机器视觉作为智能机器人的重要感觉器官,其主要任务是进行三维景物理解和识别。机器视觉主要用于军事侦察或处于危险环境的自主机器人;邮政、医院和家政服务的智能机器人;装配线工件识别、定位;太空机器人的自动操作等。

⑻科学可视化。图像处理和图形学的紧密结合,形成了科学研究领域新型的研究工具。例如考古学可用图像处理方法恢复模糊或其他降质状况的珍贵文物图像。

⑼视频和多媒体系统。电视制作系统中广泛使用图像处理、变换、合成;多媒体系统中静止图像和动态图像的采集、压缩、处理、存储和传输等。

⑽电子商务。图像处理技术在这一领域大有可为,如身份认证、产品防伪、水印技术等。

1.5 数字图像处理的发展方向

目前图像处理面临的主要任务是研究新的处理方法,构造新的处理系统,开拓新的应用领域。需要进一步研究的问题有如下几个方面:

⑴在进一步提高精度的同时着重解决处理速度问题。

⑵加强软件研究,开发新的处理方法,特别是要注意移植和见解借鉴其他学科的技术和研究成果,创造出新的处理方法。

⑶加强边缘学科的研究工作,促进图像处理技术的发展。

⑷加强理论研究,逐步形成图像处理科学自身的理论体系。

⑸图像处理领域的标准化。

图像处理技术未来发展方向大致可归纳为:

⑴图像处理的发展将围绕高清晰度电视的研制,开展实时图像处理的理论及技术研究,向着高速、高分辨率、立体化、多媒体化、智能化和标准化方向发展。

⑵图像、图形相结合,朝着三维成像或多维成像的方向发展。

⑶硬件芯片研究。把图像处理的众多功能固化在芯片上,使之更便于应用。

⑷新理论与新算法的研究。近年来随着一些新理论的引入及新算法的研究,将会成为今后图像处理理论与技术的研究热点。例如小波分析(Wavelet)、人工神经网络(artificial neural networks)、分形几何(Fractal)、形态学(Morphology)、遗传算法(Genntic Algorithms)等。

随着科学技术的进步以及人类需求的不断增加,图像处理科学无论是在理论上还是实践上,都会取得更大的发展。

 

MATLAB图像处理基础

 

2.2.1 图像文件格式及图像类型

1.MATLAB支持的几种图像文件格式:

⑴JPEG(Joint Photogyaphic Expeyts Group):一种称为联合图像专家组的图像压缩格式。

⑵BMP(Windows Bitmap):有1位、4位、8位、24位非压缩图像,8位RLE(Run length Encoded)的图像。文件内容包括文件头(一个BITMAP FILEHEADER数据结构)、位图信息数据块(位图信息头BITMAP INFOHEADER和一个颜色表)和图像数据。

⑶PCX(Windows Paintbrush):可处理1位、4位、8位、16位、24位等图像数据。文件内容包括文件头、图像数据和扩展色图数据。

⑷TIFF(Tagged Iamge File Format):处理1位、4位、8位、24位非压缩图像,1位、4位、8位、24位packbit压缩图像,1位CCITT压缩图像等。文件内容包括文件头、参数指针表与参数域、参数数据表和图像数据四部分。

⑸PNG(Portable Network Graphics):包括1位、2位、4位、8位和16位灰度图像,8位和16位索引图像,24位和48位真彩色图像。

⑹GIF(Graphics Interchange Format):任何1位到8位的可交换的图像。

⑺HDF(Hierarchial Data Format):有8位、24位光栅图像数据集。

⑻ICO(Windows Icon resource):有1位、4位、8位非压缩图像。

⑼CUR(Windows Cursor resource):有1位、4位、8位非压缩图像。

⑽XWD(X Windows Dump):包括1位、8位Zpixmaps,XYBitmaps,XYPixmmmaps。

⑾RAS(Sun Raster image):有1位bitmap、8位索引、24位真彩色和带有透明度的32位真彩色。

⑿PBM(Portable Bitmap)。

⒀PGM(Portable Graymap)。

⒁PPM(Portable Pixmap)。

2.MATLAB支持五种图像类型,即二值图像、索引图像、灰度图像、RGB图像和多帧图像阵列。有关它们的定义见下表2.1。

表2.1 图像类型及其对应的像素数据类型

图像类型

Double数据

uint8和uint16数据

二值图像

图像为m×n的整数矩阵,元素值范围[0,1]

图像为m×n的整数矩阵,元素值范围[0,1]

索引图像

图像为m×n的整数矩阵,元素值范围[0,p]

图像为m×n的整数矩阵,元素值范围[0,p-1]

灰度图像

图像为m×n的浮点数矩阵,元素值范围[0,1]

图像为m×n的整数矩阵,元素值范围[0,255]或[0,65535]

RGB图像

图像为m×n×3的浮点数矩阵,元素值范围[0,1]

图像为m×n×3的整数矩阵,元素值范围[0,255]或[0,65535]

其中,多帧图像阵列是由多帧图像组成的,每一帧图像可以为前四种图像中的一种,但组成一个多帧图像阵列的图像必须为同一种。cat函数可以将具有相同尺寸的几个独立图像存成多帧文件。对于多帧图像也可以从中提取单帧。

2.2.2 图像类型判断及转换

1.在MATLAB中如果要判断一个图像文件的类型,可使用如下指令:

l         isbw:若图像为二值图像,则返回真。

l         isgray:若图像为灰度图像,则返回真。

l         isind:若图像为索引图像,则返回真。

l         isrgb:若图像为RGB图像,则返回真。

2.在MATLAB系统中,要将一个类型的图像文件转换成另一个类型的图像文件,只需将前一个文件的图像数据用imread读出,再用imwrite以适当的格式写到后一个图像文件中去即可。另外,要将灰度图像I转换成RGB图像,可运用cat指令。cat函数可以把一些单一的图像合并成图像序列。在图像序列中每个图像需有相同的大小,如果是索引图像,色图也要一致。

此外,MATLAB还提供了若干函数,用于图像类型的转换。这些函数有:

l         dither:用抖动法(dithering)转换图像。该函数通过颜色抖动(颜色抖动即改变边沿像素的颜色,使像素周围的颜色近似于原始图像的颜色,从而以空间分辨率来换取颜色分辨率)来增强输出图像的颜色分辨率。该函数可以把RGB图像转换成索引图像或把灰度图像转换成二值图像。

l         gray2ind:灰度图像或二值图像向索引图像转换。

l         grayslice:设定阈值将灰度图像转换为索引图像。

l         im2bw:设定阈值将灰度、索引、RGB图像转换为二值图像。

l         im2double:将图像数组转换为double型。

l         im2uint8:将图像数组转换为uint8型。

l         im2uint16:将图像数组转换为uint16型。该函数不支持二值图像序列的转换。

l         ind2gray:索引图像向灰度图像转换。

l         ind2rgb:索引图像向RGB图像转换。

l         mat2gray:将一个数据矩阵转换为灰度图像。

l         rgb2gray:RGB图像向灰度图像转换或将彩色色图转换成灰度色图。

l         rgb2ind:RGB图像向索引图像转换。包含三种不同方法:均衡量化、最小值量化、色图映射。

l         im2java:一般图像向Java图像转换。

l         label2rgb:标志图像向RGB图像转换。

2.2.3 图像的查询及读写

在MATLAB中要查询一个图像文件的信息,只要用imfinfo指令加上文件及其完整路径名即可。函数调用格式为:

info = imfinfo(filename,fmt)

info = imfinfo(filename)

参数fmt对应于所有图像处理工具箱中所有支持的图像文件格式。

MATLAB提供了两个重要的用于图像文件的读写的指令,分别是从图像文件中读取数据的imread,以及将数据写入到图像文件中的imwrite。

1.imread的常见调用格式为:

A = imread(filename,fmt)

其作用是将文件名用字符串filename表示的,扩展名用fmt表示的图像文件中的数据读到矩阵A中。如果filename所指的为灰度级图像,则A为一个二维矩阵;如果filename所指的为RGB图像,则A为一个m×n×3的三维矩阵。Filename表示的文件名必须在MATLAB的搜索路径范围内,否则需指出其完整路径。

  imread的其他几种重要的调用格式为:

[X,map] = imread(filename.fmt)

[…] = imread(filename)

[…] = imread(URL,…)

[…] = imread(…,idx)           (CUR,ICO and TIFF only)

[…] = imread(…,’frames’,idx)    (GIF only)

[…] = imread(…,ref)           (HDF only)

[…] = imread(…,’BackgroundColor’,BG)    (PNG only)

[A,map,alpha] = imread(…)      (ICO,CUR and PNG only)

上面一些参数的含义如下:idx是指读取图标(cur、ico、tiff)文件中第idx个图像,默认值为1。’frame’,idx是指读取gif文件中的图像帧,idx值可以是数量、向量或’all’。ref是指整数值。alpha是指透明度。

2.imwrite的常用调用格式为:

imwrite(A,filename,fmt)

imwrite(X,map,filename,fmt)

imwrite(…,filename)

imwrite(…,Param1,Val1,Param2,Val2…)

其中imwrite(…,Param1,Val1,Param2,Val2…)可以让用户控制HDF、JPEG、TIFF等一些图像文件格式的输出特性。

  在MATLAB中,默认的保存类型是uint8。由于PNG和TIFF格式支持16位的图像,所以保存这类图像时,保存类型就是uint16。

2.2.4 图像的显示

显示图像的最基本的手段是使用image函数。该函数还产生了图像对象的句柄,并允许对对象的属性进行设置。此外,imagesc函数也具有image的功能,所不同的是imagesc函数还自动将输入数据比例化,以全色图的方式显示。

imshow函数比image和imagesc更常用,它能自动设置句柄图像的各种属性。imshow可用于显示各类图像。对于每类图像,调用方法如下:

l         imshow filename:显示图像文件。

l         imshow(BW):显示二值图像,BW为黑白二值图像矩阵。

l         imshow(X,map):显示索引图像,X为索引图像矩阵,map为色彩图示。

l         imshow(I):显示灰度图像,I为二值图像矩阵。

l         imshow(RGB):显示RGB图像,RGB为RGB图像矩阵。

l         imshow(I,[low high]):将非图像数据显示为图像,这需要考虑数据是否超出了所显示类型的最大允许范围,其中[low high]用于定义待显示数据的范围。

有关图像显示的函数或其辅助函数,除了上述的以外,MATLAB还提供了一些用于进行图像的特殊显示的函数。

l         colorbar:为图像的显示增加一个颜色条,这一用法对于了解被显示图像的灰度级别特别有用。

l         getimage:获取图像数据。

l         immovie:将多帧索引图像制作成连续图像格式。其调用格式为:

mov = immovie(D,map)

不过这种功能只对索引图像有效,其中D为多帧索引图像阵列,map为索引图像的对应色阶。对于其他类型图像,则需要首先将其转换为索引图像。

l         montage:多帧图像的一次显示。它能将每一帧分别显示在一幅图像的不同区域,所有子区的图像都用同一个色彩条。

l         movie:播放多帧连续图像。

l         subimage:在一个图形区域内显示多个图像。

l         truesize:调整图像显示的尺寸。

l         warp:显示图像的纹理表面图。前面提到的图像显示手段都只能在二维平面上显示,MATLAB6.5的一个强大功能是能将平面图像显示在空间三维曲面上。这是由warp函数的纹理成图功能来实现的,该功能能通过双线性插值将平面图像投影到三维曲面上。

l         zoom:将图像或二维图形进行放大或缩小显示。zoom本身是是一个开关键,zoom on用于打开缩放模式,zoom off用于关闭该模式,zoom in用于放大局部图像,zoom out用于缩小图像。

至于多个图像的显示,则可分为两个方面:在不同的图形窗口显示不同的图像,可以用figure指令来实现;在同一个图形窗口显示多图,可以用subplot来实现。

第三章 图像运算

3.1 图像的点运算

点运算将输入图像映射为输出图像,输出图像每个像素点的灰度值仅由对应的输入像素点的值决定。它常用于改变图像的灰度范围及分布,是图像数字化及图像显示的重要工具。点运算因其作用性质,也被称为对比度增强、对比度拉伸或灰度变换。在真正进行图像处理之前,有时可以用点运算来克服图像数字化设备的局限性。

点运算实际上是灰度到灰度的映射过程。点运算不会改变图像内像素点之间的空间关系。设输入图像为A(x, y),输出图像为B(x, y),则点运算可表示为:

B(x, y) = f [A(x, y)]                (3-1)

点运算可完全由灰度变换(gray-scale transformation)函数s=f (r)决定,后者描述了输入灰度级与输出灰度级之间的映射关系。图像的点运算分为线性点运算和非线性点运算两种。

3.1.1 线性点运算

线性点运算是指灰度变换函数f为线性函数时的运算。

如图3.1,当a>1时,输出图像对比度增大;当a<1时,输出图像对比度降低;当a=1,b=0时,输出图像就是输入图像的简单复制;当a=1,b≠0时,仅使输出图像的灰度值上移或下移,其效果是使整个图像更亮或更暗。如果a为负值,暗区域将变亮,亮区域将变暗,点运算完成了图像求补。

除了调节对比度以外,还有一种典型的线性点运算的应用就是灰度标准化。设灰度图像为I[W][H],其中W表示图像宽度,H表示图像的高度,那么灰度图像的平均灰度和方           图3.1 线性函数

差由如下计算公式得到:

平均灰度:                         

                                (3-2)

方差:

                             (3-3)

可以将其变换为具有相同均值和方差的变换函数(线性映射),其形式如下:

                 (3-4)

其中σ0和u 0为给定的变换参数。灰度标准化可以用来生成一些常用的平均模型。

3.1.2 非线性点运算

非线性点运算对应于非线性映射函数,典型的映射包括平方函数、对数函数、截取函数(窗口函数)、域值函数、多值量化函数等。

阈值化处理是最常用的一种非线性点运算,它的功能是选择一阈值,将图像二值化,然后使用生成的二进制图像进行图像分割及边缘跟踪等处理。

直方图均衡化也是一种非常常用的非线性点运算。它是指将一个已知灰度分布的图像使用某种非线性灰度变换函数进行计算,使运算结果变成一幅具有均匀灰度分布的新图像。经过直方图均衡化的点运算处理后,实际的直方图将呈现参差不齐的外形,这是由于灰度级的可能个数是限造成的。在一些灰度级处可能没有像素,在另外一些灰度级处则像素很拥挤。

点运算的MATLAB实现:

I=imread('rice.png');

rice=double(I);

rice2=rice*0.5+50;

J=uint8(rice2);

subplot(1,2,1),imshow(I);

subplot(1,2,2),imshow(J);

 

 

 

 

MATLAB在数字图像处理中的应用

 

2.1 几个基本术语

   

    在运用MATLAB进行数字图像处理之前,我们必须明确几个基本术语:

1)位图:是根据图像的尺寸和分辨率创建和保存的图像,由扫描输入。

2)矢量图:使用专用软件绘制的,以数学方程式的方式保存的图像,所以矢量图的清晰度与分辨率无关。

3)象素:是图像在计算机显示中的度量单位,可以变化,可大可小。

4)分辨率:是用于度量图像在显示器中清晰程度的一个参数,分辨率越高,图像越清晰。分辨率是与象素相关的,即单位长度上的象素数就是分辨率。由此可知,分辨率越高,象素的几何尺寸就越小。

5)图像文件的大小:指一幅图像在计算机中保存时所占用的磁盘空间,其大小与所用的颜色模式有关。灰度图像中的每一个灰度象素只占用一个字节(8位),RGB图像中红、绿、蓝各占用一个字节。另外,图像文件的大小也直接与其分辨率有关,原因是当分辨率增加时,一幅图像所包含的象素量急剧增加。

6)句柄:通俗地说就是对象的代号或标志,它能使计算机方便地从众多对象中找到所需要的对象并对之加以相应的操作。MATLAB中的句柄图形对象包括轴、文本、菜单、控制框、图像等。

2.2   MATLAB 图像文件格式简介

    针对MATLAB的数字图像处理功能,我们讨论它可以处理的几种图像文件格式:

A)PCX格式。可处理1、4、8、16、24位等图像数据。文件内容包括文件头 、图像数据、扩展调色板数据。

B)BMP格式,即位图文件,整幅图可视为一个数字矩阵。它包括1、4、8、24位非压缩图像,8位RLE(行程编码)图像。文件内容包含文件头、位图信息数据块和图像数据。选择BMP格式保存一幅灰度模式图像时,可选择以Windows格式保存。而且在选中4位或8位位图时,还可选压缩(RLE)项,在用RLE方式压缩保存后图像将毫无损失。这是用得最广的图像格式之一,在本文中都对这种格式的图像进行操作。

C)HDF格式。有8位,24位光栅图像数据集。

D)JPEG格式。是一种联合图像专家组的图像压缩格式,是目前所用对静止灰度或彩色图像的压缩标准。它实际上定义了3种编码系统:

a.基于DCT的有损编码基本系统,可用于绝大多数压缩场合;

b.用于高压缩比、高精度或渐进重建应用的扩展编码系统;

c.用于无失真应用场合的无损系统。JPEG没有规定文件格式、图像分辨率或所用的彩色空间模型,这使它就有可能适用于MATLAB。

D)TIFF格式。处理1、4、8、24位非压缩图像,1、4、8、24位 packbit 压缩图像,1位CCITT压缩图像等。文件内容包括:文件头、参数指针表与参数域、参数数据表和图像数据四部分。它是一种用途广泛的文件格式,其特点是可移植性好,几乎所有的扫描仪及在Windows、Macintosh平台上常用的版面设计软件都支持TIFF文件格式。以这种格式保存的图像文件结构比较复杂,在不压缩存放时文件比较大。

E)XWD格式。1、8位Zpixmaps, Xybitmaps, 1位XYPixmaps。

F)TGA格式。处理1、4、8、16、24位非压缩图像和行程编码图像。文件包由5个固定长度字段和3个可变长度字段组成。

2.3   MATLAB图像文件类型

    根据数据矩阵和图像象素点颜色的匹配关系,MATLAB中的图像可分为三类:索引图像、灰度图像和RGB图像。

1)索引图像:它的数据信息包括一个数据矩阵和一个双精度色图矩阵,它的数据矩阵中的值直接指定该点的颜色为色图矩阵中的某一种。色图矩阵中,每一行表示一种颜色,每行有三个数据,分别表示该种颜色中红、绿、蓝的比例情况,所有元素值都在[0,1]内。

2)灰度图像:它的数据矩阵中的元素值一般都在[0,1]或[0,255]之间,灰度图像根据这些数据利用线性插值来和色图中的颜色种类匹配。

3)RGB图像:图像中每个象素的颜色用三个数据来存储,分别指定红、绿、蓝三原色在象素颜色中的比例关系,组成一个三维数组。

2.4   MATLAB中图像的存储运算和显示方式

     

在MATLAB中,数值一般都采用double型(64位)存储和运算,为了节省存储空间,MATLAB为图像提供了特殊的数据类型uint8(8位无符号整数),以此方式存储的图像称为8位型像。函数image能够直接显示8位图像,但8位型数据和double型数据在image中意义不一样,对于索引图像,数据矩阵中的值指定该像素的颜色种类在色图矩阵中的行数。当数据矩阵中的值为0时,表示用色图矩阵中第一行表示的颜色绘制;当数据矩阵中的值为1时,表示用色图矩阵中的第二行表示的颜色绘制该像素,数据与色图矩阵中的行数总是相差1。所以,索引图像double型和uint8型在显示方法上没有什么不同,只是8位数据矩阵的值和颜色种类之间有一个偏差1。调用格式均为image(x); colormap(map);对于灰度图像,uint8表示范围[0,255],double型表示范围[0,1]。可见,double型和uint8型灰度图像不一样,二者转换格式为:

I8=uint8 (round (I64*255));

I64=double (I8)/255;

反之,imread根据文件中的图像种类作不同的处理。当文件中的图像为灰度图像时,imread把图像存入一个8位矩阵中,把色图矩阵转换为双精度矩阵,矩阵中每个元素值在[0,1]内;当为RGB图像时,imread把数据存入到一个8位RGB矩阵中。

    本软件的处理统一针对BMP格式的灰度图。在编程时图像读入与输出均要求转换为uint8型,中间运算处理过程则要用double型。

2.5  从零开始学用MATLAB

     

     MATLAB对于我来说是一门全新的语言,一般在编辑框中编程存盘后在命令框内运行,在Figure框中显示图像。在用它作数字图像处理的过程中,最常碰到的问题有:

①     图像读入 imread (‘文件名.格式’,’格式’),必须是上文提过的MATLAB支持的7种格式之一,而用Photoshop制作的PSD图像保存了所有通道和图层的信息,不能直接用MATLAB来处理。显示图像用imshow (h) 语句,h 为图像句柄;在一幅图片中显示子图用subplot规定子图的位置和大小,用subimage(h)输出子图。输出图像若需要永久保存,则可用imwrite (h,map, ’filename.bmp’,’bmp’), 写入存储器。注意在该语句前要设置调色板,即map=(gray(256))。

②     结构化程序语句写法不同于C语言。比如if, for 之后要用end 表示这一块结束。有关条件的语句都不用加括号,而用冒号来表示递增,如

for   i=1:3:10

   表示 i从1以步长3递增到10,即做三次循环。

③     要注意图像格式的转化。须知不同的图像格式对应不同的处理方式,如果处理与格式不符,将引起错误。比如范例中的图片lena256.bmp表现为灰度图,但其实质仍为RGB图像。如果不用语句rgb2gray将其转化为256级灰度图,经变换后图像会变红或变蓝。

④     数组的定义方式与C语言不同。由于C语言中含N个元素的一维数组A的下标从0到N-1,数组定义为A[N];同样的数组,MATLAB规定的下标是从1到N,所以不能再用A[N]来表示数组,只能用它表示数组的第N个元素。赋值时用A代表数组。

⑤     由于在本演示软件中,涉及较多点运算,所以运行速度较慢。等待时未知其是否顺利运行。这时最好在最外层循环加上计数标志,即变量名,这样对程序运行的影响不大,却可以知道程序的运行情况,有助于查错。但如果在内层循环加标志的话,将大大减慢运行速度。

⑥     尽管MATLAB允许未定义使用数组,但在实际应用中这样经常出错,特别是遇到在double和uint8型之间的转换时。所以最好还是养成用前定义的习惯,避免出现不必要的错误。

⑦     在做完一定量的运算后,一般要用Clear清除内存变量,以防影响后面的程序运行。

 

matlab调试工具

2007-05-31 09:32

在开发函数M文件过程中,不可避免地出现错误,即故障。MATLAB提供了很多函数和方法,帮助调试函数。

在MATLAB表达式中,有两类错误:语法错误和运行错误。当MATLAB计算一个表达式的值或一个函数被编译到内存时会发现语法错误。一旦发现语法错误,MATLAB立即标志这些错误,并提供有关所遇到的错误类型,以及发生错误处M文件的行数。给定这些反馈信息,就很容易纠正这些错误。

而另一方面,即使MATLAB标志了运行错误,但找出错误一般比较困难。当发现运行错误时,MATLAB把控制权返回给命令窗口和MATLAB的工作空间。失去了对发生错误的函数空间的访问权,因此,用户不能询问函数工作空间中的内容排除问题。

根据作者的经验,当一些操作结果导致空矩阵或NaNs时,最容易发生运行错误。所有有关NaNs的操作都返回NaNs值。因此,如果有可能出现NaNs结果,则当出现NaNs时,最好运用逻辑函数isnan来执行一些缺省操作。因为空矩阵为零维,所以对空矩阵寻址常常导致错误。函数find表示了可产生空矩阵结果的一般情况。如果函数find的空矩阵输出用于索引其它数组,所返回的值也将是空的。这样,空矩阵具有传播性质。例如:

>>x=pi*(1 : 4)    %  example data

>>i=find(x>20)  %  use find function

>>y=2*x(i)     %  propagate the empty matrix

很清楚,当希望y具有有限维数和值时,可能发生运行错误。当执行一个操作或使用可返回空结果的函数时,逻辑函数isempty有利于为空矩阵定义一个缺省值,这样避免运行错误。

有几种调试函数M文件的方法。对于简单的问题,可直接使用下列的方法组合:

1、去掉文件中所选择的行的分号,以便中间结果显示在命令窗口中。

2、在文件中加入显示感兴趣的变量的语句

3、把keyboard命令放在文件中所选择的地方,给键盘暂时控制权。这样,可以查询函数空间并按需要改变其值。

4、在M文件开始,在function语句前加上%,将函数M文件改变为脚本M文件。当MATLAB执行该脚本M文件时,该空间就是MATLAB工作空间。这样,当发生错误时可以询问。

当M文件大,递归调用或者多次嵌套(即调用其它M文件函数,被调用M文件函数又调用其它M文件函数,等等)时,用MATLAB的调试函数会更方便。与上述所列方法相反,这些调试函数不要求将有问题的M文件进行编辑。表16.1所给出的这些函数类似于其它高级编程语言中所提供的函数。有关进一步的信息,以及它们的使用实例,参阅《MATLAB用户指南》。

表16.1

MATLAB调试函数

dbclear:

取消断点

dbcont:

在断点后恢复运行

dbdown:

工作空间下移

dbquit:

退出调试模式

dbstack:

列出谁调用谁

dbstatus:

列出所用的断点

dbstep:

执行一行或多行

dbstop:

设置断点

dbtype:

列出带行号的M文件

dbup:

工作空间上移

图像类型转换函数

 

MATLAB - elevenguy - elevenguy的博客 MATLAB命令

默认情况下,matlab将图象中的数据存储为double型,即64位浮点数;matlab还支持无符号整型(uint8和uint16);uint型的优势在于节省空间,涉及运算时要转换成double型。

im2double():将图象数组转换成double精度类型

im2uint8():将图象数组转换成unit8类型

im2uint16():将图象数组转换成unit16类型

图像类型转换函数:

dither() 通过颜色抖动,把真彩图像转换成索引图像或灰度图象转换成二值图像

gray2ind() 将灰度图像(或二值图像)转换成索引图像

grayslice() 通过设定的阈值将灰度图象转换成索引图像

im2bw() 通过设定亮度阈值将灰度、真彩、索引图象转换成二值图像

ind2gray() 将索引图象转换成灰度图象

ind2rgb() 将索引图象转换成真彩色图像

mat2gray() 将一个数据矩阵转换成一幅灰度图象

rgb2gray() 将真彩转换成灰度图象

rgb2ind() 将真彩转换成索引图象

图像类型与类型间的转换

1。索引图像:包括一个数据矩阵X和一个色图阵MAP。矩阵元素值指向MAP中的特定颜色向量。

2。灰度图像:数据矩阵I,I中的数据代表了颜色灰度值。矩阵中的元素可以是double类型、8位或16位无符号的整数类型。

3。RGB图像:即真彩图像。矩阵中每个元素为一个数组,数组的元素定义了像素的红、绿、蓝颜色值。RGB数组可以是double类型、8位或16位无符号的整数类型。

4。二值图像:一个数据阵列,每个象素只能取0或1。

矩阵的基本运算

行列式求值:det(A)

矩阵加减:+、-

矩阵相乘:*

矩阵左除:A/B      %相当于inv(A)*B

矩阵右除:A\B      %相当于A*inv(B)

矩阵的幂:^

矩阵转置:'

矩阵求共轭(实部相同,虚部相反):conj(X)

矩阵求逆:inv(X)

级数的求和与收敛

symsum(fun,var,a,b):其中fun是通项表达式,var为求和变量,a为求和起点,b为求和终点

例如:I为1/[n*(2n+1)]从1到正无穷的和,求I

syms n;

f1=1/(n*(2*n+1));

I=symsum(f1,n,1,inf)

计算结果为:

I =2-2*log(2)

空间曲面

mesh()函数语法:

mesh(Z):

mesh(X,Y,Z,C):其中C是用来定义相应点颜色等属性的数组

例:求x^2+y^2=z的空间曲面

x=-4:4;

y=x;

[X,Y]=meshgrid(x,y);%生成x,y坐标

Z=X.^2+Y.^2;

mesh(X,Y,Z)

曲面图

[x,y]=meshgrid(xa,ya) 当xa,ya分别为m维和n维行向量,得到x和y均为n行m列矩阵。meshgrid常用于生成x-y平面上的网格数据;

mesh(x,y,z)绘制网面图,是最基本的曲面图形命令,其中x、y、z是同阶矩阵,表示曲面三维数据;

mesh(xa,ya,z) xa,ya分别为m维和n维向量,z为n行m列矩阵。等价于先[x,y]=meshgrid(xa,ya)再mesh(x,y,z);

surf(x,y,z)绘制曲面图,与mesh用法类似;

contour(x,y,z)绘制等高线图,与mesh用法类似,可指定z的范围;

contour3(x,y,z)绘制三维等高线图,与mesh用法类似,可指定z的范围。

空间曲线

例:求方程组的空间曲线

1。化为参数方程组

x=t

y=sqrt[t(1-t)]

z=sqrt[1-x^2-y^2]

2。 程序

t=0:0.001:1;

x=t;

y=sqrt(t.*(1-t));

z=sqrt(1-x.^2-y.^2);

plot3(x,y,z,z,-y,z)

其中.*为数组相乘,.^为数组乘方

matlab实现离散余弦变换压缩(JPEG压缩原理)

比部分上篇文章已经介绍过,为了保持文章的完整性,继续保留。

JPEG图像压缩算法:

输入图像被分成8*8或16*16的小块,然后对每一小块进行二维DCT(离散余弦变换)变换,变换后的系数量化、编码并传输;

JPEG文件解码量化了的DCT系数,对每一块计算二维逆DCT变换,最后把结果块拼接成一个完整的图像。在DCT变换后舍弃那些不严重影响图像重构的接近0的系数。

DCT变换的特点是变换后图像大部分能量集中在左上角,因为左上放映原图像低频部分数据,右下反映原图像高频部分数据。而图像的能量通常集中在低频部分。

实例程序:

function Jpeg

I=imread('D:\MATLAB7\toolbox\images\imdemos\cameraman.tif');

%该图片在安装matlab的目录中找,原图为灰度图象

I=im2double(I);%图像存储类型转换

T=dctmtx(8);%离散余弦变换矩阵

B=blkproc(I,[8 8],'P1*x*P2',T,T');

%对原图像进行DCT变换

mask=[1 1 1 1 0 0 0 0

       1 1 1 0 0 0 0 0

       1 1 0 0 0 0 0 0

       1 0 0 0 0 0 0 0

       0 0 0 0 0 0 0 0

       0 0 0 0 0 0 0 0

       0 0 0 0 0 0 0 0

       0 0 0 0 0 0 0 0];

B2=blkproc(B,[8 8],'P1.*x',mask);

%数据压缩,丢弃右下角高频数据

I2=blkproc(B2,[8 8],'P1*x*P2',T',T);

%进行DCT反变换,得到压缩后的图像

imshow(I)

title('原始图像')

figure;

imshow(I2)

title('压缩后的图像')

应用到的函数:

I=imread('图像文件名') :读取图像数据,保存在矩阵I中;

imshow(I) :显示灰度图像I,其他用法见matlab帮助;

I2=im2double(I1) :把图像数组I1转换成double精度类型;

D=dctmtx(n) :二维离散余弦变换函数,返回n*n离散余弦变换矩阵。

一个n*n的变换矩阵T被定义成:

Tpq=1/sqrt(n)                                  

,当p=0,0<=q<=M-1;

Tpq=sqrt(2/n)*cos[pi*(2q+1)*p/2n]   

,当1<=p<=M-1,0<=q<=M-1。

B=blkproc(A,[m n],fun,P1,P2...) :块操作函数。对图像A的每个不同的m*n块应用fun函数,P1,P2等为fun函数参数。在图像边缘用0来扩展;只有当fun的返回矩阵是m*n矩阵时,B和A的大小才相同。

figure:强制生成一个新的个绘图窗口;

非线性方程求解

fsolve(fun,x0,options)

其中fun为待解方程或方程组的文件名;

x0位求解方程的初始向量或矩阵;

option为设置命令参数

建立文件fun.m:

function y=fun(x)

y=[x(1)-0.5*sin(x(1))-0.3*cos(x(2)), ...

     x(2) - 0.5*cos(x(1))+0.3*sin(x(2))];

>>clear;x0=[0.1,0.1];fsolve(@fun,x0,optimset('fsolve'))

注:

...为续行符

m文件必须以function为文件头,调用符为@;文件名必须与定义的函数名相同;fsolve()主要求解复杂非线性方程和方程组,求解过程是一个逼近过程。

不定积分与定积分

不定积分:int(fun,var)

例:求∫sinaxsinbxsincxdx

syms a b c x

y=sin(a*x)*sin(b*x)*sin(c*x);

int(y,x);

pretty(ans)

定积分:int(fun,var,a,b)

其中a,b分别为上下限

求解线形方程

solve,linsolve

例:

A=[5 0 4 2;1 -1 2 1;4 1 2 0;1 1 1 1];

%矩阵的行之间用分号隔开,元素之间用逗号或空格

B=[3;1;1;0]

X=zeros(4,1);%建立一个4元列向量

X=linsolve(A,B)

diff(fun,var,n):对表达式fun中的变量var求n阶导数。

例如:F=sym('u(x,y)*v(x,y)');    %sym()用来定义一个符号表达式

diff(F);   %matlab区分大小写

pretty(ans) %pretty():用习惯书写方式显示变量;ans是答案表达式

求极限

limit:

例:limit(F,x,a,left);对表达式F求极限,变量为x,从左边趋近a。

inf:正无穷;

-inf:负无穷。

matlab之基本绘图函数

clear:清空内存中的变量;

figure:强制生成一个新的个绘图窗口;

syms x y t :声明变量;

fplot(函数表达式,绘图区间);

plot(横坐标向量,纵坐标向量,颜色/线形等参数)

ezplot(函数表达式):简单的fplot,easy fplot

axis([xmin xmax ymin ymax ...]):设置坐标轴显示范围

 

MATLAB常见问题集

 

Matlab的常见问题

===================================

1).Matlab 6.X在Windows 2000/XP上无法启动

2).我有一组x,y,z值,非规则排列,如何在Matlab中绘图?

3).如何在给定句柄的axis里绘图?

4).由Matlab符号运算得到的公式怎么才能将数据代进去运算?

5).在Matlab中如何求最值点?如何求一维数组的极值?

6).Matlab中如何作线性拟合/线性回归/多元线性回归?

7).Matlab中如何作圆回归?

8).Matlab中如何绘制箭头?

9).Matlab中如何作二维数据的插值?

10).Matlab中如何绘制三维数据阵?

11).Matlab中如何注解一大段代码?

12).Matlab中如何计算程序运行的时间?

13).Matlab中如何改变默认的工作路径?

14).Matlab如何改变默认的图形字体?

15).如何在Matlab中实现交互操作?

16).Matlab中为什么只能在小数点后显示四位?

17).Matlab如何在命令窗口按照格式输出?

18).如何在Matlab中画隐函数曲线?

19).Matlab中什么函数可以删除矩阵的某一行或列?

20).Matlab中能开的最大数组是由什么决定的?

21).如何在Matlab中添加新的工具箱?

22).如何读写Matlab的.mat文件?

23).如何得到contour线上的坐标点?

24).如何将Matlab绘制的三维网格图帖到word里?

25).请问可以查看Matlab中函数的源代码吗?

26).Matlab有没有求矩阵行数/列数/维数的函数?

27).Matlab中如何中断运算?

28).Matlab中有没有画圆或椭圆的函数?

29).Matlab下如何定义整形

30).Matlab如何产生均匀分布的白噪声?

31).在Matlab中debug的时候能否跟踪变量的?

32).请问在Matlab中怎样输入特殊符号啊或者上标、下标?

33).Matlab中如何后台运行一个DOS程序?

34).Matlab如何加载输入文件(批处理模式). ?

35).Matlab如何启动时执行规定的文件?

36).如何在Matlab GUI中使用图形背景?

37).大量数据点Matlab绘图为什么很慢?

38).Matlab中如何求解广义积分?即积分限到有无穷的或者有歧

异点的积分(瑕积分)?

39).为什么我的Matlab程序这么慢?

40).Matlab中如何作线性拟合/线性回归/多元线性回归?

>*****************************************************************************<

Matlab的常见问题

>*****************************************************************************<

===================================

1)Matlab 6.X在Windows 2000/XP上无法启动

:#highsun,2001/3/2, SMTH/NewSoftware #

其实也出来很久了,不知大家有没有注意到.

虽然是针对繁体中文系统的,我试过在简体

中文系统下一样可以用。

http://www.mathworks.com/support/solutions/data/26985.shtml

http://www.mathworks.com/support/solutions/data/26990.shtml

Solution Number: 26990

Date Last Modified: 2001-01-30

Product: MATLAB 6.0 ==> Current Version

Platform: Windows

Problem Description

Why do I encounter problems when running MATLAB 6.0 (R12) on Hebrew

or

Traditional Chinese (Taiwan) Windows? I try to start MATLAB but after

the splash screen disappears, MATLAB exits.

PLEASE NOTE: This solution only applies to MATLAB 6.0. If you have a

similar problem with MATLAB 5.0 or the Student Edition of MATLAB 5.0,

see solution 7213.

Solution:

This problem is caused by a bug in one of the font properties files we ship

with MATLAB. The font.properties file is used by Java to map the standard

Java font names to system fonts for a particular language operating system.

However, we made a few assumptions that do not hold for the Hebrew or

Traditional Chinese Windows, causing this problem.

We have created a fixed version of the mwt.jar file that you can use to

correct this. To use the fix, first rename your mwt.jar file as mwt.old.

This file is found in the $MATLAB\java\jar directory, where $MATLAB is your

MATLAB root directory. Then download the newer mwt.jar file from:

ftp://ftp.mathworks.com/pub/tech-support/solutions/s26990

and place it in your $MATLAB\java\jar directrory. Then restart MATLAB;

this should correct the problem you're seeing.

2)我有一组x,y,z值,非规则排列,如何在Matlab中绘图?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/12, BigGreen/MathTools #

参见第一节问题7)

3)如何在给定句柄的axis里绘图?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/12, SMTH/MathTools #

plot(data,'parent',haxis);

或者

hbar=bar(data);

set(hbar,'parent',haxis);

4)由Matlab符号运算得到的公式怎么才能将数据代进去运算?

:#ramjet (德芙)2002/3/3, SMTH/MathTools #

使用subs(),或先将值赋予一个符号变量,然后用eval()

5)在Matlab中如何求最值点?如何求一维数组的极值?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/18, SMTH/MathTools#

最值:

一维或多维数组最值用max(data()

如果想返回最值所在的位置,用[Y,I]=max(data)

:#FangQ(Qianqian.Fang@Dartmouth.Edu), 2001/4/21,UESTC/Math#

极值:

data是你的数据,

find(diff(sign(diff(data)))==-2)+1

找到极大值的位置

find(diff(sign(diff(data)))==2)+1

找到极小值的位置

data(find(diff(sign(diff(data)))==-2)+1)和

data(find(diff(sign(diff(data)))==2)+1)

返回的是极大值和极小值

6)Matlab中如何作线性拟合/线性回归/多元线性回归?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21, BigGreen/MathTools #

即用y=a*x+b来拟合一组数据{{x1,y1},{x2,y2}…{xn,yn}}

matlab中使用polyfit

x=data(:,1);

y=data(:,2);

p=polyfit(x,y,1);

p(1)为斜率a,p(2)为截距b

多元线性回归即用y=a1*x1+a2*x2+..+am*xm来拟合数据点{x1i,x2i,…xmi,yi}

(i=1~n)

|x11,x21,…xm1|

A=|x12,x22,…xm2|

|…………… |

|x1n,x2n,…xmn|

Y={y1,y2,y3,…,yn}'

则系数{a1,a2,…,am}'=pinv(A)*Y

在matlab中使用

coeff=A\Y

则可以得到最小二乘意义上的拟合系数

7)Matlab中如何作圆回归?

:#Peter Boettcher (boettcher@ll.mit.edu),2002/5/16, comp.soft-sys.matlab#

Q5.5: How can I fit a circle to a set of XY data?

=================================================

An elegant chunk of code to perform least-squares circle fitting was

written by Bucher Izhak and has been floating around the newgroup for

some time. The first reference to it that I can find is in:

function [xc,yc,R,a] = circfit(x,y)

%CIRCFIT Fits a circle in x,y plane

%

% [XC, YC, R, A] = CIRCFIT(X,Y)

% Result is center point (yc,xc) and radius R.A is an optional

% output describing the circle's equation:

%

% x^2+y^2+a(1)*x+a(2)*y+a(3)=0

% by Bucher izhak 25/oct/1991

n=length(x); xx=x.*x; yy=y.*y; xy=x.*y;

A=[sum(x) sum(y) n;sum(xy) sum(yy) sum(y);sum(xx) sum(xy) sum(x)];

B=[-sum(xx+yy) ; -sum(xx.*y+yy.*y) ; -sum(xx.*x+xy.*y)];

a=A\B;

xc = -.5*a(1);

yc = -.5*a(2);

R = sqrt((a(1)^2+a(2)^2)/4-a(3));

Tom Davis provided a more sophisticated approach that works for more

cases in and Code included.

8)Matlab中如何绘制箭头?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21, SMTH/MathTools #

http://www.mathworks.com/matlabcentral/fileexchange/index.jsp

2-D Plotting and Graphics中查找arrow.m,或者

http://www.mathworks.com/matlabcentral/spotlight/arrows.shtml

http://www.math.umd.edu/~jec/matcomp/matcompmfiles/mfiles.html

9)Matlab中如何作二维数据的插值?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21, BigGreen/MathTools #

对于一维、二维、三维规则数据点阵使用interp1/interp2/interp3,

二维、三维非规则数据用griddata/griddata3

10)Matlab中如何绘制三维数据阵?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21, BigGreen/MathTools #

如果使用matlab,打开帮助窗口,在目录树上找到

MATLAB\Using Matlab\3-D Visualization: Volume Visualization Techniques

如果图形复杂,建议使用Tecplot,参见Tecplot手册中数据格式,将你

的三维数据读入Tecplot,双击zone,可以设置mesh/contour/surface

transparency等。

在Field菜单中有3D Iso-surface Details和3D Slice Details,可以绘制等值

面和任意平面的截面图。

11)Matlab中如何注解一大段代码?

:#misc,2002/6/21, SMTH/MathTools #

if(0)

大段的代码

end

12)Matlab中如何计算程序运行的时间?

:#misc,2002/6/21, SMTH/MathTools #

tic

your_code;

toc

或者使用

t=cputime;

your_operation;

cputime-t

13)Matlab中如何改变默认的工作路径?

:#SindyGong, 2002/4/7, SMTH/MathTools #

编辑一个startup.m文件,其中cd yourpath

或者在X:\matlab\toolbox\local\matlabrc.m的最后添加cd yourpath

参见:

http://www.mathworks.com/support/solutions/data/25164.shtml

14)Matlab如何改变默认的图形字体?

:#comp.soft-sys.matlab FAQ#

编辑一个startup.m文件,其中

set(0,'DefaultObjectnamePropertyName',value)

或者在X:\matlab\toolbox\local\matlabrc.m的最后添加

set(0,'DefaultObjectnamePropertyName',value)

15)如何在Matlab中实现交互操作?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21,BigGreen/MathTools #

如果只在命令窗口进行交互操作,请参见demo中的例子,主要是

通过input命令和pause/clear/disp等实现的,还有一些窗口资源可以使

用:

uigetfile,uiputfile,uiwait,uisetcolor,uisetfont, uiopen,uisave

inputdlg,msgbox,helpdlg,questdlg,warndlg,errordlg

16)Matlab中为什么只能在小数点后显示四位?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21,BigGreen/MathTools #

用format命令来改变命令窗口数字的显示格式和精度,但不会影

响matlab的计算精度,matlab的矩阵运算默认都是双精度浮点型运算。

17)Matlab如何在命令窗口按照格式输出?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21,SMTHTools #

fprintf(1,"your_format_string",var1,var2,…);

18)如何在Matlab中画隐函数曲线?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21,BigGreen/MathTools #

http://www.mathworks.com/matlabcentral/fileexchange/index.jsp

查找implicit,会找到一个Arthur Jutan写的implot.m

Mathematica中绘制隐函数用ImplicitPlot[]

或者ImplicitPlot3D[]

Maple中为implicitplot(),implicitplot3d()

参见

http://engineering.dartmouth.edu/~fangq/MATH/download/source/Implicit

Plot3D.htm

19)Matlab中什么函数可以删除矩阵的某一行或列?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21,BigGreen/MathTools #

A(j,=[]; %删除A的第j行

A(:,i)=[]; %删除A的第i列

20)Matlab中能开的最大数组是由什么决定的?

:# chenft (mike),2002/6/1, SMTH/MathTools #

I have had similar problems. Below is an explanation I received from Ian

Boyd

from Mathworks (just giving credit where credit is due) that explains

what's happening. You solution is to run matlab with the -nojvm mode.

"The heap memory system in J***A consists of data and handle elements.

When you allocate a variable you get a handle and data. As long as data

has an

associated handle, the JVM considers it valid and will not clean it up.

However, when you call the clear function in MATLAB, all handles are

destroyed, and the data associated is now invalid. This means that the

J***A

engine can free up that data (garbage collection), but does not mean

that it will clean it up at that moment.

Calling the PACK command encourages J***A to run the garbage collector

and de-fragment the memory. But it does not force it to (This is part

of the J***A design). Even though the memory is 'freed' on the heap,

it is not actually free to the OS, it is only free to the JVM. Here

is one way to think of it:

[MATLAB]

[J***A]

[OS]

MATLAB runs on J***A (virtual machine), and Java runs on the OS (physical

machine). So when MATLAB is running in J***A mode memory allocations

are requested from the JRE, not the OS.

One problem you may be running into is that the default maximum J***A heap

size is relatively low ( <= 64 M, so that is all the memory one session

of MATLAB will ever get on your system.

The good news is that you can increase this value. You will need to create

a java.opts file in $MATLAB/bin/$ARCH (or in the current directory when

you

start MATLA and put the following command:

%%%BEGIN CODE%%%

maxHeapSize = 268435456

%%%END CODE%%%

This will give you 256MB of JVM memory and you can adjust the parameter

as needed.

Note: $MATLAB is the root directory and $ARCH is your system

architecture. This solution works on Windows as well as Solaris, Linux,

Alpha, and SGI. A similar operation is possible on IBM and HPUX, but with

a different syntax.

For the 1.1.8 JVM (Windows, Linux, Solaris, Alpha, SGI) our defaults are:

minHeapSize = 16000000

maxHeapSize = 64000000

These are the structure field names in that correspond to -ms and

-mx, and the settings above are roughly 16MB and 64MB.

To investigate the Java heap a bit, ask via the following:

>> java.lang.Runtime.getRuntime.totalMemory

>> java.lang.Runtime.getRuntime.freeMemory

When the free memory hits zero, Java will double the heap size (up to the

maximum setting).

If you choose to run without Java, you will remove the overhead of the

middle man, but you will also lose some MATLAB functionality (mostly

graphics and the Editor). You will still have most of the computational

power though.

Without J***A, memory management will come directly from the OS, and a

CLEAR operation will result in memory being freed back to the OS.

21)如何在Matlab中添加新的工具箱?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21,BigGreen/MathTools #

如果是Matlab安装光盘上的工具箱,重新执行安装程序,选中即可。

如果是单独下载的工具箱,一般情况下仅需要把新的工具箱解压到某

个目录,然后用addpath(对于多个目录的使用genpath())或者pathtool添

加工具箱的路径,然后用which newtoolbox_command.m来检验是否可

以访问。如果能够显示新设置的路径,则表明该工具箱可以使用了。

具体请看工具箱自己代的README文件。

22)如何读写Matlab的.mat文件?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21,BigGreen/MathTools #

文件结构参见:

http://www.mathworks.de/access/helpdesk/help/pdf_doc/matlab/matfile_f

ormat.pdf

http://www.mathworks.com/support/solutions/data/8757.shtml

ftp://ftp.mathworks.com/pub/tech-support/solutions/s8757/readmemat.txt

建议使用matlab自己提供的函数来读写简单安全,或者参考:

http://engineering.dartmouth.edu/~fangq/MATH/download/source/mat_file

.txt

来自matlab的c math library

23)如何得到contour线上的坐标点?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21,BigGreen/MathTools #

lcount=5;

[c,h]=contour(peaks,lcount);

x=get(h,'xdata');

y=get(h,'ydata');

这里得到的x和y都是cell数组,用x{1}/y{1}来得到每条线上的坐标对,

注意,每条线的最后一个数据是NaN

24)如何将Matlab绘制的三维网格图帖到word里?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21,BigGreen/MathTools #

如果需要位图,好处是所见即所得,坏处是图像精度差,不能放缩:

1.用拷屏 Alt+PrintScreen

2.在图形窗口菜单Edit\Copy Options….\选择Bitmap,可以选择透

明背景,然后Edit\Copy Figure

如果需要拷贝矢量图:

在图形窗口菜单Edit\Copy Options….\选择Metafile,然后

Edit\Copy Figure,在Word中粘贴

经常地,按照Metafile方式粘贴的图片曲线会出现锯齿,最好的方式是

使用eps文件:

1.将需要拷贝的图作为当前窗口

2.再转换到matlab命令窗口,print -deps filename.eps

3.-deps还可以用depsc,deps2,depsc2

4.在word中插入图片,选中该eps,如果是word 2000以前版本

,不会显示图片内容,但可以打印,word XP即可显示,又可打印。

5.如果不满意,可以在word中双击编辑,如果安装有Adobe

Illustrator等矢量图像编辑软件,也可以进行编辑。

25)请问可以查看Matlab中函数的源代码吗?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21,BigGreen/MathTools #

Matlab除了buildin函数和mex/dll文件看不到原码,其他如工具箱等都可

以直接看到代码,首先确认该文件安装在matlab中,即which

filename.m存在,然后可以edit filename.m

26)Matlab有没有求矩阵行数/列数/维数的函数?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21,BigGreen/MathTools #

ndims(A)返回A的维数

size(A)返回A各个维的最大元素个数

length(A)返回max(size(A))

[m,n]=size(A)如果A是二维数组,返回行数和列数

nnz(A)返回A中非0元素的个数

27)Matlab中如何中断运算?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21,BigGreen/MathTools #

在命令窗口按Ctrl+C,在UNIX/LINUX会立即中断运算,在Windows可

能由于操作系统的原因,有时会出现死机和等待的情况。

28)Matlab中有没有画圆或椭圆的函数?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21,BigGreen/MathTools #

没有,Matlab没有提供直接绘圆的图元函数,需要自己写代码,其实

就两句:

sita=0:pi/20:2*pi;

plot(r*cos(sita),r*sin(sita)); %半径为r的圆

plot(a*cos(sita+fi),b *sin(sita+fi)); %椭圆

如果是单位圆,可以使用rectangle('Curvature', [1 1])

29)Matlab下如何定义整形

:#修改:fhorse (马不停蹄),2002/6/21,SMTH/MathTools #

Matlab默认的矩阵数据结构都是双精度浮点型,即64位来表示一个数

字,大多数的函数和操作都定义在double数据结构,如果你需要

把double的数据转换为整形,然后再参与运算,需要使用

double(int32(x))或者floor/round/ceil等函数

如果为了节省内存,只进行赋值、打印等简单操作,可以参

见uint8/uint16/uint32命令的帮助

30)Matlab如何产生均匀分布的白噪声?

:#misc,2002/6/21,SMTH/MathTools #

help rand 均匀分布百噪声

help randn高斯分布百噪声

31)在Matlab中debug的时候能否跟踪变量的?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),2002/6/21,BigGreen/MathTools #

可以,如果使用medit,设置断点后可以用鼠标移到所看的变量上,显

示当前的值,或者在命令窗口打该变量名直接回车。如果在代码中实

现调试断点等功能,参

见dbstop,dbcont,dbstep,dbclear,dbtype,dbstack,dbup,dbdown,dbstatus,

dbquit

32)请问在Matlab中怎样输入特殊符号啊或者上标、下标?

:#FangQ(Qianqian.Fang@Dartmouth.Edu),southerner(笑着),2002/6/6,SMTH/MathTools#

matlab的text/title/xlabel/ylabel对象支持简单的TeX排版语法,如希腊字

母,上下标等例如

text(0.5,0.5,'\alpha^\beta_2');

33)Matlab中如何后台运行一个DOS程序?

:#FangQ(Qianqian.Fang@Dartmouth.Edu), 2002/6/4. BigGreen/en_Matlab#

这里是一个后台执行一个需要外部输入的DOS命令的例子,需要的输

入实事先都写在同目录下的input.txt文件中:

dos('myexe < input.txt &')

34)Matlab如何加载输入文件(批处理模式) ?

:#翻译自:comp.sys-soft.Matlab FAQ. BigGreen/en_Matlab#

PC上可以使用matlab /r参数来在matlab启动的时候直接加载运行m文件

,在UNIX上,使用

matlab < MyMFile > MyOutputFile

来外部执行MyMFile,

以上执行方式都可以通过脚本文件实现批处理

35)Matlab如何启动时执行规定的文件?

:#FangQ(Qianqian.Fang@Dartmouth.Edu), 2002/5/29.BigGreen/en_Matlab#

参见上一个问题的回答

36)如何在Matlab GUI中使用图形背景?

:#FangQ(Qianqian.Fang@Dartmouth.Edu), 2002/5/29.BigGreen/en_Matlab#

这是一个简单的例子:

[A,map]=imread('yourimg.gif');

imagesc(A)

colormap(map)

set(gca,'position',[0 0 1 1])

axis off

ax2=axes('position',[0.2,0.2,0.6,0.6]);

plot(rand(1,10),'parent',ax2);

set(ax2,'color','none')

37)大量数据点Matlab绘图为什么很慢?

:#FangQ(Qianqian.Fang@Dartmouth.Edu), 2002/6/22.BigGreen/en_Matlab#

1.首先看能否用已有函数对整个矩阵绘图,比

如mesh/plot3/trimesh等

2.如果必须一点一点/或者一条线一条线的添加,最好作如下

设置:

doublebuffer=on

erasemode=none

backingstore=off

renderer=opengl

以及参考MathWorks对于高速绘图的tips:

http://www.mathworks.com/support/tech-notes/v5/1200/1203.shtml,

38)Matlab中如何求解广义积分?即积分限到有无穷的或者有歧

异点的积分(瑕积分)?

:#FangQ(Qianqian.Fang@Dartmouth.Edu), 2002/6/22. BigGreen/en_Matlab#

Matlab的quad/quad8只能作定积分,广义积分需要自己来写程序逼近,

流程大概如下:

1.设定收敛限epsi

2.把为inf/-inf或者歧义点的积分限设置为一个初始值,k=1

3.计算定积分Q(k)

4.然后朝着inf/-inf或者歧义点移动一个步长,然后计算定积分

Q(k+1)

5.判断(abs(Q(k+1)-Q(k))

QuasiMonteCarlo或者Oscillatory]

39)为什么我的Matlab程序这么慢?

:#FangQ(Qianqian.Fang@Dartmouth.Edu), 2002/6/22. BigGreen/en_Matlab#

我们工学院的收发室的门上贴着一张小纸条,写的是

"Our policy is always blaming the computer"

大多数的人在遇到问题的时候,总是责备计算机如何如何,别人如何

如何,其实,最最主要的因素是在于自己。

一个程序运行快慢,有很多因素决定,最主要的是算法,简炼而优美

的的数学公式胜过100遍的优化。能从算法上改进,才能比别人有根

本的优势。计算机也很重要,以前我总把自己用的PC看成万能的加

以崇拜,对UNIX嗤之以鼻,结果当自己真正开始算起来,才知道差

别有多大。搞大型数值计算的,没有好的工作站或者并行系统,就输

在了起跑线上了。然后是程序的优化,看看变量是否占用太多内存,

看看是否有功能重复的模块或者计算,经常的是用牺牲内存来换取速

度,具体取舍,具体需要来决定。用profile看看哪些语句占用时间最

多,然后把核心部分进行优化。

如果是使用Matlab,使用vectorization和矩阵整体操作的代码要比大量

的for循环快很多,eval/inline函数如果出现在核心循环,也会让速度下

降几时倍的。

40).Matlab中如何作非线性回归?

:#FangQ(Qianqian.Fang@Dartmouth.Edu), 2002/6/22. BigGreen/en_Matlab#

请参考

http://www.mathworks.com/support/solutions/data/10652.shtml

matlab默认只提供了多项式拟合的函数polyfit,对于其他稍微简单

一点的拟合,如标准的指数、对数、高阶多项式拟合,都有解析公式,参见:

http://mathworld.wolfram.com/LeastSquaresFitting.html

对于更加复杂的非线性函数,建议使用Mathematica或者DataFit

Mathematica中提供了Fit[],以及

<< Statistics`NonlinearFit`

NonlinearFit[],NonlinearRegress[]

可以拟合任意复杂的表达式。

DataFit可以自定义拟合模型,适用于复杂系统的拟合。

 

 

Vc++下利用Matlab工具箱进行数字信号处理

 

Matlab的信号处理工具箱是信号算法文件的集合,它处理的基本对象是信号与系统,信号处理工具箱位于目录、Toolbox\Signal下,利用工具箱中的文件可以实现信号的变换、滤波、谱估计、滤波器设计等。在其它的环境如Vc下如果能调用Matlab工具箱中的文件,会大大地加快一些算法的实现,同时其可靠性也很高。

利用Matlab引擎

Matlab引擎采用客户和服务器计算方式,在运用中,Vc的C语言或C++语言的程序作为前端客户机,它向Matlab引擎传递命令和数据信息,并从Matlab引擎接收数据信息,它提供了下列几个函数: engOpen, engGetArray, engPutArray, engEvaString,

engOutputBuffer ,engClose与客户机进行交互。

下面例程是在Vc下建一个基于对话框的应用程序,在对话框中设置一个Button控件OnMatlabEngine.,在对话框 .cpp文件中加入”engine.h” 和“math.h” 头文件,下面给出部分程序清单。

Void CtestmatlabDlg::OnMatlabEngine(){

Engine *ep;

mxArray* T=NULL,*result=NULL,*mFs=NULL,*mnfft= NULL;

double datax[1024];

char buffer[1024];

for(int j=0;j<1024;j++)//注:如通过采集卡采集数据可将采集的数据放在datax[]数组中,此循环就不需要

{

double samt=(double)(1.0/1024);

datax[j]=sin(2.0*63.0*samt*3.1415926+1.15*3.1415926);

}

double *pPxx,*pFxx;

if(!(ep=engOpen(" \0"))){//打开Matlab引擎,建立与本地Matlab的连接

fprintf(stderr,"\n Can't start MATLAB engine\n");

exit(-1);

}

double Fs[1]={1024};//因为Matlab所有参与运算的参数都是矩阵的形式,因而下列几行将参数转变

double nfft[1]={1024};//成Matlab可接受的矩阵形式。

T=mxCreateDoubleMatrix(1,1024,mxREAL);

mnfft=mxCreateDoubleMatrix(1,1,mxREAL);

mFs=mxCreateDoubleMatrix(1,1,mxREAL);

mxSetName(T,"T");

mxSetName(mnfft,"mnfft");

mxSetName(mFs,"mFs");

memcpy((char*)mxGetPr(T),(char*)datax, 1024*sizeof(double));

memcpy((char*)mxGetPr(mnfft),(char*)nfft, sizeof(double));

memcpy((char*)mxGetPr(mFs),(char*)Fs,1*sizeof(double));

engPutArray(ep,T); //将转化的参数放入引擎中,此时可在Matlab command窗口下查看此参数

engPutArray(ep,mnfft);

engPutArray(ep,mFs);

engEvalString(ep,"[pxx,fo]=psd(T,mnfft,mFs);"); //利用引擎执行工具箱中文件

engOutputBuffer(ep,buffer,512); //如只想看显示图形,可将返回参数去掉,psd无返回参数缺省情况下会自动画图形

result=engGetArray(ep,"pxx");//取出引擎中的数据放在所指的区域中供后续处理

pPxx=mxGetPr(result);

result=engGetArray(ep,"fo");

pFxx=mxGetPr(result);

engEvalString(ep,"plot(fo,10*log10(pxx));");//利用引擎画图

engEvalString(ep,"title('功率谱分析');");

engEvalString(ep,"xlabel('Hz');");

engEvalString(ep,"ylable('db');");

mxDestroyArray(T); //释放内存

mxDestroyArray(mFs);

mxDestroyArray(mnfft);

mxDestroyArray(result);

engEvalString(ep,"close;");

engClose(ep);

}

上述程序在Vc下编译需要将 libeng.dll和libmx.dll两个动态库利用以下的命令:

lib/def:<自己的Matlab的安装路径,下同>e:\ Matlab\extern\include\*.def /machine:ix86 /out:*.lib来生成程序所需的静态连接库libeng.lib和libmx.lib,将libeng.lib和libmx.lib所在的目录加入Vc++ project/link/object/library modules下即可。

利用Matlab自身的编译器调用工具箱中的函数

 

Matlab的编译器可将Matlab的M文件转换为为C或C++的源代码以产生完全脱离Matlab运行环境的独立的运用程序,但Matlab本身的资料说明编译器如用来建立独立的运用程序,不能调用Matlab工具箱中的函数,这非常不利于搞一些特殊的算法。本人研究了一段时间发现,工具箱中的函数既然是M文件就一定可以用编译器来编译,以提供如Vc的调用函数,但是编译器只能编译一个独立的M文件,即这个 M文件不依赖于其他的M文件。如果M文件中又调用了其他的M文件,可将被调用的M文件拷贝到调用M文件的相应位置,作适当的改动就可以用于编译器编译。编译器不支持图形函数,所以M文件中如有图形函数需注释掉。

当Matlab的编译器mcc加入适当的参数-e(mcc –e *.*)或-p(mcc –p *.*)就可生成将输入的M文件转换为适用于特定运用的C或C++源代码。这样如果要在Vc下编译通过,还需连入以下几个库libmmfile.dll, libmatlb.dll, libmcc.dll, libmat.dll. libmx.dll. mibut.dll 以及Matlab C MATH库,建议采用前述的方法将动态连接改为静态连接。对于C/C++编译环境的设置,在Matlab command窗口下运行mex –setup 然后依提示操作,而对于C/C++连接环境的设置,运行mbuild –setup依提示操作即可。

下面给出利用编译器将Matlab工具箱中psd.m文件生成可供Vc调用的函数。

将psd.m文件拷贝一份至Matlab\bin目录下,改写相应调用的M文件如nargchk.m, hanning.m等。为生成的代码简洁,对于采集数据处理输入参数很明了的情况下可作大量的删减,最终使psd.m成为一个不依赖于其他M文件的独立的M文件,注意千万注释掉作图代码,最终改成如下形式,限于篇幅给出关键的几步:

function [Pxx,f]=psd(Fs,nfft,noverlap,x)

window=o,5*(1-cos(2*pi*(1:nfft)’/(nffft+1)));//hanning 窗

dflag=’none’;

window=window(;)

………………………………….

以上只要稍懂Matlab语言和信号处理知识就可完成这项工作。

假设上述代码重新存为testwin.m,在Matlab command 窗口下设置好环境参数运行mcc –e testwin,则可在Matlab\bin下生成testwin.c ,如运行mcc –p testwin 则生成testwin.cpp.

Vc下建立一个基于对话框的文件,然后在对话框里加一个Button控件OnButtonPsd

将上述生成的.c文件的头文件加入到工程的.cpp中,且将#ifdef_cplusplus

extern “c”{

#end if

c代码声明加入Vc的包含文件和生成的.C的包含文件之间

将#ifdef_cplusplus

}

#end if加入.cpp文件未尾

为了简洁且便于处理将生成的c函数稍改动,给出部分代码如下:

void CTestpsdwinDlg::OnButtonPsd(){

mxArray* x_rhs_;//指向采集数据存放区

Fs=23510;//数据采集的频率 nfft=1024;//1024点的fft

double datax[1024]//采集的数据

x_rhs_mxCreateDoubleMatrix(1,1024,mxReal);

memcpy(mxGetPr(x_rhs_),datax,1024*sizeof(double));

noverlap=512;

……………….

……………….

mccCopy(&Pxx,&Spec);

mccCopy(&f,&frevgg_vector);

for(int j=0;j<(int)(nfft/2+1);j++)

{

datap[j]=mccGetRealVectorElement(&Pxx, (j+1));//功率谱密度存于datap[]数组

dataf[j]=mccGetRealVectorElement(&f, (j+1));//相应频率存于数组dataf[]中

}

mccFreeMatrix(&Pxx);

……………….

SendMessageBox(WM_PAINT,0,0);//利用Vc下的图形函数画图

Return;

}

 

如上生成的程序可读性不太好,而生成的c++代码则可读性较好,但千万注意只能用 Matlab的MATH库,不可用c++的MATH库,否则编译会出错,限于篇幅在此不述。

3)利用Matcom调用工具箱中的函数

Matcom编译M文件,先将M文件按照与Matcom的cpp库的对应关系翻译为cpp源代码,然后用对应版本的c编译器将cpp文件编译成相应的exe或dll文件,所以第一次运行要指定c编译器的路径,否则无法编译,指定好的编译信息就写在Matcom\bin\matcom.ini文件中,不过这一步按装matcom时,它自动寻找编译器并将其写入matcom.ini文件中,matcom4.5版中使用TeeChart3.0 OCX控件,因而它支持图形操作。

我们依然用上述的testwin.m文件,不要将图形函数注释掉,利用Mideva来生成可被Vc调用的信号处理程序。

运行Mideva在主界面上直打开M文件,在菜单中选择compile to dll,输入testwin..在Matcom debug目录下可以找到这样的几个文件,testwin.c ,testwin.h,testwin.cpp,testwin.lib,testwin.dll,testwin.exp等。

将上述testwin.cpp和testwin.h加入工程中,project/add to project/files并且在相应的文件中加入”stdafx.h”

加连接库:Tools\option\directory\ ,选include选项,加入e:\matcom45\lib (包含matcom.h)

library选项,加入e:\matcom45\lib

4) project\add to project\files 文件类型选项选(.lib)将e:\matcom45\lib\v4501.lib加入工程中编译运行。相应代码如下:

void CtestmatcomDlg::OnpsdButton(){

double datap[512],dataf[512];

initM(MATCOM_VERSION);//初始化matcom库

Mm Fs,nfft,noverlap;//创建矩阵

Mm x=zeros(1,1024);

Fs=1024;nfft=1024;noverlap=128;

dMm(Pxx_o);dMm(f_o);//创建并命名矩阵

datax[];//数据采集的数据存于此数组中

for(int i=1;i<=1024;i++)

{

x.r(1,i)=datax[i+1];//给x阵赋值

}

testwin(Fs,nfft,noverlap,x,i_o,Pxx,f_o);//matcom生成的函数

for(i=0;i<513;i++){//取出功率谱密度分析结果

dataf[i]=f_o.r(i+1,1);

datap[i]=Pxx_o.r(i+1,1);}

exitM();

return;

}

可见利用Matcom进行M文件转换非常的容易,生成的代码可读性很好,以上的转换同时生成了可供Vc调用的动态连接库,其使用和一般的动态库一样使用。同时需指明Matcom不仅可转换独立的不依赖于其它M文件的M文件,同时可转换调用其它M文件的M文件嵌套。条件是这此M文件在同一个目录下面,如前所述的psd.m可直接用上述方法转换,生成了多个重载形式的psd函数

结论:利用Mtlab引擎调用工具箱中的函数可节省大量的系统资源,应用程序整体性能较好,但不可脱离Matlab 的环境运行。用Matlab编译器进行工具箱函数的调用,须转换相应的M文件使其成为独立的M文件,且不支持图形函数,转换的代码可读性不太好。用Matcom 进行转换非常方便,生成的代码可读性很好,支持图形函数,且代码执行的速度比不转换平均要快1.5倍以上。以上程序在Vc++ 6.0,Matlab5.2,Matcom4.5中调试通过,以上方法在工程实践中已得到很好的运用。

摘要:本文详述了在Vc环境下如何利用Matlab工具箱进行数字信号处理,全文以Matlab工具箱中功率谱密度分析函数为例,介绍了通过Matlab自带的引擎、Matlab自身的编译器以及利用MathTools公司的Matcom进行对工具箱函数的调用。

2019-04-19 11:35:48 chenxi1900 阅读数 921

图像格式转换

1 、tensor to PIL image

from torchvision import transforms 
count = 0
def TensortoImg(img):
      global count
      img = img.cpu()
      img = transforms.ToPILImage()(img[0])
      # img.show()
      img.save('count.jpg')
      count += 1
2016-03-10 08:16:02 icamera0 阅读数 127849

在数字图像处理中,针对不同的图像格式有其特定的处理算法。所以,在做图像处理之前,我们需要考虑清楚自己要基于哪种格式的图像进行算法设计及其实现。本文基于这个需求,使用python中的图像处理库PIL来实现不同图像格式的转换。

对于彩色图像,不管其图像格式是PNG,还是BMP,或者JPG,在PIL中,使用Image模块的open()函数打开后,返回的图像对象的模式都是“RGB”。而对于灰度图像,不管其图像格式是PNG,还是BMP,或者JPG,打开后,其模式为“L”。

通过之前的博客对Image模块的介绍,对于PNGBMPJPG彩色图像格式之间的互相转换都可以通过Image模块的open()save()函数来完成。具体说就是,在打开这些图像时,PIL会将它们解码为三通道的“RGB”图像。用户可以基于这个“RGB”图像,对其进行处理。处理完毕,使用函数save(),可以将处理结果保存成PNGBMPJPG中任何格式。这样也就完成了几种格式之间的转换。同理,其他格式的彩色图像也可以通过这种方式完成转换。当然,对于不同格式的灰度图像,也可通过类似途径完成,只是PIL解码后是模式为“L”的图像。

这里,我想详细介绍一下Image模块的convert()函数,用于不同模式图像之间的转换。

Convert()函数有三种形式的定义,它们定义形式如下:

im.convert(mode) image

im.convert(“P”, **options) image

im.convert(mode, matrix) image

使用不同的参数,将当前的图像转换为新的模式,并产生新的图像作为返回值。

通过博客“Python图像处理库PIL的基本概念介绍”,我们知道PIL中有九种不同模式。分别为1LPRGBRGBACMYKYCbCrIF

本文我采用的示例图像是图像处理中经典的lena照片。分辨率为512x512lena图片如下:

一、模式“RGB”转换为其他不同模式

1、 模式“1

模式“1”为二值图像,非黑即白。但是它每个像素用8bit表示,0表示黑,255表示白。下面我们将lena图像转换为“1”图像。

例子:

>>>from PIL import Image

>>> lena =Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")

>>> lena.mode

'RGB'

>>> lena.getpixel((0,0))

(197, 111, 78)

>>> lena_1 = lena.convert("1")

>>> lena_1.mode

'1'

>>> lena_1.size

(512, 512)

>>>lena_1.getpixel((0,0))

255

>>> lena_1.getpixel((10,10))

255

>>>lena_1.getpixel((10,120))

0

>>>lena_1.getpixel((130,120))

255

 

图像lena_1的模式为“1”,分辨率为512x512,如下:

2、 模式“L

模式“L”为灰色图像,它的每个像素用8bit表示,0表示黑,255表示白,其他数字表示不同的灰度。在PIL中,从模式“RGB”转换为“L”模式是按照下面的公式转换的:

L = R * 299/1000 + G * 587/1000+ B * 114/1000

下面我们将lena图像转换为“L”图像。

例子:

>>> from PIL importImage

>>> lena = Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")

>>> lena.mode

'RGB'

>>> lena.getpixel((0,0))

(197, 111, 78)

>>> lena_L =lena.convert("L")

>>> lena_L.mode

'L'

>>> lena_L.size

(512, 512)

>>>lena.getpixel((0,0))

(197, 111, 78)

>>>lena_L.getpixel((0,0))

132

对于第一个像素点,原始图像lena(197, 111, 78),其转换为灰色值为:

197 *299/1000 + 111 * 587/1000 + 78 * 114/1000 = 132.952PIL中只取了整数部分,即为132

转换后的图像lena_L如下:

3、 模式“P

模式“P”为8位彩色图像,它的每个像素用8bit表示,其对应的彩色值是按照调色板查询出来的。

下面我们使用默认的调色板将lena图像转换为“P”图像。

例子:

>>> from PIL importImage

>>> lena = Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")

>>> lena.mode

'RGB'

>>> lena.getpixel((0,0))

(197, 111, 78)

>>> lena_P =lena.convert("P")

>>> lena_P.mode

'P'

>>>lena_P.getpixel((0,0))

62

 

转换后的图像lena_P如下:

4、 模式“RGBA

模式“RGBA”为32位彩色图像,它的每个像素用32bit表示,其中24bit表示红色、绿色和蓝色三个通道,另外8bit表示alpha通道,即透明通道。

下面我们将模式为“RGB”的lena图像转换为“RGBA”图像。

例子: 

                                                                                                                              

>>> from PIL import Image

>>>lena = Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")

>>>lena.mode

'RGB'

>>>lena.getpixel((0,0))

(197,111, 78)

>>>lena_rgba = lena.convert("RGBA")

>>>lena_rgba.mode

'RGBA'

>>>lena_rgba.getpixel((0,0))

(197,111, 78, 255)

>>>lena_rgba.getpixel((0,1))

(196,110, 77, 255)

>>>lena.getpixel((0,0))

(197,111, 78)

>>>lena.getpixel((0,1))

(196,110, 77)

 

从实例中可以看到,使用当前这个方式将“RGB”图像转为“RGBA”图像时,alpha通道全部设置为255,即完全不透明。

转换后的图像lena_rgba如下:

5、 模式“CMYK

模式“CMYK”为32位彩色图像,它的每个像素用32bit表示。模式CMYK”就是印刷四分色模式,它是彩色印刷时采用的一种套色模式,利用色料的三原色混色原理,加上黑色油墨,共计四种颜色混合叠加,形成所谓“全彩印刷”。

四种标准颜色是:CCyan = 青色,又称为‘天蓝色’或是‘湛蓝’MMagenta = 品红色,又称为‘洋红色’;YYellow = 黄色;KKey Plate(blacK) = 定位套版色(黑色)。

下面我们将模式为“RGB”的lena图像转换为“CMYK”图像。

例子:

>>>from PIL import Image

>>> lena =Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")

>>> lena_cmyk =lena.convert("CMYK")

>>> lena_cmyk.mode

'CMYK'

>>>lena_cmyk.getpixel((0,0))

(58, 144, 177, 0)

>>> lena_cmyk.getpixel((0,1))

(59, 145, 178, 0)

>>>lena.getpixel((0,0))

(197, 111, 78)

>>>lena.getpixel((0,1))

(196, 110, 77)

 

从实例中可以得知PIL中“RGB”转换为“CMYK”的公式如下:

C = 255 - R
M = 255 - G
Y = 255 - B
K = 0

由于该转换公式比较简单,转换后的图像颜色有些失真。

转换后的图像lena_cmyk如下:

6、 模式“YCbCr

模式“YCbCr”为24位彩色图像,它的每个像素用24bit表示。YCbCr其中Y是指亮度分量,Cb指蓝色色度分量,而Cr指红色色度分量。人的肉眼对视频的Y分量更敏感,因此在通过对色度分量进行子采样来减少色度分量后,肉眼将察觉不到的图像质量的变化。

模式“RGB”转换为“YCbCr”的公式如下:

Y= 0.257*R+0.504*G+0.098*B+16
Cb = -0.148*R-0.291*G+0.439*B+128
Cr = 0.439*R-0.368*G-0.071*B+128

下面我们将模式为“RGB”的lena图像转换为“YCbCr”图像。

例子:

>>>from PIL import Image

>>> lena =Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")

>>> lena_ycbcr =lena.convert("YCbCr")

>>>lena_ycbcr.mode

'YCbCr'

>>>lena_ycbcr.getpixel((0,0))

(132, 97, 173)

>>>lena.getpixel((0,0))

(197, 111, 78)

 

按照公式,Y = 0.257*197+0.564*111+0.098*78+16= 136.877

Cb= -0.148*197-0.291*111+0.439*78+128= 100.785
Cr = 0.439*197-0.368*111-0.071*78+128 = 168.097

由此可见,PIL中并非按照这个公式进行“RGB”到“YCbCr”的转换。

转换后的图像lena_ycbcr如下:

7、 模式“I

模式“I”为32位整型灰色图像,它的每个像素用32bit表示,0表示黑,255表示白,(0,255)之间的数字表示不同的灰度。在PIL中,从模式“RGB”转换为“I”模式是按照下面的公式转换的:

I = R * 299/1000 + G * 587/1000 + B * 114/1000

下面我们将模式为“RGB”的lena图像转换为“I”图像。

例子:

>>> from PIL import Image

>>>lena = Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")

>>>lena.getpixel((0,0))

(197,111, 78)

>>>lena.getpixel((0,1))

(196,110, 77)

>>> lena_I =lena.convert("I")

>>> lena_I.mode

'I'

>>>lena_I.getpixel((0,0))

132

>>>lena_I.getpixel((0,1))

131

>>> lena_L =lena.convert("L")

>>>lena_L.getpixel((0,0))

132

>>>lena_L.getpixel((0,1))

131

 

从实验的结果看,模式“I”与模式“L”的结果是完全一样,只是模式“L”的像素是8bit,而模式“I”的像素是32bit

8、 模式“F

模式“F”为32位浮点灰色图像,它的每个像素用32bit表示,0表示黑,255表示白,(0,255)之间的数字表示不同的灰度。在PIL中,从模式“RGB”转换为“F”模式是按照下面的公式转换的:

F = R * 299/1000+ G * 587/1000 + B * 114/1000

下面我们将模式为“RGB”的lena图像转换为“F”图像。

例子:

>>>from PIL import Image

>>> lena =Image.open("D:\\Code\\Python\\test\\img\\lena.jpg")

>>>lena.getpixel((0,0))

(197, 111, 78)

>>>lena.getpixel((0,1))

(196, 110, 77)

>>> lena_F =lena.convert("F")

>>> lena_F.mode

'F'

>>>lena_F.getpixel((0,0))

132.95199584960938

>>>lena_F.getpixel((0,1))

131.95199584960938

 

模式“F”与模式“L”的转换公式是一样的,都是RGB转换为灰色值的公式,但模式“F”会保留小数部分,如实验中的数据。

(未完待续)

2017-11-14 21:14:26 akadiao 阅读数 7399

tensorflow图像处理
一张RGB格式的彩色图像可以看成是一个三维矩阵,矩阵中的每一个数代表图像不同的位置上不同的颜色的亮度.但是图像存储时并不是直接存储这些三维矩阵,而是要先对其进行压缩编码再存储.因此读取图像的过程其实是先读取其压缩编码后的结果,然后将其解码的过程.

读取图像&转换格式

#!/usr/bin/python
# coding:utf-8

import matplotlib.pyplot as plt
import tensorflow as tf
# 读取图像数据
img = tf.gfile.FastGFile('daibola.jpg').read()

with tf.Session() as sess:
    # 用ipeg格式将图像解码得到三维矩阵(png格式用decode_png)
    # 解码后得到结果为张量
    img_data = tf.image.decode_jpeg(img)
    # 打印出得到的三维矩阵
    print img_data.eval()
    # 使用pyplot可视化得到的图像
    plt.imshow(img_data.eval())
    plt.show()

    #转换格式   
    # 转换图像的数据类型
    img_data = tf.image.convert_image_dtype(img_data, dtype=tf.uint8)
    # 将图像的三维矩阵重新按照png格式存入文件
    encoded_image = tf.image.encode_png(img_data)
    # 得到图像的png格式
    with tf.gfile.GFile('model/model.png', 'wb') as f:
        f.write(encoded_image.eval())

输出:

[[[ 19  18  16]
  [ 20  19  17]
  [ 22  21  19]
  ..., 
  [ 22  21  19]
  [ 22  21  19]
  [ 22  21  19]]

 [[  8   7   5]
  [ 10   9   7]
  [ 11  10   8]
  ..., 
  [  8   7   5]
  [  9   8   6]
  [ 10   9   7]]

 [[ 14  13  11]
  [ 15  14  12]
  [ 17  16  14]
  ..., 
  [ 13  12  10]
  [ 13  12  10]
  [ 15  14  12]]

 ..., 
 [[109  88  57]
  [109  88  57]
  [109  88  57]
  ..., 
  [ 35  28  18]
  [ 35  28  18]
  [ 34  27  17]]

 [[109  88  57]
  [109  88  57]
  [109  88  57]
  ..., 
  [ 34  27  17]
  [ 34  27  17]
  [ 34  27  17]]

 [[107  88  56]
  [107  88  56]
  [107  88  56]
  ..., 
  [ 32  28  17]
  [ 33  29  18]
  [ 33  29  18]]]

这里写图片描述