图像边缘可表示为一阶过极点或二阶过零点.
拉普拉斯算子表示为d2f = a2f / a2x + a2f / a2y
由于噪声点对边缘检测影响较大,所以由高斯滤波和拉普拉斯算子结合,形成高斯拉普拉斯算子。
由高斯函数根据拉普拉斯算子的公式求导可得
离散化,取sigma为1.0,则5x5模块为
{0.0175 0.0392 0.0431 0.0392 0.0175
0.0392 0 -0.0965 0 0.0392
0.0431 -0.0965 -0.3183 -0.0965 0.0431
0.0392 0 -0.0965 0 0.0392
0.0175 0.0392 0.0431 0.0392 0.0175}
对其取整,并使总和为0,则
{ -2, -4, -4, -4, -2,
-4, 0, 8, 0, -4,
-4, 8, 24, 8, -4,
-4, 0, 8, 0, -4,
-2, -4, -4, -4, -2 };
#include"cv.h"
#include "highgui.h"
void LOG(CvMat* gray, CvMat* edge);
int main()
{
IplImage *src = cvLoadImage("flower.jpg",1);
const int width = src->width;
const int height = src->height;
CvMat *gray = cvCreateMat(height, width, CV_8UC1);
cvCvtColor(src, gray, CV_BGR2GRAY);
CvMat *edge = cvCreateMat(height, width, CV_8UC1);
LOG(gray, edge);
cvShowImage("SRC", src);
cvShowImage("GRAY", gray);
cvShowImage("LOG", edge);
cvWaitKey(0);
cvCvtColor(gray, src, CV_GRAY2BGR);
cvSaveImage("GRAY.bmp", src);
cvCvtColor(edge, src, CV_GRAY2BGR);
cvSaveImage("EDGE.bmp", src);
cvReleaseMat(&gray);
cvReleaseMat(&edge);
return 0;
}
void LOG(CvMat* gray, CvMat* edge)
{
const int width = gray->width;
const int height = gray->height;
cvZero(edge);
CvMat* edgeTemp1 = cvCreateMat(height, width, CV_16SC1);
cvZero(edgeTemp1);
int Template1[25] = { -2, -4, -4, -4, -2,
-4, 0, 8, 0, -4,
-4, 8, 24, 8, -4,
-4, 0, 8, 0, -4,
-2, -4, -4, -4, -2 };
for (int j = 2; j < height - 2; j ++)
{
int* edgeTemp1Data = (int*)(edgeTemp1->data.ptr + j * edgeTemp1->step);
uchar* edgeData = (uchar*)(edge->data.ptr + j * edge->step);
for (int i = 2; i < width - 2; i ++)
{
for (int k = 0; k < 5; k ++)
{
for (int l = 0; l < 5; l ++)
{
edgeTemp1Data[i] += Template1[5 * k + l] * ((uchar*)(gray->data.ptr + (j + k - 2) * gray->step))[i + l - 2];
if (abs(edgeTemp1Data[i]) > 255)
{
edgeData[i] = 255;
}
else
{
edgeData[i] = abs(edgeTemp1Data[i]);
}
}
}
}
}
cvReleaseMat(&edgeTemp1);
}