1. 程式人生 > >基於L0測度的優化能量公式的流場平滑

基於L0測度的優化能量公式的流場平滑

視訊網址:https://www.bilibili.com/video/av36468467/

程式碼網址:https://download.csdn.net/download/lykymy/10799373

影象能量的計算

long min_energy(int value1, int value2)
{
	int min_difference1 = 100, min_difference2 = 100;
	int min_difference = abs(value2 - value1);
	if ((value1 - 0) < min_difference1)
	{
		min_difference1 = value1 - 0;
	}
	if ((90 - value1) < min_difference1)
	{
		min_difference1 = 90 - value1;
	}
	if ((value2 - 0) < min_difference2)
	{
		min_difference2 = value2 - 0;
	}
	if ((90 - value2) < min_difference2)
	{
		min_difference2 = 90 - value2;
	}
	if (min_difference < (min_difference1 + min_difference2))
	{
		long temp = min_difference * min_difference;
		return temp;
	}
	else
	{
		long temp = (min_difference1 + min_difference2) * (min_difference1 + min_difference2);
		return temp;
	}
}
void energy_solve(Mat & image, int time)
{
	long sum = 0, temp = 0, up_difference = 0, down_difference = 0, left_difference = 0 , right_difference = 0;
	for (int i = 1; i < image.rows - 1; i++)
	{
		for (int j = 1; j < image.cols - 1; j++)
		{
			up_difference = min_energy(image.at<short>(i, j) , image.at<short>(i - 1, j));
			down_difference = min_energy(image.at<short>(i, j) , image.at<short>(i + 1, j));
			left_difference = min_energy(image.at<short>(i, j) , image.at<short>(i, j - 1));
			right_difference = min_energy(image.at<short>(i, j) , image.at<short>(i, j + 1));
			temp = sqrt(up_difference + down_difference + left_difference + right_difference);
			sum += temp;
		}
	}
	cout << "This is "<< time << " Flow Field Energy Value : " << sum << endl;
}

L0測度平滑處理

void l0_smooth(Mat & image, float angle_rate, float side_rate, float left_down_rate, float right_down_rate, float right_top_rate, int time)
{
	//建立grad_x和grad_y 、abs_grad_x和abs_grad_y矩陣
	Mat grad_x; 
	Mat grad_y;
	//建立sobel運算元處理顯示圖片
	Mat sobel_img = Mat::zeros(image.size(), CV_16S);
	int scale = 1;
	int delta = 0;
	int ddepth = CV_16S;
	//求X方向梯度
	Sobel(image, grad_x, ddepth, 1, 0, 3, scale, delta, BORDER_DEFAULT);
	//求Y方向梯度
	Sobel(image, grad_y, ddepth, 0, 1, 3, scale, delta, BORDER_DEFAULT);
	//構建流場
	for (int i = 0; i < image.rows; i++)
	{
		for (int j = 0; j < image.cols; j++)
		{
			if (grad_x.at<ushort>(i, j) != 0)
			{
				sobel_img.at<short>(i, j) = atan(fabs(grad_y.at<ushort>(i, j) / grad_x.at<ushort>(i, j)));
			}
			else
			{
				sobel_img.at<short>(i, j) = 90;
			}
		}
	}
	//構造l0平滑流場
	Mat l0_img = Mat::zeros(sobel_img.size(), CV_16S);
	//構造臨時變數
	int left_down_value, right_down_value, right_top_value;
	//計算影象的能量值
	energy_solve(sobel_img, 0);
	//重複迭代time次
	for (int k = 1; k <= time; k++)
	{
		//進行l0平滑,處理中間部分
		for (int i = 1; i < sobel_img.rows - 1; i++)
		{
			for (int j = 1; j < sobel_img.cols - 1; j++)
			{
				left_down_value = (sobel_img.at<short>(i - 1, j) - sobel_img.at<short>(i, j)) + (sobel_img.at<short>(i, j + 1) - sobel_img.at<short>(i, j)) + 2 * (sobel_img.at<short>(i - 1, j - 1) - sobel_img.at<short>(i, j));
				right_down_value = (sobel_img.at<short>(i - 1, j) - sobel_img.at<short>(i, j)) + (sobel_img.at<short>(i, j - 1) - sobel_img.at<short>(i, j)) + 2 * (sobel_img.at<short>(i + 1, j + 1) - sobel_img.at<short>(i, j));
				right_top_value = (sobel_img.at<short>(i + 1, j) - sobel_img.at<short>(i, j)) + (sobel_img.at<short>(i, j - 1) - sobel_img.at<short>(i, j)) + 2 * (sobel_img.at<short>(i - 1, j + 1) - sobel_img.at<short>(i, j));
				l0_img.at<short>(i, j) = sobel_img.at<short>(i, j) + left_down_value *left_down_rate + right_down_value * right_down_rate + right_top_value * right_top_rate;
			}
		}
		//進行l0平滑,處理上邊緣部分
		for (int t = 1; t < sobel_img.cols - 1; t++)
		{
			l0_img.at<short>(0, t) = sobel_img.at<short>(0, t) + side_rate * ((sobel_img.at<short>(0, t - 1) - sobel_img.at<short>(0, t)) + (sobel_img.at<short>(1, t) - sobel_img.at<short>(0, t)) + (sobel_img.at<short>(0, t + 1) - sobel_img.at<short>(0, t)));
		}
		//進行l0平滑,處理下邊緣部分
		for (int t = 1; t < sobel_img.cols - 1; t++)
		{
			l0_img.at<short>(l0_img.rows - 1, t) = sobel_img.at<short>(sobel_img.rows - 1, t) + side_rate * ((sobel_img.at<short>(sobel_img.rows - 1, t - 1) - sobel_img.at<short>(sobel_img.rows - 1, t)) + (sobel_img.at<short>(sobel_img.rows - 2, t) - sobel_img.at<short>(sobel_img.rows - 1, t)) + (sobel_img.at<short>(sobel_img.rows - 1, t + 1) - sobel_img.at<short>(sobel_img.rows - 1, t)));
		}
		//進行l0平滑,處理左邊緣部分
		for (int t = 1; t < sobel_img.rows - 1; t++)
		{
			l0_img.at<short>(t, 0) = sobel_img.at<short>(t, 0) + side_rate * ((sobel_img.at<short>(t - 1, 0) - sobel_img.at<short>(t, 0)) + (sobel_img.at<short>(t, 1) - sobel_img.at<short>(t, 0)) + (sobel_img.at<short>(t + 1, 0) - sobel_img.at<short>(t, 0)));
		}
		//進行l0平滑,處理右邊緣部分
		for (int t = 1; t < sobel_img.rows - 1; t++)
		{
			l0_img.at<short>(t, l0_img.cols - 1) = sobel_img.at<short>(t, sobel_img.cols - 1) + side_rate * ((sobel_img.at<short>(t - 1, sobel_img.cols - 1) - sobel_img.at<short>(t, sobel_img.cols - 1)) + (sobel_img.at<short>(t, sobel_img.cols - 2) - sobel_img.at<short>(t, sobel_img.cols - 1)) + (sobel_img.at<short>(t + 1, sobel_img.cols - 1) - sobel_img.at<short>(t, sobel_img.cols - 1)));
		}
		//進行l0平滑,處理左上角
		l0_img.at<short>(0, 0) = sobel_img.at<short>(0, 0) + angle_rate * ((sobel_img.at<short>(0, 1) - sobel_img.at<short>(0, 0)) + (sobel_img.at<short>(1, 1) - sobel_img.at<short>(0, 0)) + (sobel_img.at<short>(1, 0) - sobel_img.at<short>(0, 0)));
		//進行l0平滑,處理右上角
		l0_img.at<short>(0, l0_img.cols - 1) = sobel_img.at<short>(0, sobel_img.cols - 1) + angle_rate * ((sobel_img.at<short>(0, sobel_img.cols - 2) - sobel_img.at<short>(0, sobel_img.cols - 1)) + (sobel_img.at<short>(1, sobel_img.cols - 2) - sobel_img.at<short>(0, sobel_img.cols - 1)) + (sobel_img.at<short>(1, sobel_img.cols - 1) - sobel_img.at<short>(0, sobel_img.cols - 1)));
		//進行l0平滑,處理左下角
		l0_img.at<short>(l0_img.rows - 1, 0) = sobel_img.at<short>(sobel_img.rows - 1, 0) + angle_rate * ((sobel_img.at<short>(sobel_img.rows - 2, 0) - sobel_img.at<short>(sobel_img.rows - 1, 0)) + (sobel_img.at<short>(sobel_img.rows - 2, 1) - sobel_img.at<short>(sobel_img.rows - 1, 0)) + (sobel_img.at<short>(sobel_img.rows - 1, 1) - sobel_img.at<short>(sobel_img.rows - 1, 0)));
		//進行l0平滑,處理右下角
		l0_img.at<short>(l0_img.rows - 1, l0_img.cols - 1) = sobel_img.at<short>(l0_img.rows - 1, sobel_img.cols - 1) + angle_rate * ((sobel_img.at<short>(l0_img.rows - 1, sobel_img.cols - 2) - sobel_img.at<short>(l0_img.rows - 1, sobel_img.cols - 1)) + (sobel_img.at<short>(l0_img.rows - 2, sobel_img.cols - 2) - sobel_img.at<short>(l0_img.rows - 1, sobel_img.cols - 1)) + (sobel_img.at<short>(l0_img.rows - 2, sobel_img.cols - 1) - sobel_img.at<short>(l0_img.rows - 1, sobel_img.cols - 1)));
		for (int i = 0; i < l0_img.rows; i++)
		{
			for (int j = 0; j < l0_img.cols; j++)
			{
				if (l0_img.at<short>(i , j) < 0)
				{
					l0_img.at<short>(i, j) = 0;
				}
				if (l0_img.at<short>(i, j) > 90)
				{
					l0_img.at<short>(i, j) = 90;
				}
			}
		}
		//獲取下次迭代影象
		sobel_img = l0_img.clone();
		//計算當前的影象能量
		energy_solve(l0_img, k);
	}
}

效果

原始處理圖片