转载请标明出处,https://blog.csdn.net/qq_36491519/article/details/86347393
已经有一年多没有写过博客了,最近好多新同事在学习计算机视觉的时候经常会问一些基础的问题,比如拉普拉斯算子等。因此打算重拾旧业写一些博客,以供大家参考。以前在国外的时候跟风(因为师兄弟们都是老外--貌似我才是老外。。。。)喜欢在国外的论坛上去写一些东西(呵呵,我的东方思维人家看不懂,所以没什么浏览量),现在决定在csdn上好好写一写。题外话了,开始正题。
拉普拉斯算子其实就是一个二阶微分算子,微分算子干嘛用的?锐化,增强,清晰图片用的。
有微分算子当然有积分算子,积分就可以看做是累加了。所以微分算子和平均运算等都被用于模糊图像,这些以后再谈论。
拉普拉斯算子公式:
展开之后
到这里就比较清晰了,最基本的拉普拉斯算子就成型了,
在3*3的掩模中就可以标识为:
0 | 1 | 0 |
1 | -4 | 1 |
0 | 1 | 0 |
这只是各基本版,你也可以根据需求做扩展,扩展就有很多了,按你自己的实际需求来设计。
往往在实际工程中我们不单纯的用拉普拉斯算子,而是用原始图像和拉普拉斯算子叠加来完成图像操作,如下公式:
实际操作后的图如下:
(a)图为月球原图,(b)为拉普拉斯处理过的图,(d)用原始图像和拉普拉斯算子叠加来完成的图像,是不是(d)效果更好呀。
用c++代码实现还是比较简单的,毕竟公式不复杂,(你也可以用matlab,python等实现)最懒的办法就是看opencv的算子实现。
/**************************************
*by 狂徒vincent
https://blog.csdn.net/qq_36491519
* 函数名称:
* LapTemplate(int inputH, int inputW, int inputX0, int inputY0, float * pTemplate, float fCoef)
* 参数:
* int inputH-模板的高度
* int inputW-模板的宽度
* int inputX0-模板的中心元素X坐标
* int inputY0-模板的中心元素Y坐标
* float *pTemplate-指向模板数组的指针
* float f-模板系数
*
* 返回值:
* void
*/**************************************
void LapTemplate(int inputH, int inputW, int inputX0, int inputY0, float * pTemplate, float fCoef){
unsigned char *pSrc, *pDst;
int i,j,k,l;
float value;
int m_imgWidth =inputH;
int [] m_pImgDataOut;
int m_nBitCount = 8;
if(m_pImgDataOut != NULL)
{
delete []m_pImgDataOut;
m_pImgDataOut = NULL;
}
int lineByte = (m_imgWidth * m_nBitCount / 8 + 3) / 4 * 4;
if(m_nBitCount != 8)
{
AfxMessageBox("只能处理8位灰度图像!");
return ;
}
//创建要复制的图像区域
int m_nBitCountOut = m_nBitCount;
int lineByteOut = (m_imgWidth * m_nBitCountOut / 8 + 3) / 4 * 4;
if (!m_pImgDataOut)
{m_pImgDataOut = new unsigned char
[lineByteOut * m_imgHeight];
}
int pixelByte = m_nBitCountOut / 8;
for(i = 0; i < m_imgHeight; i++){
for(j = 0; j < m_imgWidth * pixelByte; j++)
*(m_pImgDataOut + i * lineByteOut + j)= *(m_pImgData + i * lineByteOut + j);
}
//行处理
for (i = inputY0; i < m_imgHeight - inputH + inputY0 + 1; i++)
{
//列处理
for (j = inputX0; j <inputW + inputX0 + 1; j++)
{//指向新DIB第i行第j列像素的指针
pDst = m_pImgDataOut + lineByte * (m_imgHeight -1 - i) + j;
value=0;
//计算
for (k = 0; k < inputH; k++)
{
for (l = 0; l < inputW; l++)
{
pSrc = m_pImgData + lineByte * (m_imgHeight - 1 - i + inputY0 - k)+ j - inputX0 + l;
//计算加权平均
value += (*pSrc) * pTemplate[k * inputW + l];
}
}
//乘以系数
value *= f;//取结果的绝对值
value = (float)fabs(value);
if (value > 255)
{
*pDst = 255;
}
else
{
*pDst = (unsigned char)(value+0.5);
}
}
}
/**by 狂徒vincent
https://blog.csdn.net/qq_36491519
*/
}
这就是拉普拉斯算子,但有一点很重要,就是拉普拉斯算子虽然在边缘检测等很有用,但会造成噪声增强,所以在用拉普拉斯算子之前一定要做平滑处理等来去噪。
拉普拉斯算子就讲到这吧,有机会再和大家分享我在图像处理,计算机视觉以及视频技术方面的一些经验,也期盼从各位中学到新知识。