📄 chap03.htm
字号:
name="_Toc486332876"></a><a name="_Toc486338985"></a><a name="_Toc454810850"></a><a
name="_Toc454856624"><span><span>锐化</span></span></a></h2>
<p style='line-height:18.0pt'><span
style='font-family:宋体;"Times New Roman"'>锐化</span><span lang=EN-US>(sharpening)</span><span
style='font-family:宋体;"Times New Roman"'>和平滑恰恰相反,它是通过增强高频分量来减少图象中的模糊,因此又称为高通滤波</span><span
lang=EN-US>(high pass filter)</span><span style='font-family:宋体;"Times New Roman";"Times New Roman"'>。锐化处理在增强图象边缘的同时增加了图象的噪声。</span></p>
<p style='line-height:18.0pt'><span
style='font-family:宋体;"Times New Roman"'>常用的锐化模板是拉普拉斯</span><span lang=EN-US>(Laplacian)</span><span
style='font-family:宋体;"Times New Roman"'>模板</span><span lang=EN-US>(</span><span style='font-family:
宋体;"Times New Roman"'>见</span><span
lang=EN-US>(3.4)</span><span style='font-family:宋体;
"Times New Roman"'>式</span><span lang=EN-US>)</span><span
style='font-family:宋体;"Times New Roman"'>,又是个数学家的名字,可见学好数学,走遍天下都不怕。</span></p>
<p align=center style='text-align:center;line-height:18.0pt'><span
lang=EN-US><sub> <img width=100 height=75
src="chap03.files/image067.gif" v:shapes="_x0000_i1081"> </sub> </span></p>
<p align=right style='text-align:right;line-height:18.0pt'><span
lang=EN-US>(3.4)</span></p>
<p style='line-height:18.0pt'><span
style='font-family:宋体;"Times New Roman"'>容易看出拉普拉斯模板的作法:先将自身与周围的</span><span lang=EN-US>8</span><span
style='font-family:宋体;"Times New Roman"'>个象素相减,表示自身与周围象素的差别;再将这个差别加上自身作为新象素的灰度。可见,如果一片暗区出现了一个亮点,那么锐化处理的结果是这个亮点变得更亮,增加了图象的噪声。</span></p>
<p style='line-height:18.0pt'><span
style='font-family:宋体;"Times New Roman"'>因为图象中的边缘就是那些灰度发生跳变的区域,所以锐化模板在边缘检测中很有用,这一点将在后面详细介绍。</span></p>
<p style='line-height:18.0pt'><span
style='font-family:宋体;"Times New Roman"'>图</span><span lang=EN-US>3.1</span><span style='font-family:
宋体;"Times New Roman"'>经过拉普拉斯模板处理后,如图</span><span
lang=EN-US>3.4</span><span style='font-family:宋体;
"Times New Roman"'>所示</span></p>
<p align=center style='text-align:center;line-height:18.0pt'><span
lang=EN-US> <img width=174 height=193
src="chap03.files/image068.gif" v:shapes="_x0000_i1082"> </span></p>
<p align=center style='text-align:center;line-height:18.0pt'><b><span
style='font-family:宋体;"Times New Roman"'>图</span>3.4 </b><b><span
style='font-family:宋体;"Times New Roman"'>锐化</span><span lang=EN-US></span></b></p>
<p style='line-height:18.0pt'><span
style='font-family:宋体;"Times New Roman"'>下面给出的程序是一个通用的</span><span lang=EN-US>3</span><span
style='font-family:宋体;"Times New Roman"'>×</span><span lang=EN-US>3</span><span style='font-family:
宋体;"Times New Roman"'>模板的函数,其中第二参数为模板类型,为如下定义的常量:</span></p>
<p style='line-height:18.0pt'><span lang=EN-US>#define TEMPLATE_SMOOTH_BOX 1
//Box</span><span style='font-family:宋体;"Times New Roman";"Times New Roman"'>平滑模板</span></p>
<p style='line-height:18.0pt'>#define TEMPLATE_SMOOTH_GAUSS 2 //<span
style='font-family:宋体;"Times New Roman"'>高斯平滑模板</span></p>
<p style='line-height:18.0pt'><span lang=EN-US>#define TEMPLATE_SHARPEN_LAPLACIAN
3 //</span><span style='font-family:宋体;"Times New Roman";"Times New Roman"'>拉普拉斯锐化模板</span></p>
<p style='line-height:18.0pt'><span
style='font-family:宋体;"Times New Roman"'>对应的模板数组如下</span></p>
<p style='line-height:18.0pt'><span lang=EN-US>int Template_Smooth_Box[9]={1,1,1,1,1,1,1,1,1};</span></p>
<p style='line-height:18.0pt'><span lang=EN-US>int Template_Smooth_Gauss[9]={1,2,1,2,4,2,1,2,1};</span></p>
<p style='line-height:18.0pt'><span lang=EN-US>int Template_Sharpen_Laplacian[9]={-1,-1,-1,-1,9,-1,-1,-1,-1};</span><span
lang=EN-US style='font-size:9.0pt;'></span></p>
<p style='line-height:18.0pt'><span
style='font-family:宋体;"Times New Roman"'>以后我们碰到其它的模板,仍然要用这个函数,所做的操作只是增加一个常量标识,及其对应的模板数组。</span></p>
<p style='line-height:18.0pt'><span
style='font-family:宋体;"Times New Roman"'>要注意的是,运算后如果出现了大于</span><span lang=EN-US>255</span><span
style='font-family:宋体;"Times New Roman"'>或者小于</span><span lang=EN-US>0</span><span style='font-family:
宋体;"Times New Roman"'>的点,称为溢出,溢出点的处理通常是截断,即大于</span><span
lang=EN-US>255</span><span style='font-family:宋体;
"Times New Roman"'>时,令其等于</span><span lang=EN-US>255</span><span
style='font-family:宋体;"Times New Roman"'>;小于</span><span lang=EN-US>0</span><span style='font-family:
宋体;"Times New Roman"'>时,取其绝对值。</span></p>
<p style='line-height:18.0pt'><span
style='font-family:宋体;"Times New Roman"'>这段程序和前几章介绍的代码许多地方是很相似的,所以注释简单一些。程序中并没有用到那种分解成两个一维模板的快速算法,你如果有兴趣,可以自己编着试试。</span></p>
<p style='line-height:18.0pt'><span lang=EN-US>BOOL TemplateOperation(HWND hWnd,
int TemplateType)</span></p>
<p style='line-height:18.0pt'><span lang=EN-US>{</span></p>
<p style='line-height:18.0pt'><span> </span>DWORD
OffBits,BufSize;</p>
<p style='line-height:18.0pt'>LPBITMAPINFOHEADER lpImgData;</p>
<p style='line-height:18.0pt'><span> </span>LPSTR
lpPtr;</p>
<p style='line-height:18.0pt'><span> </span>HLOCAL
hTempImgData;</p>
<p style='line-height:18.0pt'><span> </span>LPBITMAPINFOHEADER
lpTempImgData;</p>
<p style='line-height:18.0pt'><span> </span>LPSTR
lpTempPtr;</p>
<p style='line-height:18.0pt'><span> </span>HDC
hDc;</p>
<p style='line-height:18.0pt'><span> </span>HFILE
hf;</p>
<p style='line-height:18.0pt'><span> </span>LONG
x,y;</p>
<p style='line-height:18.0pt'><span> </span>float
coef; //<span style='font-family:宋体;"Times New Roman";"Times New Roman"'>模板前面所乘的系数</span></p>
<p style='line-height:18.0pt'><span> </span>int
CoefArray[9]; //<span style='font-family:宋体;
"Times New Roman"'>模板数组</span></p>
<p style='line-height:18.0pt'><span> </span>float
TempNum;</p>
<p style='line-height:18.0pt'><span> </span>char
filename[80];</p>
<p style='line-height:18.0pt'><span> </span>switch(TemplateType){
//<span style='font-family:宋体;
"Times New Roman"'>判断模板类型</span></p>
<p style='line-height:18.0pt'><span> </span>case
TEMPLATE_SMOOTH_BOX: //Box<span style='font-family:宋体;"Times New Roman";"Times New Roman"'>平滑模板</span></p>
<p style='line-height:18.0pt'><span>
</span>coef=(float)(1.0/9.0);</p>
<p style='line-height:18.0pt'><span>
</span>memcpy(CoefArray,Template_Smooth_Box,9*sizeof(int));</p>
<p style='line-height:18.0pt'><span>
</span>strcpy(filename,"c:\\smbox.bmp"); </p>
<p style='line-height:18.0pt'><span>
</span>break;</p>
<p style='line-height:18.0pt'><span> </span>case
TEMPLATE_SMOOTH_GAUSS: //<span style='font-family:宋体;"Times New Roman";"Times New Roman"'>高斯平滑模板</span></p>
<p style='line-height:18.0pt'><span>
</span>coef=(float)(1.0/16.0);</p>
<p style='line-height:18.0pt'><span>
</span>memcpy(CoefArray,Template_Smooth_Gauss,9*sizeof(int));</p>
<p style='line-height:18.0pt'><span>
</span>strcpy(filename,"c:\\smgauss.bmp");</p>
<p style='line-height:18.0pt'><span>
</span>break;</p>
<p style='line-height:18.0pt'><span> </span>case
TEMPLATE_SHARPEN_LAPLACIAN: //<span
style='font-family:宋体;"Times New Roman"'>拉普拉斯锐化模板</span></p>
<p style='line-height:18.0pt'><span>
</span>coef=(float)1.0;</p>
<p style='line-height:18.0pt'><span>
</span>memcpy(CoefArray,Template_Sharpen_Laplacian,9*sizeof(int));</p>
<p style='line-height:18.0pt'><span>
</span>strcpy(filename,"c:\\shlaplac.bmp");</p>
<p style='line-height:18.0pt'><span>
</span>break;</p>
<p style='line-height:18.0pt'><span> </span>}</p>
<p style='line-height:18.0pt'><span> </span>OffBits=bf.bfOffBits-sizeof(BITMAPFILEHEADER);</p>
<p style='line-height:18.0pt'><span> </span>BufSize=OffBits+bi.biHeight*LineBytes;</p>
<p style='line-height:18.0pt'><span> </span>if((hTempImgData=LocalAlloc(LHND,BufSize))==NULL)</p>
<p style='line-height:18.0pt'><span
lang=EN-US>{</span></p>
<p style='line-height:18.0pt'><span> </span>
MessageBox(hWnd,"Error alloc memory!","Error Message",MB_OK|</p>
<p style='line-height:
18.0pt'><span lang=EN-US>MB_ICONEXCLAMATION);</span></p>
<p style='line-height:
18.0pt'><span lang=EN-US>return FALSE;</span></p>
<p style='line-height:18.0pt'><span
lang=EN-US>}</span></p>
<p style='line-height:18.0pt'><span> </span> lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
</p>
<p style='line-height:18.0pt'><span> </span>lpTempImgData=(LPBITMAPINFOHEADER)LocalLock(hTempImgData);</p>
<p style='line-height:18.0pt'><span> </span>lpPtr=(char
*)lpImgData;</p>
<p style='line-height:18.0pt'><span> </span>lpTempPtr=(char
*)lpTempImgData;</p>
<p style='line-height:18.0pt'><span
lang=EN-US>//</span><span style='font-family:宋体;
"Times New Roman"'>先将原图直接拷贝过来,其实主要是拷贝周围一圈的象素</span></p>
<p style='line-height:18.0pt'><span> </span>memcpy(lpTempPtr,lpPtr,BufSize);
</p>
<p style='line-height:18.0pt'><span> </span>for(y=1;y<bi.biHeight-1;y++)
//<b><span style='font-family:黑体'>注意<span lang=EN-US>y的范围是从1到bi.biHeight-2</span></span></b></p>
<p style='line-height:18.0pt'><span>
</span>for(x=1;x<bi.biWidth-1;x++){ //<b><span style='font-family:黑体'>注意<span lang=EN-US>x的范围是从1到bi.biWidth-2</span></span></b></p>
<p style='line-height:18.0pt'><span>
</span>lpPtr=(char *)lpImgData+(BufSize-LineBytes-y*LineBytes)+x;</p>
<p style='line-height:18.0pt'><span>
</span>lpTempPtr=(cha
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -