基于拉普拉斯方程的图像流场平滑

代码

#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;

void show_src_image(Mat image)
{
	//创建显示图片的窗口
	namedWindow("Original Image", CV_WINDOW_AUTOSIZE);
	//显示原始图片
	imshow("Original Image", image);
}

void show_scharr_image(Mat image)
{
	//创建grad_x和grad_y矩阵
	Mat grad_x;
	Mat grad_y;
	//创建scharr算子处理显示图片
	Mat scharr_img = Mat::zeros(image.size(), CV_16S);
	//创建laplace平滑处理显示图片
	Mat laplace_img = Mat::zeros(image.size(), CV_16S);
	//定义scharr算子与laplace平滑处理默认参数
	int scale = 1;
	int delta = 0;
	int ddepth = CV_16S;
	//求X方向梯度
	Scharr(image, grad_x, ddepth, 1, 0, scale, delta, BORDER_DEFAULT );
	//求Y方向梯度
	Scharr(image, grad_y, ddepth, 0, 1, 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)
			{
				scharr_img.at<ushort>(i , j) = grad_y.at<ushort>(i, j) / grad_x.at<ushort>(i, j);
			}
			else
			{
				scharr_img.at<ushort>(i, j) = 90;
			}
		}
	}
	//计算利用laplacian算子进行平滑
	for (int i = 1; i < scharr_img.rows - 1; i++)
	{
		for (int j = 1; j < scharr_img.cols - 1; j++)
		{
			laplace_img.at<short>(i , j) = scharr_img.at<short>(i - 1 , j) + scharr_img.at<short>(i + 1, j) + scharr_img.at<short>(i, j + 1) + scharr_img.at<short>(i, j - 1) - 4 * scharr_img.at<short>(i, j);
		}
	}
	//创建显示窗口
	namedWindow("scharr laplace image", CV_WINDOW_AUTOSIZE);
	//显示拉普拉斯平滑处理过的图片
	imshow("scharr laplace image", laplace_img);
}

void show_sobel_image(Mat image)
{
	//创建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);
	//创建laplace平滑处理显示图片
	Mat laplace_img = Mat::zeros(image.size(), CV_16S);
	//定义sobel算子与laplace平滑处理默认参数
	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<ushort>(i, j) = grad_y.at<ushort>(i, j) / grad_x.at<ushort>(i, j);
			}
			else
			{
				sobel_img.at<ushort>(i, j) = 90;
			}
		}
	}
	//计算利用laplacian算子进行平滑
	for (int i = 1; i < sobel_img.rows - 1; i++)
	{
		for (int j = 1; j < sobel_img.cols - 1; j++)
		{
			laplace_img.at<short>(i, j) = (sobel_img.at<short>(i - 1, j) + sobel_img.at<short>(i + 1, j) + sobel_img.at<short>(i, j + 1) + sobel_img.at<short>(i, j - 1)) / 4 ;
		}
	}
	//创建显示窗口
	namedWindow("sobel laplace image", CV_WINDOW_AUTOSIZE);
	//显示拉普拉斯平滑处理过的图片
	imshow("sobel laplace image", laplace_img);
}

void show_prewitt_image(Mat image)
{
	//定义prewitt水平方向上的模板
	float prewittx[9] =
	{
		-1,0,1,
		-1,0,1,
		-1,0,1
	};
	//定义prewitt垂直方向上的模板
	float prewitty[9] =
	{
		1,1,1,
		0,0,0,
		-1,-1,-1
	};
	//创建laplace平滑处理显示图片
	Mat laplace_img;
	Mat abs_laplace_img;
	//定义prewitt算子与laplace平滑处理默认参数
	int scale = 1;
	int delta = 0;
	int ddepth = CV_16S;
	int kernel_size = 3;
	//将模板prewittx转化为Mat类型
	Mat px = Mat(3, 3, CV_32F, prewittx);
	//将模板prewitty转化为Mat类型
	Mat py = Mat(3, 3, CV_32F, prewitty);
	//定义存储水平梯度值的矩阵
	Mat dstx = Mat(image.size(), image.type(), image.channels());
	//定义存储垂直梯度值的矩阵
	Mat dsty = Mat(image.size(), image.type(), image.channels());
	//定义存储最终梯度值的矩阵
	Mat prewitt_img = Mat(image.size(), image.type(), image.channels());
	//利用模板prewittx进行水平方向的卷积运算
	filter2D(image, dstx, image.depth(), px);
	//利用模板prewitty进行垂直方向的卷积运算
	filter2D(image, dsty, image.depth(), py);
	//定义临时变量
	float tempx, tempy, temp;
	//计算利用prewitt算子求取梯度的图像
	for (int i = 0; i<image.rows; i++)
	{
		for (int j = 0; j<image.cols; j++)
		{
			tempx = dstx.at<uchar>(i, j);
			tempy = dsty.at<uchar>(i, j);
			//求取prewitt处理后的最终梯度值
			temp = sqrt(tempx*tempx + tempy*tempy);
			prewitt_img.at<uchar>(i, j) = (uchar)temp;
		}
	}
	//创建显示窗口
	namedWindow("prewitt image", CV_WINDOW_AUTOSIZE);
	//显示prewitt算子处理过的图片
	imshow("prewitt image", prewitt_img);
	//对图像进行laplace平滑处理
	Laplacian(prewitt_img, laplace_img, ddepth, kernel_size, scale, delta, BORDER_DEFAULT);
	//对图像的每个像素取绝对值
	convertScaleAbs(laplace_img, abs_laplace_img);
	//创建显示窗口
	namedWindow("prewitt laplace image", CV_WINDOW_AUTOSIZE);
	//显示拉普拉斯平滑处理过的图片
	imshow("prewitt laplace image", abs_laplace_img);
}

void show_roberts_image(Mat image)
{
	//创建显示roberts算子处理后的图像
	Mat roberts_img = Mat::zeros(image.size(), image.type());
	//创建laplace平滑处理显示图片
	Mat laplace_img;
	Mat abs_laplace_img;
	//定义prewitt算子与laplace平滑处理默认参数
	int scale = 1;
	int delta = 0;
	int ddepth = CV_16S;
	int kernel_size = 3;
	//计算利用roberts算子求取的梯度值
	for (int i = 0; i < image.rows - 1; i++)
	{
		for (int j = 0; j < image.cols - 1; j++)
		{
			//求取prewitt算子水平方向的梯度
			int grad_x = image.at<uchar>(i, j) - image.at<uchar>(i + 1, j + 1);
			//求取prewitt算子垂直方向的梯度
			int grad_y = image.at<uchar>(i + 1, j) - image.at<uchar>(i, j + 1);
			//求取prewitt处理后的最终梯度值
			roberts_img.at<uchar>(i, j) = (uchar)sqrt(grad_x * grad_x + grad_y * grad_y);
		}
	}
	//创建显示窗口
	namedWindow("roberts image", CV_WINDOW_AUTOSIZE);
	//显示roberts算子处理过的图片
	imshow("roberts image", roberts_img);
	//对图像进行laplace平滑处理
	Laplacian(roberts_img, laplace_img, ddepth, kernel_size, scale, delta, BORDER_DEFAULT);
	//对图像的每个像素取绝对值
	convertScaleAbs(laplace_img, abs_laplace_img);
	//创建显示窗口
	namedWindow("roberts laplace image", CV_WINDOW_AUTOSIZE);
	//显示拉普拉斯平滑处理过的图片
	imshow("roberts laplace image", abs_laplace_img);
}

int main(int argc, char** argv)
{
	//读取图片文件
	Mat src = imread("flower.jpg", IMREAD_COLOR);
	//定义同等大小、同等类型的存储图片的变量
	Mat gaussian_img = Mat::zeros(src.size(), src.type());
	Mat gray_img = Mat::zeros(src.size(), src.type());

	//判断文件是否读取成功
	if (!src.data)
	{
		cout << "Fail to read picture ." << endl;
		return -1;
	}
	//对图像进行高斯滤波
	GaussianBlur(src, gaussian_img, Size(3, 3), 0, 0, BORDER_DEFAULT);
	//将图像转化为灰度图片
	cvtColor(gaussian_img, gray_img, CV_RGB2GRAY);
	//显示原始图片
	show_src_image(src);
	//显示sobel算子求梯度、laplace平滑处理后的图片
	show_sobel_image(gray_img);
	//显示scharr算子求梯度、laplace平滑处理后的图片
	//show_scharr_image(gray_img);
	//显示prewitt算子求梯度、laplace平滑处理后的图片
	//show_prewitt_image(gray_img);
	//显示roberts算子求梯度、laplace平滑处理后的图片
	//show_roberts_image(gray_img);
	//等待用户终止
	waitKey();
	return 0;
}

效果

原始图像

流场平滑后的图像

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值