laplace算子是二阶导
众所周知
f
′
(
x
)
=
f
(
x
+
δ
)
−
f
(
x
)
δ
(
δ
趋
于
0
的
极
限
)
f'(x)= \frac{f(x+\delta)-f(x)}{\delta}(\delta趋于0的极限)
f′(x)=δf(x+δ)−f(x)(δ趋于0的极限)
而与
δ
\delta
δ趋于0的方式无关,可以大于0趋于0,可以小于0趋于0,甚至可以震荡趋于0,而图像是离散的,所以求导也只能近似代替
比如取
δ
=
1
或
者
−
1
\delta=1或者-1
δ=1或者−1
即
f
′
(
x
)
=
f
(
x
+
1
)
−
f
(
x
)
f'(x)=f(x+1)-f(x)
f′(x)=f(x+1)−f(x)或者
f
′
(
x
)
=
f
(
x
)
−
f
(
x
−
1
)
f'(x)=f(x)-f(x-1)
f′(x)=f(x)−f(x−1)
此时二阶导
f
′
′
(
x
)
=
f
′
(
x
+
1
)
−
f
′
(
x
)
=
f
(
x
+
1
)
−
f
(
x
)
−
f
(
x
)
+
f
(
x
−
1
)
f''(x)=f'(x+1)-f'(x)=f(x+1)-f(x)-f(x)+f(x-1)
f′′(x)=f′(x+1)−f′(x)=f(x+1)−f(x)−f(x)+f(x−1)(第一次选择
δ
\delta
δ大于0趋于0,后一个两个均选择小于0趋于0,至于为啥这样做,感觉是为了对称性,或者是同一个方向累积的话误差会变大比如
f
′
′
(
x
)
=
f
′
(
x
+
1
)
−
f
′
(
x
)
=
f
(
x
+
2
)
−
f
(
x
+
1
)
−
f
(
x
+
1
)
+
f
(
x
)
f''(x)=f'(x+1)-f'(x)=f(x+2)-f(x+1)-f(x+1)+f(x)
f′′(x)=f′(x+1)−f′(x)=f(x+2)−f(x+1)−f(x+1)+f(x)显然太偏了)
计算方式确定后,核就定了,计算就是卷积比较简单
#include<iostream>
#include<opencv2\opencv.hpp>
using namespace std;
using namespace cv;
void BGR2Gray(Mat src, Mat &grayPic)
{
for (int i = 0; i < src.rows; i++)
{
for (int j = 0; j < src.cols; j++)
{
//Gray = R*0.299 + G*0.587 + B*0.114
grayPic.at<uchar>(i, j) = src.at<Vec3b>(i, j)[0] * 0.114 + src.at<Vec3b>(i, j)[1] * 0.587 + src.at<Vec3b>(i, j)[2] * 0.299;
}
}
}
void mylaplace(int lp[][3], Mat src, Mat out)
{
for (int i = 1; i < src.rows-1; i++)
{
for (int j = 1; j < src.cols-1; j++)
{
int tmp = 0;
for (int i1 = -1; i1 <= 1; i1++)
{
for (int i2 = -1; i2 <= 1; i2++)
{
tmp += lp[1 + i1][1 + i2] * src.at<uchar>(i + i1, j + i2);
}
}
if (tmp > 255)
tmp = 255;
if (tmp < 0)
tmp = 0;
out.at<uchar>(i, j) = tmp;
}
}
}
int main()
{
int lp[3][3] = { 0, 1, 0,
1, -4, 0,
0, 1, 0 };
int lp2[3][3]= { 1, 1, 1,
1, -8, 1,
1, 1, 1 };
Mat pic = imread("C:\\Users\\Thinkpad\\Desktop\\c++work\\pic\\lena.jpg", 1);
Mat src = Mat::zeros(pic.rows, pic.cols, CV_8UC1);
Mat out = src.clone();
BGR2Gray(pic, src);
mylaplace(lp2, src, out);
imshow("1", out);
waitKey();
return 0;
}