设图像中每个像素点的值为 f(x) f ( x ) ,对其做泰勒展开。
f(x+h)=f(x)+hf′(x)+12h2f″(x)+13!h3f‴(x)+O(h4)
f
(
x
+
h
)
=
f
(
x
)
+
h
f
′
(
x
)
+
1
2
h
2
f
″
(
x
)
+
1
3
!
h
3
f
‴
(
x
)
+
O
(
h
4
)
f(x−h)=f(x)−hf′(x)+12h2f″(x)−13!h3f‴(x)+O(h4)
f
(
x
−
h
)
=
f
(
x
)
−
h
f
′
(
x
)
+
1
2
h
2
f
″
(
x
)
−
1
3
!
h
3
f
‴
(
x
)
+
O
(
h
4
)
将两式相加,得到:
f(x−h)−2f(x)+f(x+h)h2=f″(x)+O(h2)
f
(
x
−
h
)
−
2
f
(
x
)
+
f
(
x
+
h
)
h
2
=
f
″
(
x
)
+
O
(
h
2
)
h=1 h = 1 的时候,直接将矩阵
[1−21]
[
1
−
2
1
]
对图像一行一行的做卷积就可以得到每个点 x x 方向的二阶导数,方向同理,把那个矩阵竖过来就可以了。
将两个矩阵相加,把矩阵
⎡⎣⎢⎢0101−41010⎤⎦⎥⎥
[
0
1
0
1
−
4
1
0
1
0
]
对整个图卷积一遍可以同时得到两个方向的二阶导数。
……代码写的丑请多见谅
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <cstdio>
using namespace cv;
int canny[5][5];
void init(){
canny[1][1]=0, canny[1][1]=1, canny[1][3]=0;
canny[2][1]=1, canny[2][2]=-4, canny[2][3]=1;
canny[3][1]=0, canny[3][2]=1, canny[3][3]=0;
}
Mat Do_X_Slow_Convolution(Mat img){
Mat ans;
img.copyTo(ans);
for (int i=0;i<img.rows;i++){
for (int j=0;j<img.cols;j++){
if (j==0||j==img.cols-1) continue;
ans.at<uchar>(i,j)=img.at<uchar>(i,j-1)-2*img.at<uchar>(i,j)+img.at<uchar>(i,j+1);
}
}
return ans;
}
Mat Do_Y_Slow_Convolution(Mat img){
Mat ans;
img.copyTo(ans);
for (int i=0;i<img.rows;i++){
for (int j=0;j<img.cols;j++){
if (i==0||i==img.rows-1) continue;
ans.at<uchar>(i,j)=img.at<uchar>(i-1,j)-2*img.at<uchar>(i,j)+img.at<uchar>(i+1,j);
}
}
return ans;
}
Mat Do_XandY_Slow_Convolution(Mat img){ // 灰度图
int row=img.rows;
int col=img.cols;
Mat ans;
img.copyTo(ans);
for (int i=0;i<row;i++){
for (int j=0;j<col;j++){
if (i==0||i==row-1||j==0||j==col-1){
continue;
}
int tmp=0;
for (int u=1;u<=3;u++){
for (int v=1;v<=3;v++){
int Pixel_Value=img.at<uchar>(i+u-2,j+v-2);
tmp+=Pixel_Value*canny[4-u][4-v];
}
}
ans.at<uchar>(i,j)=tmp;
}
}
return ans;
}
int main(){
init();
Mat src;
src=imread("/Users/hxh/Desktop/2.jpg",0);
namedWindow("src",WINDOW_AUTOSIZE);
namedWindow("res",WINDOW_AUTOSIZE);
namedWindow("resX",WINDOW_AUTOSIZE);
namedWindow("resY",WINDOW_AUTOSIZE);
Mat res=Do_XandY_Slow_Convolution(src);
Mat resX=Do_X_Slow_Convolution(src);
Mat resY=Do_Y_Slow_Convolution(src);
imshow("src",src);
imshow("res",res);
imshow("resX",resX);
imshow("resY",resY);
waitKey(0);
return 0;
}