源自http://blog.csdn.net/tlovet1314/article/category/718759
第一章Windows位图和调色板
1.1 位图和调色板的概念
1. 真彩色图: 它的颜色数高达256×256×256种,也就是说包含我们上述提到的R、G、B颜色表示方法中所有的颜色。真彩色图是说它具有显示所有颜色的能力,即最多可以包含所有的颜色。
1.2 bmp文件格式
(WORD为无符号16位整数,DWORD为无符号32位整数,LONG为32长整型)
1. bmp文件大体上分成四个部分:
1)位图文件头BITMAPFILEHEADER,共14个字节。
2)位图信息头BITMAPINFOHEADER,共40个字节。
3)调色板Palette
4)实际的位图数据ImageDate
调色板实际上是一个数组,共有biClrUsed个元素(如果该值为零,则有 个元素)。数组中每个元素的类型是一个RGBQUAD结构,占4个字节。(红色,绿色与蓝色的排序与一般图像文件的颜色数据排序恰好相反~)
对于用到调色板的位图,图象数据就是该象素颜在调色板中的索引值。对于真彩色图,图象数据就是实际的R、G、B值
2. 要注意两点:
1) 每一行的字节数必须是4的整倍数,如果不是,则需要补齐。
2) 一般来说,BMP文件的数据从下到上,从左到右的。
1.3 显示一个bmp文件的C程序
一,loadBmpFile函数实现过程:
1. 打开文件到HFILE结构变量中。
2. 从HFILE变量中读取BITMPFILEHEADER和BITMAPINFOHEADER两个结构变量。
3. 计算图像行字节数和图像总字节数。
4. 计算实际使用到的颜色个数并验证结果.
5. 填写bf.bfsize;
6. 分配全局内存空间,大小为(bitmapinfoheader+palette+实际图像)返回一个句柄。
7. LPBITMAPINFOHEADER指向分配的全局内存空间。
8. 文件指针重新定位到BITMAPINFOHEADER开始处并将内容读入LPBITMAPINFOHEADER类型指针中。关闭文件。_hread和_lread的区别。
9. NumColors不为零时,说明用到了调色板。为逻辑调色板分配局部内存,大小为逻辑调色板结构长度加NumColors个PALETTENTRY。
10.LOGPALETTE类型指针pPal指向该内存区,填写逻辑调色板结构的头。lpRGB指向的是调色板开始的位置,填写pPal->palPalEntry的每一项。
11.产生逻辑调色板全局变量hPalette,解锁并释放局部内存。
12.获得设备上下文句柄。
13.如果产生了逻辑调色板,将新的逻辑调色板选入DC,将旧的逻辑调色板句柄保存在hPrevPalette中。
14.产生位图句柄。使用完现在的调色板,就要把原来的调色板还原至DC中。
15.释放设备上下文,解锁内存区。
二,响应WM_PAINT消息:
1. 获得屏幕设备上下文BeginPaint和GetDC的区别。
2. 建立一个内存设备上下文。当有调色板,将调色板选入屏幕设备上下文和内存设备上下文。
3. 将位图选入内存设备上下文,显示位图,释放内存设备上下文,释放屏幕设备上下文。
注意:1)要2个DC的原因是,在绘制位图时要将源(内存)设备上下文的内容复制到目的(屏幕)设备上下文中。
书提供的代码运行都有问题,经过修改,错误是没了,不过就是图片显示不出来!而且对它的代码还有一些不太明白,比如系统如何发送WM_LOADBITMAP这个消息的呢?
终于解决了!!
答:看书上提供的代码时没有注意到有一个.rc为后缀的资源文件,里面定义了一个menu,menu里面有一个子控件open,它和WM_LOADBITMAP关联。以前从来没想过去手动编辑资源文件,要不是昨天开始尝试使用dos下编译c++文件,怎么也没想要打开这个文件看看。看来放一放还是对了,忍了这么久终于解放了!稍后写一篇关于如果VC资源文件结构的文章,对以后学习有帮助。
第二章图象的几何变换
2.1 平移
初始坐标为(x0,y0)的点经过平移(tx,ty)(以向右,向下为正方向)后,坐标变为(x1,y1)。这两点之间的关系是x1=x0+tx ,y1=y0+ty。
其矩阵表示为:
其逆矩阵表示为:
逆运算在计算平移后的RGB值有帮助。通过结果点,利用逆运算计算原点RGB值。
1. 灰度图是指只含亮度信息,不含色彩信息的图象,就象我们平时看到的黑白照片:亮度由暗到明,变化是连续的。可以通过RGB各项都相同的256色调色板来表示,例如:(0,0,0)是全黑色,(255,255,255)是全白色,中间的是灰色。
2. YUV——Y分量的物理含义就是亮度,U和V分量代表了色差信号。这种表示方法有两个优点:1)Y分量包含所有亮度信息,只用Y分量就能完全能够表示出一幅灰度图来。当同时考虑U,V分量时,就能够表示出彩色信息来。可以方便的实现灰度和彩色图之间切换。2)在对图像压缩时,可以着重考虑Y分量的值。
平移的算法实现:
1. 创建对话框,获取偏移量值:xOffset,yOffset
2. 计算新图像所需的缓冲区大小并分配局部内存空间。
3. 定义两个指针lpImgData和lpTempImgData分别指向原和新文件的内存。
4. 初始化lpTempImgData指向的缓冲区。
5. 计算平移前和平移后最左上角和最右下角的坐标,从而得出平移后的图像高。
6. 找出平移前和平移后图像数据最左边的地址(见下面的代码提示,这个表达式想蛮久才想通的,为了怕以后忘记,还自己做了个flash,不错!学了flash第一次做出自己东西的感觉真好!),按行进行复制。
lpPtr=(char*)lpImgData+(BufSize-LineBytes-(i+SrcY0)*LineBytes)+SrcX0;
lpTempPtr=(char*)lpTempImgData+(BufSize-LineBytes-(i+DstY0)*LineBytes)+DstX0;
1. 释放原来的位图句柄
2. 产生新的位图,将平移后的图象存成文件,释放资源和内存。
注:bmp图像数据存储顺序是从下至上,从左至右。
1.2 旋转
1.定义 旋转通常是以中心为原点进行,这里讨论旋转后图像扩大的情况。将一个点顺时针旋转a角后的坐标变换公式,如图2.10所示,r为该点到原点的距离,在旋转过程中,r保持不变;b为r与x轴之间的夹角。
图2.10 旋转示意图
旋转前:x0=rcosb;y0=rsinb
旋转a角度后:
x1=rcos(b-a)=rcosbcosa+rsinbsina=x0cosa+y0sina;
y1=rsin(b-a)=rsinbcosa-rcosbsina=-x0sina+y0cosa
2. 坐标系转换:以左上角为原点坐标系 和以中心点为原点坐标系 之间的转换矩阵为:其中设图象的宽为w,高为h。
3. 变换步骤:
1)将坐标系o’变成o;
2)将该点顺时针旋转a角;
3)将坐标系o变回o’,这样,我们就得到了变换矩阵,是上面三个矩阵的级联。
逆变换为
1.3 镜象
镜象(mirror)分水平镜象和垂直镜象两种。设原图宽为w,高为h,变换后,图的宽和高不变。
水平镜象的变化矩阵为:
垂直镜象的变化矩阵为:
2.4 转置
转置(transpose)是指将x,y坐标对换,转置后图的宽高对换了。
2.5 缩放
假设放大因子为ratio,(为了避免新图过大或过小,我们在程序中限制0.25≤ratio≤4)。
第二章终于结束了,虽然没有代码实现,但看了书上的代码,都能看懂!希望快点能找到显示位图的代码错误,这样我才可以实现接下来的代码嘛!也怪自己,太要面子了,不会可以问咯!就是死要面子,不过这样也好,别人告诉我的,终究不如自己发现的。现在在看《深入浅出MFC》,讲机制原理性的比较多,要的就是这方面的。加油~ 誓要把那个错误揪出来... ...
第三章图象的平滑(去噪声)、锐化
3.1 平滑
1.定义: 平滑又叫去噪声或低通滤波。在灰度连续变化的图象中,如果出现了与相邻象素的灰度相差很大的点,比如说一片暗区中突然出现了一个亮点,这样的点就叫噪声。而平滑的目标就是消除噪声,使其能于邻近区域的灰度不会相差很大。
2.方法: 使用模板操作。例如:
(3.1)
将原图中的每一点的灰度和它周围八个点的灰度相加,然后除以9,作为新图中对应点的灰度。中间的黑点表示中心元素,即用哪个元素做为处理后的元素。
模板不允许移出边界,所以结果图象会比原图小。边界上无法进行模板操作的点,通常的做法是复制原图的灰度,不进行任何处理。
由于模板操作是非常耗时的操作,有时可以将二维模板转换成两个一维模板。例如:
(3.2)
典型的模板有两种:1)Box模板(公式3.1):虽然考虑了邻域点的作用,但并没有考虑各点位置的影响。2)高斯模板(公式3.2):它考虑了位置的影响。
3.2 中值滤波
1.定义: 也是典型的低通滤波。目的是保护图象边缘的同时去除噪声。所谓中值滤波,是指把以某点(x,y)为中心的小窗口内的所有象素的灰度按从大到小的顺序排列,将中间值作为(x,y)处的灰度值(若窗口中有偶数个象素,则取两个中间值的平均)。
2.几种典型图:
1)“step”:左边区域灰度值低,右边区域灰度值高,中间有一条明显的边界。
2)高斯噪声:图中有很多噪声点,而且是杂乱无章,随机分布的。
3)脉冲:中间的灰度要比两边高许多。
3.总结中值滤波的表现: 中值滤波容易去除孤立点,线的噪声同时保持图象的边缘;它能很好的去除二值噪声(“step”,脉冲),但对高斯噪声无能为力。要注意的是,当窗口内噪声点的个数大于窗口宽度的一半时,中值滤波的效果不好。
3.3 锐化
1.定义: 和平滑相反,属于高通滤波。锐化处理在增强图象边缘的同时增加了图象的噪声。
2.方法: 拉普拉斯模板(如下公式)。
因为图象中的边缘就是那些灰度发生跳变的区域,所以锐化模板在边缘检测中很有用。要注意的是,运算后如果出现了大于255或者小于0的点,称为溢出,溢出点的处理通常是截断,即大于255时,令其等于255;小于0时,取其绝对值。
第四章图象的半影调和抖动技术
1. 黑白二值图:只由黑点和白点组成,表现出灰色图象的效果。黑点越多,图像就暗点,反之,图像就亮点。
2. 半影调技术:由二值图象显示出灰度效果的方法。它的一个主要用途就是在只有二值输出的打印机上打印图象。主要的两种方法:图案法和抖动法。
4.1 图案法
1. 图案法是指灰度可以用一定比例的黑白点组成的区域表示,从而达到整体图象的灰度感。黑白点的位置选择称为图案化。
2. 分辨率,单位是dpi(dot per inch),即每英寸点数,点数越多,分辨率就越高,图象就越清晰。显示器的尺寸(英寸)是指对角线。
3. 像素点灰度的表示方法(图案):如果这16×16的方块中一个黑点也没有,就可以表示灰度256;有一个黑点,就表示灰度255;依次类推,当都是黑点时,表示灰度0。这样,16×16的方块可以表示257级灰度。
4. 图案的构成:有规则的图案和随机的图案。一般情况下,有规则的图案比随即图案能够避免点的丛集,但有时会导致图象中有明显的线条。
5. 标准图案:一个整数矩阵。例如要表示256级灰度,则其中的每个值从0到255。图象的实际灰度和阵列中的每个值比较,当该值大于等于灰度时,对应点打一黑点。
6. 设计标准图案的算法:(由Limb在1969年提出的)
先以一个2×2的矩阵开始:设M1= ,通过递归关系有Mn+1= ,其中Mn和Un均为2n×2n的方阵,Un的所有元素都是1。根据这个算法,可以得到M2= ,为16级灰度的标准图案。
M3(8×8阵)比较特殊,称为Bayer抖动表。M4是一个16×16的矩阵。
7. 在不改变原图的大小下,使用利用图案化技术:设原图是256级灰度,利用Bayer抖动表,做如下处理:
if (g[y][x]>>2) > bayer[y&7][x&7] then 打一白点 else 打一黑点
其中,x,y代表原图的象素坐标,g[y][x]代表该点灰度。首先将灰度右移两位,变成64级,然后将x,y做模8运算,找到Bayer表中的对应点,两者做比较,根据上面给出的判据做处理。模8运算使得原图分成了一个个8×8的小块,每个小块和8×8的Bayer表相对应。
4.2 抖动法
1. 规则抖动:如上面提到Bayer表算法。优点是算法简单;缺点是图案化有时很明显,这是因为取模运算虽然引入了随机成分,但还是有规律的。
2. Floyd-Steinberg算法:
假设灰度级别的范围从b(black)到w(white),中间值t为(b+w)/2,对应256级灰度,b=0,w=255,t=127.5。设原图中象素的灰度为g,误差值为e,则新图中对应象素的值用如下的方法得到:
if g > t then
打白点
e=g-w
else
打黑点
e=g-b
3/8 × e 加到右边的象素
3/8 × e 加到下边的象素
1/4 × e 加到右下方的象素
但在这个算法中,因为e有可能是负数,为了防止得到的值超出char能表示的范围,我们使用了一个int类型的缓冲区存储新值。
要注意的是,误差传播有时会引起流水效应,即误差不断向下,向右累加传播。解决的办法是:奇数行从左到右传播,偶数行从右到左传播。
4.3 将bmp文件转换为txt文件
1. 原理:首先将位图分成同样大小的小块,求出每一块灰度的平均值,然后和每个字符的灰度做比较,找出最接近的那个字符,来代表这一小块图象。
2. 字符灰度的确定方法:打开记事本(notepad),输入字符“1”,选定该字符,使其反色。按Alt+PrintScreen键拷贝窗口屏幕。打开画笔(paintbrush),粘贴;然后把图放到最大(×8),打开“查看”→“缩放” →“显示网格”菜单。每个字符的面积是8×16(宽×高),所以一个字符的灰度值可以用如下的公式计算(1-所占的黑点数/(8×16))×255。
在努力,就是向成功一点点迈进!加油~~~
第五章直方图修正和彩色变换
5.1 反色
1.定义: 反色(invert)就是形成底片效果。
2.用途: 当黑色区域占比较大区域时,可以利用反色,节省打印的墨。
3.做法:反色的实际含义是将R、G、B值反转。
1)真彩图。真彩图不带调色板,每个象素用3个字节,表示R、G、B三个分量。所以处理很简单,把反转后的R、G、B值写入新图即可。
2)带调色板的彩色图。只需要将调色板中的颜色反转,形成新调色板,而位图数据不用动,就能够实现反转。
3)灰度图,是一种特殊的伪彩色图,所以反转的处理和上面讲的一样。
注:二值图不一定是黑白图,其实在调色板中是黑色和蓝色两种,但通常情况下是黑白图。
5.2 彩色图转灰度图
1.定义:YUV的颜色表示方法,在这种表示方法中,Y分量的物理含义就是亮度,它含了灰度图的所有信息,只用Y分量就完全能够表示出一幅灰度图来。
我们利用上式,根据R、G、B的值求出Y值后,将R、G、B值都赋值成Y,就能表示出灰度图来,这就是彩色图转灰度图的原理。
2.做法:
1)真彩图。根据R、G、B的值求出Y值后,将R、G、B值都赋值成Y,写入新图即可。由于改成灰度图后,是必须带一个256色的调色板,并把图像中的内容改变为对调色板的索引值。
2)彩色图。我们只需要将调色板中的彩色变成灰度,形成新调色板,而位图数据不用动,就可以了。
5.3 真彩图转256色图
1.定义:真彩图能表示2^24种颜色,就是要从中挑选出256种颜色。
2.做法:
1)准备长度为4096的数组——用于存储4096种颜色的信息;
2)统计这4096种颜色在图中的使用频率。对图中的每一个象素,取R、G、B的最高四位,拼成一个12位的整数,该整数值对应的数组元素加1。
3)排除数组值为0的元素;
4)根据数组值从大到小排序;
5)取前256种颜色的数组信息,作为调色板上的256种颜色;
6)将图像内容数据改写为调色板的索引值。对图中每个像素取R,G,B的高4位,拼成一个12位整数,到调色板中查找,如果存在,则填入对应的索引值;如果不存在,则利用最小平方误差在调色板中查找替换颜色的索引值。
注:最小平方误差,即:(red1 – red2)^2+(green1 – green2)^2+(blue1 – blue2)^2中最小的一个。可以先对第256种以后的颜色计算替换颜色索引值,再更改图像内容数据。
5.4 对比度扩展
1. 低对比度:即灰度都挤在一起,没有拉开。假设有一幅图,由于成象时光照不足,使得整幅图偏暗(例如,灰度范围从0到63);或者成象时光照过强,使得整幅图偏亮(例如,灰度范围从200到255)。
2. 灰度扩展:把你所感性趣的灰度范围拉开,使得该范围内的象素,亮的越亮,暗的越暗。
3. 做法:根据以下公式计算出新的灰度值:
gold表示原图的灰度值,gnew表示gold经过对比度扩展后得到了新的灰度值。g1old和g2old表示原图中要进行对比度扩展的范围,g1new和g2new表示对应的新值。
我们假设a=c,这样,我们只要给出b,g1old和g2old,就可以求出
a=(255-b(g2old-g1old))/(255-(g2old-g1old))
要注意的是,给出的三个参数必须满:(1) b*(g2old-g1old)<=255;(2) (g2old-g1old)<=255。
5.5 削波
1. 定义:是对比度扩展的特例,即a=c=0。
2. 做法:只要给出g1old和g2old两个值,运用方程:b(g2old-g1old)=255计算出b值,并带入上节的公式中求得新图的灰度值即可。
5.6 阈值化
1. 定义:是削波的特例,即g1old=g2old。
2. 做法:阈值就象个门槛,比它大就是白,比它小就是黑。
3. 作用:是一种常用的将图像转换成黑白二值图的方法。
5.7 灰度窗口变换
1 .定义:灰度窗口变换是将某一区间的灰度级和其它部分(背景)分开。
2. 种类:
1)清除背景:把不在灰度窗口范围内的象素都赋值为0,在灰度窗口范围内的象素都赋值为255,这也能实现灰度图的二值化;
2)保留背景:把不在灰度窗口范围内的象素保留原灰度值,在灰度窗口范围内的象素都赋值为255。
3. 应用领域:电影特技处理(例如:“蓝幕”技术)。
5.8 灰度直方图统计
1.定义:用来统计图像灰度分布情况。,图中的横坐标表示灰度值,纵坐标表示该灰度值出现的次数(频率)。
5.9 灰度直方图均衡化
1. 直方图修正,就是通过一个灰度映射函数Gnew=F(Gold),将原灰度直方图改造成你所希望的直方图。
2. 直方图均衡化是一种最常用的直方图修正。它是把给定图象的直方图分布改造成均匀直方图分布。直观地讲,直方图均衡化导致图象的对比度增加。//??感觉像降低对比度。
3. 做法:
1)用一个数组s记录Pi分布的概率,即灰度i出现的次数与总的点数之比;
2)i从1开始,令s[i]=s[i]+s[i-1];
3)用一个数组L记录新的调色板索引值,即令L[i]=s[i]×(10-1);
4)计算新调色板的灰度值。
for (i = 0; i < EquaScale; i++) {
Gray=(int)(i*255.0/(EquaScale-1)); //??超级不理解为什么是这样算的。
… …
}
5)通过数组L结果,调整图像实际数据内的调色板索引值。
第6章腐蚀,膨胀,细化算法
这部份内容属于数学形态学,作者说是他认为最有趣的一个章节。限于篇幅,只介绍二值图象的形态学运算。在程序中,为了处理的方便,还是采用256级灰度图,不过只用到了调色板中的0和255两项。
先来定义一些基本符号和关系。
1. 元素:记作a∈X
2. B包含于X:记作B X
3. B击中X:B和X有交集,记作B↑X
4. B不击中X:记作B∩X=Ф
5. 补集:即B Xc
6. 结构元素:也被称作刷子,可以看作是特殊的颜色图案。
7. 对称集:将B中所有元素的坐标取反,即令(x,y)变成(-x,-y),记作Bv。
8. 平移:设有一幅图象B,有一个点a(x0,y0),将B平移a后的结果是,把B中所有元素的横坐标加x0,纵坐标加y0,即令(x,y)变成(x+x0,y+y0),记作Ba
6.1 腐蚀
1.定义:把结构元素B平移a后得到Ba,若Ba包含于X,我们记下这个a点,所有满足上述条件的a点组成的集合称做X被B腐蚀(Erosion)的结果。用公式表示为:E(X)={a| Ba X}=X B。
2.性质:
1) 其中,E(X)一定包含于X,而且比X小。
2) B是对称的,即B的对称集Bv=B,所以X被B腐蚀的结果和X被 Bv腐蚀的结果是一样的。如果B不是对称的,X被B腐蚀的结果和X被 Bv腐蚀的结果不同。
3.腐蚀的方法:
拿B的中心点和X上的黑点(因为被腐蚀的只有黑点)一个一个地对比,如果B上的所有点都在X的范围内,则该点保留,否则将该点去掉。
6.2 膨胀
1.定义:膨胀可以看做是腐蚀的对偶运算。把结构元素B平移a后得到Ba,若Ba击中X,我们记下这个a点。所有满足上述条件的a点组成的集合称做X被B膨胀的结果。用公式表示为:D(X)={a | Ba↑X}=XB。
2.性质:
1)X一定包含于D(X),而且比D(X)小。
2)如果B不是对称的,X被B膨胀的结果和X被 Bv膨胀的结果不同。
3.膨胀的方法:
拿B的中心点和X上的白点(只对白点进行扩张)及X周围的点一个一个地对,如果B上有一个点落在X的范围内,则该点就为黑。
腐蚀运算和膨胀运算互为对偶的,用公式表示为(X B)c=(Xc B),即X 被B腐蚀后的补集等于X的补集被B膨胀。
6.3 开
1.定义:先腐蚀后膨胀称为开,即OPEN(X)=D(E(X))。
2.作用:一般来说,开运算能够去除孤立的小点,毛刺和小桥(即连通两块区域的小点),而总的位置和形状不变。
6.4 闭
1.定义:先膨胀后腐蚀称为闭,即CLOSE(X)=E(D(X))。
2.作用:一般来说,闭运算能够填平小湖(即小孔),弥合小裂缝,而总的位置和形状不变。
注意:如果B是非对称的,进行开运算或闭运算时要用B的对称集Bv膨胀,否则,开运算或闭运算的结果和原图相比要发生平移。开运算和闭运算是对偶运算。
6.5 细化
1.定义:从原来的图中去掉一些点,但仍要保持原来的形状。实际上,是保持原图的骨架。所谓骨架,可以理解为图象的中轴。
2.去除点选择的方法:扫描图中所有黑点的相邻8个点。黑点记为0,白点记为1。从左到右,从上到下,拼成8位二进制数值。然后查对应表(已经定义好了的),来决定是否删除这个点。
3.算法实现方法:设置一个BOOL变量表示这次扫描中有没有删除点。如果有,则继续新一轮扫描;反之终止。每次扫描包括一次水平扫描和一次垂直扫描。在每一行水平扫描的过程中,先判断每一点的左右邻居,如果都是黑点,则该点不做处理。另外,如果某个黑点被删除了,那么跳过它的右邻居,处理下一个点。
这一章的算法实现比较简单,只是在概念理解方面花了一些时间。马上就要开学了,还有三章内容要看,唉~ 为自己加油打气~~~~
第7章 边沿检测与提取,轮廓跟踪
7.1 边沿检测
由于图像边界上的灰度和其它地方的相差较大,所以可以通过模板的方式检测出边沿。这种模板就是一种边沿检测器,又称边沿算子。模板的梯度和图像边沿的方向总是正交,例如,边是水平方向的,那可以用梯度是垂直方向的模板检测它的边沿;而边是垂直方向的,就可以用梯度是水平方向的模板检测它的边沿;一个梯度为45度方向模板,可以检测出135度方向的边沿。
下面介绍几种算子:
1.Sobel算子
Sobel算子是一种常用的模板,和上面提到的算子相比,对于象素的位置的影响做了加权,因此效果更好。该算子有两种形式:一种是:检测水平边沿的;检测垂直平边沿的。另一种形式是各向同性Sobel算子,检测水平边沿的,检测垂直平边沿的。各向同性Sobel算子和普通Sobel算子相比,它的位置加权系数更为准确,在检测不同方向的边沿时梯度的幅度一致。
2.高斯拉普拉斯算子
为了消除噪声点对边沿检测的影响,该算子采用将高斯平滑滤波器和拉普拉斯锐化滤波器结合了起来,先平滑掉噪声,再进行边沿检测,所以效果会更好。常用的LOG算子是5×5的模板,如下所示 。到中心点的距离与位置加权系数的关系用曲线很象一顶墨西哥草帽,所以LOG又叫墨西哥草帽滤波器。
7.2 Hough变换
Hough变换用来在图象中查找直线。它的原理很简单:假设有一条与原点距离为s,方向角为θ的一条直线,直线上的每一点都满足方程7.1:
可以利用这个变换找出图中最长的直线,实现算法如下:
1.创建一个二维数组hDistAlpha,其中第一维表示距离s(计算可能出现的最大距离为,用来确定数组第二维的大小),第二维表示方向角θ(书上正好和我说的相反,但看了程序以后我更坚持自己的想法)。
2.创建一个二维数组Line,计算每条直线的上下两个端点。
3.对图像中的每个黑点,角度的变化范围从00到1780(角度每次增加20 ),按方程(7.1)求出对应的距离s来,相应的数组元素[s][]加1,同时相应的填写数组Line的内容。
4.所有的象素都算完后,找到数组元素中最大的,就是最长的那条直线。直线的端点可以在Line中找到。
7.3 轮廓提取
轮廓提取的算法非常简单,就是掏空内部点:如果原图中有一点为黑,且它的8个相邻点都是黑色时(此时该点是内部点),则将该点删除。
7.4 种子填充
种子填充算法用来在封闭曲线形成的环中填充某中颜色,在这里我们只填充黑色。其原理是:准备一个堆栈,先将要填充的点push进堆栈中;以后,每pop出一个点,将该点涂成黑色,然后按左上右下的顺序查看它的四个相邻点,若为白(表示还没有填充),则将该邻点push进栈。一直循环,直到堆栈为空。此时,区域内所有的点都被涂成了黑色。
要注意的是:(1)要填充的区域是封闭的;(2)我们处理的虽然是二值图,但实际上是256级灰度图,不过只用到了0和255两种颜色;(3)在菜单中选择种子填充命令时,提示用户用鼠标点取一个要填充区域中的点,处理是在WM_LBUTTONDOWN中。
7.5 轮廓跟踪
轮廓跟踪,顾名思义就是通过顺序找出边缘点来跟踪出边界。一个简单二值图象闭合边界的轮廓跟踪算法很简单:首先按从上到下,从左到右的顺序搜索,找到的第一个黑点一定是最左上方的边界点,记为A。它的右,右下,下,左下四个邻点中至少有一个是边界点,记为B。从开始B找起,按右,右下,下,左下,左,左上,上,右上的顺序找相邻点中的边界点C。如果C就是A点,则表明已经转了一圈,程序结束;否则从C点继续找,直到找到A为止。判断是不是边界点很容易:如果它的上下左右四个邻居都是黑点则不是边界点,否则是边界点。
第8章 图象的检测及模板匹配
利用电脑来实现图像识别和分割是非常困难的,人脑可以从很复杂的景物中分开并识别每个物体,甚至可以毫不费力地跟上每秒好几十帧变化的图象。而对于计算机来说,要达到人脑的识别水平是相当困难。因为实现复杂,这里只是一些最基本,最简单的算法和思想,针对也只能是一些具体(而不是通用)的应用。算法共有三个:投影法、差影法和模板匹配。
8.1 投影法
1.定义:投影法结果类似于灰度直方图,通过垂直或水平投影确定识别目标的垂直或水平位置。
2.实现方法:
1)去除噪声(由于噪声点对投影有一定的影响,所以处理前最好先做一次平滑)。
2)将图像进行阈值化(为了使处理想过更好);
3)二值化(方便后期统计处理);
4)做垂直或水平投影(统计每行(或每列)白点(或黑点)的个数,再形成相应的直方图)。
8.2 差影法
差影法的原理非常简单:将前后两幅图象相减,得到的差作为结果结果图象。差影法是非常有用的,可以用在监控系统中,电影“阿甘正传”特技中应用了“蓝幕”技术,其实也包含了差影法的原理。
8.3 模板匹配
所谓模板匹配,其实想法很简单:拿已知的模板(在本例中为足球的图象),和原图象中同样大小的一块区域去对,可以用平方误差之和来衡量原图中的块和模板之间的差别。
因为需要一个个象素的平移和匹配,所以运算量相当庞大。
呵呵~ 好像习惯了每章内容都写一点感想!这章内容虽然电子书上介绍的很少,但深刻感受到,这部分的内容有很多,也有专门的学派在研究图像识别。以前经常在电视上看到很多关于图像识别的技术,都挺感兴趣的,不过真要深究这方面的话,还是比较麻烦的!涉及的算法太多。。。
9号就开学了,还剩两章内容没有看,得加油啦!
每个人不同,所以每个人的路不同。对于不同人来说,成功的终点也会不同,所以只要朝着自己的方向,用自己的方法去活者就好,每天多努力一点。。。
第9章 图象的压缩编码,JPEG压缩编码标准
注:1英寸=25.4毫米
从信息论的角度来看,压缩就是去掉信息中的冗余,即保留不确定的信息,去掉确定的信息(可推知的),也就是用一种更接近信息本质的描述来代替原有冗余的描述。
压缩可分为两大类:无损压缩(可逆)和有损压缩(不可逆)。
压缩编码的方法有很多,主要分成以下四大类:象素编码,预测编码,变换编码和其它方法。
1) 象素编码:编码时对每个象素单独处理,不考虑象素之间的相关性。常用的几种方法有:脉冲编码调制(PCM),熵编码,行程编码和位平面编码。
2) 预测编码: 去除相邻象素之间的相关性和冗余性,只对新的信息进行编码。常用的预测编码有调制(DM);微分预测编码(DPCM)
3) 变换编码: 将给定的图象变换到另一个数据域(如频域)上,使得大量的信息能用较少的数据来表示。变换编码有很多,如离散傅立叶变换(DFT),离散余弦变换(DCT)和离散哈达玛变换(DHT)。
4) 其它的编码方法也有很多,如混合编码、矢量量化(VQ) 、LZW算法。
9.1 哈夫曼编码
它的基本原理是频繁使用的数据用较短的代码代替,较少使用的数据用较长的代码代替,每个数据的代码各不相同。
产生Huffman编码需要对原始数据扫描两遍。第一遍扫描要精确地统计出原始数据中,每个值出现的频率,第二遍是建立Huffman树并进行编码。由于需要建立二叉树并遍历二叉树生成编码,因此数据压缩和还原速度都较慢,但简单有效,因而得到广泛的应用。
由于以前学过这种编码,所以算法就不详记了~
9.2 行程编码
行程编码的原理也很简单:将一行中颜色值相同的相邻象素用一个计数值和该颜色值来代替。
优点:如果一幅图象是由很多块颜色相同的大面积区域组成,那么压缩效率惊人。
缺点:如果图象中每两个相邻点的颜色都不同,用这种算法不但不能压缩,反而数据量增加一倍。所以现在单纯采用行程编码的压缩算法用得并不多,PCX文件算是其中的一种。
9.3 LZW算法的大体思想
LZW是一种比较复杂的压缩算法,其压缩效率也比较高。它的基本原理:LZW把每一个第一次出现的字符串用一个数值来编码,在还原程序中再将这个数值还成原来的字符串。LZW是无损的。GIF文件采用了这种压缩算法。
9.4 JPEG压缩编码标准
额。。。 最后一节实在是看不下去了!
深刻总结,对图像压缩和编码完全没有兴趣~ 就饶了我吧~~~~~~~~~
祈祷——别让我从事压缩和编码这方面的事情~~~~
第10章 图象处理编程工具及简单的多媒体编程
10.1 LeadTools
问题:1.没找到lead std control这一项,也没有找到lead32.ocx这个文件。
10.2 DirectDraw
DirectDraw是为速度而设计的,它绕过与Windows的图形设备相连的多个层次,直接与硬件的底层打交道。这很适合游戏编程,因为它着重于快速产生平稳的图形。
DirectX技术的最大特点是能直接对硬件抽象层(HAL)操作,实现视频、声音的输出、网络相互通信,特别能对游戏杆直接编程。
目前的最新版DirectX5.0 SDK包括DirectDraw、DirectSound、DirectPlay、Direct3D、DirectInput、DirectSetup六个部分。其中DirectDraw管理游戏的视频输出,DirectSound管理游戏的声音输出,DirectPlay管理游戏的网络通信,Direct3D管理游戏的三维图形,DirectInput管理游戏的游戏杆控制,DirectSetup管理游戏的安装。
下图一说明了DirectDraw和其他Windows显示构件的联系。
图10.4 DirectDraw和其他Windows显示构件
10.3 简单的多媒体编程
MCI是Media Control Interface(媒体控制接口)的缩写,它提供了一套与设备无关的命令消息和命令字来控制媒体的播放。
库VFW32.LIB中提供了MCI的所有功能,编译后生成的是真正的可执行文件,无需附加动态库和控件,如VBX和OCX等。
勉勉强强总算看完了这本电子书,可能是因为中间断断续续的看,所以前面很多东西都不太记得了!明天把所有的内容都重温一遍吧~ 还得找出所有不太明白的地方,开学去问学长学姐们!不由得松一口气,两个月看一本电子书好像真的不会很艰难的,如果没看完,导师不知道会怎么想我呢!
看完全书总结:图像处理涉及的范围真的很广,虽然一些数学公式和算法我还没弄清楚,但已经找到自己喜欢的部分了,那就是电影特效处理!那种漂亮和奇特的画片,真想是自己的作品。
好的,既然找到自己喜欢的部分,好好向那方面努力吧!!! 加油哦~~~