Demo entry 6780655

C++

   

Submitted by anonymous on Dec 28, 2018 at 01:54
Language: C++. Code size: 4.1 kB.

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
using namespace cv;
using namespace std;
/*********************************************************************************************************/
/*     用sobel算子对灰度图像进行滤波           */
int factorial(int n)
{
	// factorial()函数实现阶乘
	int fac = 1;
	if (n == 0)
	{
		return fac;
	}
	for (int i = 1; i <= n; ++i)
	{
		fac *= i;
	}
	return fac;
}
Mat getPascalSmooth(int n)
{
	//  getPascalSmooth()函数用来创建sobel平滑算子
	Mat pascalSmooth = Mat::zeros(Size(n, 1), CV_32FC1);
	for (int i = 0; i < n; ++i)
	{
		pascalSmooth.at<float>(0, i) = float(factorial(n - 1) / (factorial(i)*factorial(n - 1 - i)));
	}
	return pascalSmooth;
}
Mat getPascalDiff(int n)
{
	//  getPascalDiff()函数用来创建sobel差分算子
	Mat pascalDiff = Mat::zeros(Size(n, 1), CV_32FC1);
	Mat pascalSmooth_previous = getPascalSmooth(n - 1);
	for (int i = 0; i < n; ++i)
	{
		if (i == 0)
		{
			pascalDiff.at<float>(0, i) = 1;
		}
		else if (i == n - 1)
		{
			pascalDiff.at<float>(0, i) = -1;
		}
		else
		{
			pascalDiff.at<float>(0, i) = pascalSmooth_previous.at<float>(0, i) - pascalSmooth_previous.at<float>(0, i - 1);
		}
	}
	return  pascalDiff;
}
void conv2D(InputArray src, InputArray kernel, OutputArray dst, int ddepth, Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT)
{
	//  conv2D()函数用来完成same卷积运算
	Mat kernelFlip;
	flip(kernel, kernelFlip, -1);    // 卷积运算的第一步,将卷积核逆时针翻转180°
	filter2D(src, dst, ddepth, kernelFlip, anchor, 0.0, borderType);   //卷积运算的第二步
}
void sepConv2D_Y_X(InputArray src, OutputArray  src_kerY_kerX, int ddepth, InputArray kernelY, InputArray kernelX, Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT)
{
	// 对于可分离的离散二维卷积,先进行垂直方向上的卷积,再进行水平方向上的卷积
	Mat src_kerY;
	conv2D(src, kernelY, src_kerY, ddepth, anchor, borderType);   // 输入矩阵与垂直方向上的卷积核的卷积
	conv2D(src_kerY, kernelX, src_kerY_kerX, ddepth, anchor, borderType);  // 把从上面得到的卷积结果和水平方向上的卷积核卷积
}
void sepConv2D_X_Y(InputArray src, OutputArray  src_kerX_kerY, int ddepth, InputArray kernelX, InputArray kernelY, Point anchor = Point(-1, -1), int borderType = BORDER_DEFAULT)
{
	// 对于可分离的离散二维卷积,先进行水平方向上的卷积,再进行垂直方向上的卷积
	Mat src_kerX;
	conv2D(src, kernelX, src_kerX, ddepth, anchor, borderType);   // 输入矩阵与水平方向上的卷积核的卷积
	conv2D(src_kerX, kernelY, src_kerX_kerY, ddepth, anchor, borderType);  // 把从上面得到的卷积结果和垂直方向上的卷积核卷积
}
Mat sobel(Mat& image, int x_flag, int y_flag, int winSize, int borderType)
{
	// sobel函数用来完成图像灰度矩阵与sobel核的卷积 
	CV_Assert(winSize >= 3 && winSize % 2 == 1);   // sobel卷积核的窗口大小为大于3的奇数
	Mat pascalSmooth = getPascalSmooth(winSize);   // sobel平滑算子
	Mat pascalDiff = getPascalSmooth(winSize);     // sobel差分算子
	Mat image_con_sobel;                           // 输出矩阵
	if (x_flag != 0)
	{
		sepConv2D_Y_X(image, image_con_sobel, CV_32FC1, pascalSmooth.t(), pascalDiff, Point(-1, -1), borderType);     //先进行一维垂直方向上的平滑,再进行一维水平方向上的差分,即图像与sobel_x进行卷积运算
	}
	if (x_flag == 0 && y_flag != 0)
	{
		sepConv2D_X_Y(image, image_con_sobel, CV_32FC1, pascalSmooth, pascalDiff.t(), Point(-1, -1), borderType);    //先进行一维水平方向上的平滑,再进行一维垂直方向上的差分,即图像与sobel_y进行卷积运算
	}
	return  image_con_sobel;
}
/********************************************************************************************************************/
//  主函数
int main()
{
	const Mat src_img = imread("iron.jpg");
	if (src_img.empty())
	{
		printf("could not load image...\n");
		return -1;
	}
	imshow("原图:", src_img);
	// 将彩色图转化为灰度图,调用OpenCV提供的cvtColor接口
	Mat gray_img;
	cvtColor(src_img, gray_img, 2);
	imshow("灰度图", gray_img);
	// 用sobel算子计算度图像的水平和垂直方向上的差分
	Mat image_con_sobel_Ix, image_con_sobel_Iy;
	image_con_sobel_Ix = sobel(gray_img, 1, 0, 3, BORDER_DEFAULT);
	image_con_sobel_Iy = sobel(gray_img, 0, 1, 3, BORDER_DEFAULT);
	//  水平方向和垂直方向上的边缘强度
	// 数据类型转换,边缘强度的灰度级显示
	Mat scale_sobel_Ix, scale_sobel_Iy;
	convertScaleAbs(image_con_sobel_Ix, scale_sobel_Ix);              //  转化为8位灰度级显示
	convertScaleAbs(image_con_sobel_Iy, scale_sobel_Iy);
	imshow("垂直方向的边缘", scale_sobel_Ix);
	imshow("水平方向的边缘", scale_sobel_Iy);
	waitKey(0);
	return 0;
}

This snippet took 0.01 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).