代码
#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;
}
效果
原始图像
![](https://i-blog.csdnimg.cn/blog_migrate/732e8fdc6258b404583c834e7adabf3e.png)
流场平滑后的图像
![](https://i-blog.csdnimg.cn/blog_migrate/f2f613d9b6584f950e7cd636cc36ebad.png)