# OpenCV-跟我一起学数字图像处理之拉普拉斯算子

Laplace算子和Sobel算子一样，属于空间锐化滤波操作。起本质与前面的Spatial Filter操作大同小异，下面就通过Laplace算子来介绍一下空间锐化滤波，并对OpenCV中提供的Laplacian函数进行一些说明。

• 数学原理

Laplace算子的差分形式

 0 1 0 1 -4 1 0 1 0

 1 1 1 1 -8 1 1 1 1

 0 -1 0 -1 4 -1 0 -1 0

 -1 -1 -1 -1 8 -1 -1 -1 -1

• 基于OpenCV的Laplace算子的计算

OpenCV中Laplacian函数可以实现对图像的Laplace操作，具体用法如下，

Laplacian( src_gray, dst, ddepth, kernel_size, scale, delta, BORDER_DEFAULT );

1. src_gray，输入图像
2. dst，Laplace操作结果
3. ddepth，输出图像深度，因为输入图像一般为CV_8U，为了避免数据溢出，输出图像深度应该设置为CV_16S
5. scale,delta,BORDER_DEFAULT，默认设置就好

//load the Original Image and get some informations
namedWindow("OriginalImage");
imshow("OriginalImage",src);
CV_Assert(src.depth() == CV_8U);


//OpenCV solution - Laplacian
Mat dst,abs_dst_laplace;
Laplacian(src,dst,CV_16S,
3);
convertScaleAbs(dst,abs_dst_laplace);

//show the result
namedWindow(result_laplacian);
imshow(
result_laplacian,abs_dst_laplace);

Laplace操作结果：

Laplace算子滤波仿真

//get some informations of original image
int nr = src.rows;
int nc = src.cols;
int n = nr*nc;
int arr[9] = {0};


//scan the whole pixels of original image
//and do Laplacian Operation
int* table_lap = new int[n];
int* table_orig = new int[n];
int l;
for (int i=0;i<n;i++)
{
table_lap[i]
= 0;
table_orig[i]
= 0;
}
for (int i=1;i<nr-1;i++)
{
const uchar* previous = src.ptr<uchar>(i-1);
const uchar* current = src.ptr<uchar>(i);
const uchar* next = src.ptr<uchar>(i+1);
for (int j=1;j<nc-1;j++)
{
for (int k=0;k<3;k++)
{
arr[k]
= previous[j+k-1];
arr[k
+3] = current[j+k-1];
arr[k
+6] = next[j+k-1];
}
l
= nc*i+j; //calculate the location in the table of current pixel
table_orig[l]
= arr[4];
}
}

//pixels scale
uchar* La_scaled = new uchar[n];
table_scale(table_lap,La_scaled,n);

Mat LaResult_own;
LaResult_own.create(src.size(),src.type());
uchar
* p = NULL;
for (int i=0;i<nr;i++)
{
p
= LaResult_own.ptr<uchar>(i);
for (int j=0;j<nc;j++)
{
l
= nc*i+j;
p[j]
= La_scaled[l];
}
}

//show results
namedWindow(LaResult_own);
imshow(
LaResult_own,LaResult_own);

//**********************//
//**********************//
{
int tmp[9] = {-1,-1,-1,-1,8,-1,-1,-1,-1};
for (int i=0;i<9;i++)
{
table[l] = table[l] + tmp[i]*arr[i];
}
}

tabel_scale函数就是我写的图像拉伸函数，将Laplace操作结果拉伸到[0,255]，具体函数段如下，

//*****************************//
//scale the pixels to [0 255]
//*****************************//
void table_scale(int* table,uchar* result,int n)
{
int min = table[0];
int max = table[0];
for (int i=0;i<n;i++)
{
if(min>table[i])
{
min = table[i];
}
if(max<table[i])
{
max = table[i];
}
}
for (int i=0;i<n;i++)
{
result[i] = (uchar)(255*(table[i]-min)/(max-min));
}
}

Laplace滤波图像与原图像的混合

//blending with the original image using Eq g(x,y)=f(x,y)+c*Lap(x,y)
int* table_blend = new int[n];
for(int i=0;i<n;i++)
{
table_blend[i] = table_orig[i] - table_lap[i];
if(table_blend[i]<0)
{
table_blend[i] = 0;
}
else if (table_blend[i]>255)
{
table_blend[i] = 255;
}
}


Mat Blresult;
Blresult.create(src.size(),src.type());
for (int i=0;i<nr;i++)
{
p
= Blresult.ptr<uchar>(i);
for(int j=0;j<nc;j++)
{
l
= nc*i+j;
p[j]
= table_blend[l];
}
}

//show blending result
namedWindow(blending result_laplacian);
imshow(
blending result_laplacian,Blresult);