基于高斯拟合的工业渐晕图像复原C++代码实现
本文主要实现论文《基于高斯曲面拟合的影像渐晕复原方法》。论文链接:http://www.doc88.com/p-6327759362814.html.
渐晕图像示例如下图,中间亮,边缘暗,论文的目的是通过二维高斯函数拟合渐晕图片,然后将原图与高斯拟合矩阵相减,得到的图片就是边缘亮度增高的结果图。
论文中高斯函数的参数更新使用梯度下降,梯度向量和Hessian矩阵如下:
C++代码:
#include<opencv2/core.hpp>
#include<opencv2/highgui.hpp>
#include<opencv.hpp>
#include<math.h>
#include<ctime>
#include <iostream>
using namespace std;
using namespace cv;
int M, N; //图像高、宽
Mat gradient(Mat src, double B, double x0, double y0, double a); //求高斯函数的梯度
Mat hessian(Mat src, double B, double x0, double y0, double a); //求Hessian矩阵
int main()
{
String desktop = "C:/Users/tian.li/Desktop/";
Mat src = imread(desktop + "rect.png");
cvtColor(src, src, CV_BGR2GRAY);
//像素值归一化
Mat img = (Mat_<double>)src / 255.0;
M = img.rows;
N = img.cols;
//寻找最大像素点,也就是高斯拟合函数的中心点
double A = -1;
Point maxPt;
minMaxLoc(img, NULL, &A, NULL, &maxPt);
int i0 = maxPt.x;
int j0 = maxPt.y;
cout << "i0:" << i0 << " j0:" << j0 << endl;
//初始化高斯拟合函数的各个参数B--幅度值,x0--中心点横坐标,y0--中心点纵坐标,a--标准差
double B = log(A);
double x0 = i0, y0 = j0;
double a = sqrt((pow((M / 2.0 - x0), 2) + pow((N / 2.0 - y0), 2)) / (B - log(img.at<double>(M / 2, N / 2))));
//初始化允许误差、、真实误差
double epsilon = 0.01, erro = 1.0;
//声明梯度变量、Hessian矩阵
Mat g, h;
int cnt = 0;
while (erro >= epsilon && cnt++ < 1e6) {
//求梯度和Hessian矩阵
g = gradient(img, B, x0, y0, a);
h = hessian(img, B, x0, y0, a);
//计算梯度下降的步长
double up = ((Mat)(g.t()*g)).at<double>(0, 0); //gT*g
double down = ((Mat)(g.