灰度图L0最小梯度平滑opencv+C++代码

Matlab代码:​​​​​​http://t.csdn.cn/vX6Hj​​​​​​

对上述文章中的“代码一”进行C++转换

本文C++代码只针对灰度图像,且只进行了暴力转换,尚未对算法速度进行优化,还望各位大佬手下留情,如有需要可留言

代码如下:

#include
#include
using namespace cv;
using namespace std;

//Matlab中psf2otf()函数
Mat psf2otf(const cv::Mat& psf, const cv::Size& outSize)
{
	Mat otf;

	if (countNonZero(psf) && !psf.empty())
	{
		Size psfSize = psf.size();

		Size paddSize = outSize - psfSize;

		copyMakeBorder(psf, otf, 0, paddSize.height,
			0, paddSize.width,
			BORDER_CONSTANT, Scalar(0));
		dft(otf, otf, DFT_COMPLEX_OUTPUT);
		
		//计算psf的元素个数
		int nElem = psf.cols * psf.rows;

		double nOps = 0;

		int nfft = nElem / psfSize.width;
		nOps += nfft + psfSize.width * log2(psfSize.width) * nfft;
		nfft = nElem / psfSize.height;
		nOps += nfft + psfSize.height * log2(psfSize.height) * nfft;
		//将复数otf分解成实部real和虚部imagin
		Mat planes[2];
		split(otf, planes);

		double max1, min1;
		cv::minMaxIdx(abs(planes[1]), &min1, &max1);
		//double imagin_max = mymax(abs(planes[1]));
		double imagin_max = max1;

		double max2, min2;
		cv::minMaxIdx(abs(otf), &min2, &max2);
		//double mag_max = mymax(myMagnitude(otf));
		double mag_max = max2;

		double eps = nOps * pow(2, -52);
		if ((imagin_max / mag_max) < eps)
			return planes[0];
	}
	return otf;
}
//Matlab中diff()函数
Mat diff(Mat& src, int a, int b)
{
	if (b == 2)//列数(宽)减少
	{
		Mat dst = Mat::zeros(Size(src.cols - 1, src.rows), src.type());
		for (int i = 0; i < dst.rows; i++)
		{
			double* p = src.ptr(i);
			double* d = dst.ptr(i);
			for (int j = 0; j < dst.cols; j++)
			{
				d[j] = (p[j + 1] - p[j]);
			}
		}
		return dst;	
	}
	else
	{
		Mat dst = Mat::zeros(Size(src.cols, src.rows - 1), src.type());
		for (int i = 0; i < dst.rows; i++)
		{
			double* p = src.ptr(i);
			double* p_down = src.ptr(i + 1);
			double* d = dst.ptr(i);
			for (int j = 0; j < dst.cols; j++)
			{
				d[j] = (p_down[j] - p[j]);
			}
		}
		return dst;
	}
}
//L0梯度最小平滑
void L0(Mat& t_Im, float t_lambda, float t_kappa)
{
	double lambda = (double)t_lambda;
	double kappa = (double)t_kappa;

	//S = im2double(Im);
	Mat S;
	t_Im.convertTo(S, CV_64FC1, 1.0 / 255.0);

	//betamax = 1e5;
	double betamax = 1e5;
	/*
	* fx = [-1, 1];
	* fy = [-1; 1];
	* [N,M,D] = size(Im);
	* sizeI2D = [N,M];
	* otfFx = psf2otf(fx,sizeI2D);
	* otfFy = psf2otf(fy,sizeI2D);
	*/
	Mat fx = (Mat_(1, 2) << 1, -1);
	Mat fy = (Mat_(2, 1) << 1, -1);
	Mat otfFx = psf2otf(fx, t_Im.size());
	Mat otfFy = psf2otf(fy, t_Im.size());

	//Normin1 = fft2(S);
	Mat Normin1;
	dft(S, Normin1, DFT_COMPLEX_OUTPUT);

	//Denormin2 = abs(otfFx).^2 + abs(otfFy ).^2;
	Mat Denormin2(t_Im.rows, t_Im.cols, CV_64FC1);
	for (int i = 0; i < t_Im.rows; i++)
	{
		double* d = Denormin2.ptr(i);
		for (int j = 0; j < t_Im.cols; j++)
		{
			Vec2d& c1 = otfFx.at(i, j);
			Vec2d& c2 = otfFy.at(i, j);
			// 0: Real, 1: Image
			d[j] = pow(c1[0], 2) + pow(c1[1], 2) + pow(c2[0], 2) + pow(c2[1], 2);
		}
	}

	//beta = 2*lambda;
	double beta = 2.0 * lambda;

	while (beta < betamax)
	{
		// Denormin   = 1 + beta*Denormin2;
		Mat Denormin = 1.0 + beta * Denormin2;

		// h-v subproblem
		
		//diff(S,1,2)
		Mat diffS12 = diff(S, 1, 2);
		/*
		* matlab中S(:, 1, : ), S中的第一列数据
		* matlab中S(:, end, : ), S中的最后一列数据
		*/
		Mat S01 = S.colRange(0, 1);
		Mat S0end = S.colRange(S.cols - 1, S.cols);
		/*
		* h = [diff(S,1,2), S(:,1,:) - S(:,end,:)];
		*/
		Mat Scol = S01 - S0end;
		Mat h = Mat::zeros(S.size(), CV_64FC1);
		for (int i = 0; i < S.rows; i++)
		{
			double* p = diffS12.ptr(i);
			double* sp = Scol.ptr(i);
			double* d = h.ptr(i);
			for (int j = 0; j < S.cols; j++)
			{
				if (j < diffS12.cols)
				{
					d[j] = p[j];
				}
				else
				{
					d[j] = sp[0];
				}
			}
		}

		//diff(S,1,1)
		Mat diffS11 = diff(S, 1, 1);
		/*
		* matlab中S(1, :, : ), S中的第一行数据
		* matlab中S(end, :, : ), S中的最后一行数据
		*/
		Mat S10 = S.rowRange(0, 1);
		Mat Send0 = S.rowRange(S.rows - 1, S.rows);
		/*
		* v = [diff(S,1,1); S(1,:,:) - S(end,:,:)];
		*/
		Mat Srow = S10 - Send0;
		Mat v = Mat::zeros(S.size(), CV_64FC1);
		for (int i = 0; i < S.rows; i++)
		{
			if (i < diffS11.rows)
			{
				double* p = diffS11.ptr(i);
				double* d = v.ptr(i);
				for (int j = 0; j < S.cols; j++)
				{
					d[j] = p[j];
				}
			}
			else
			{
				double* sp = Srow.ptr(0);
				double* d = v.ptr(i);
				for (int j = 0; j < S.cols; j++)
				{
					d[j] = sp[j];
				}
			}
		}
		/*
		* matlab中:
	    *   if D==1
				t = (h.^2+v.^2)(i);
			double* vt = v.ptr(i);
			for (int j = 0; j < S.cols; j++)
			{
				// (∂S/∂x)^2 + (∂S/∂y)^2			
				double val = pow(ht[j], 2) + pow(vt[j], 2);
				// (∂S/∂x)^2 + (∂S/∂y)^2  < λ/β
				if (val < lambda / beta) {
					ht[j] = 0.0;
					vt[j] = 0.0;
				}
			}
		}
		// S subproblem

		//Normin2 = [h(:,end,:) - h(:, 1,:), -diff(h,1,2)];
		Mat diffh12 = diff(h, 1, 2);
		/*
		* matlab中h(:, 1,:), h中的第一列数据
		* matlab中h(:,end,:), h中的最后一列数据
		*/
		Mat h0end = h.colRange(h.cols - 1, h.cols);
		Mat h01 = h.colRange(0, 1);
		Mat hcol = h0end - h01;
		Mat Normin21 = Mat::zeros(S.size(), CV_64FC1);
		for (int i = 0; i < S.rows; i++)
		{
			double* p = diffh12.ptr(i);
			double* sp = hcol.ptr(i);
			double* d = Normin21.ptr(i);
			for (int j = 0; j < S.cols; j++)
			{
				if (j == 0)
				{
					d[j] = sp[0];
				}
				else
				{
					d[j] = -p[j - 1];
				}
			}
		}
		//Normin2 = Normin2 + [v(end,:,:) - v(1, :,:); -diff(v,1,1)];
		/*
		* matlab中v(1, :,:), v中的第一行数据
		* matlab中v(end,:,:), v中的最后一行数据
		*/
		Mat diffv11 = diff(v, 1, 1);

		Mat v10 = v.rowRange(0, 1);
		Mat vend0 = v.rowRange(v.rows - 1, v.rows);
		Mat vrow = vend0 - v10;
		Mat Normin22 = Mat::zeros(S.size(), CV_64FC1);
		for (int i = 0; i < S.rows; i++)
		{
			if (i == 0)
			{
				double* sp = vrow.ptr(0);
				double* d = Normin22.ptr(i);
				for (int j = 0; j < S.cols; j++)
				{
					d[j] = sp[j];
				}
			}
			else
			{
				double* p = diffv11.ptr(i - 1);
				double* d = Normin22.ptr(i);
				for (int j = 0; j < S.cols; j++)
				{
					d[j] = -p[j];
				}
			}
		}
		Mat Normin2 = Normin21 + Normin22;

		//fft2(Normin2)
		Mat fft2Normin2;
		dft(Normin2, fft2Normin2, DFT_COMPLEX_OUTPUT);

		//FS = (Normin1 + beta*fft2(Normin2))./Denormin;
		Mat FS = Normin1 + beta * fft2Normin2;
		for (int i = 0; i < S.rows; i++)
		{
			double* p = Denormin.ptr(i);
			for (int j = 0; j < S.cols; j++)
			{
				FS.at(i, j)[0] /= p[j];
		     	FS.at(i, j)[1] /= p[j];
			}
		}
		//ifft2(FS)
		Mat ifft;
		idft(FS, ifft, cv::DFT_SCALE | cv::DFT_COMPLEX_OUTPUT);
		for (int i = 0; i < S.rows; i++)
		{
			double* p = S.ptr(i);
			for (int j = 0; j < S.cols; j++)
			{
				//S = real(ifft2(FS));
				p[j] = ifft.at(i, j)[0];
			}
		}
		//beta = beta*kappa;
		beta = beta * kappa;
	}
	//显示图片
	normalize(S, S, 0, 255, NORM_MINMAX);
	S.convertTo(S, CV_8UC1);
	resize(S, S, Size(S.cols / 1, S.rows / 1));
	imshow("S", S);
}
int main()
{
    Mat src = imread("C:\\Users\\DELL\\Desktop\\Lena.jpg", 0);
    L0(src,0.02,2.0);
	waitKey(0);
	return 0;
}

选取Lena图像,原图、Matlab与C++结果图分别如下:

原图:

灰度图L0最小梯度平滑opencv+C++代码_第1张图片

 Matlab的L0梯度最小平滑结果图:

灰度图L0最小梯度平滑opencv+C++代码_第2张图片

  C++的L0梯度最小平滑结果图:

灰度图L0最小梯度平滑opencv+C++代码_第3张图片

你可能感兴趣的:(数字图像处理代码,opencv,c++,计算机视觉)