您现在的位置是:首页 >技术教程 >opencv_c++学习(十五)网站首页技术教程

opencv_c++学习(十五)

小小小~ 2024-06-17 11:26:28
简介opencv_c++学习(十五)

一、图像的模板匹配

在这里插入图片描述
顾名思义,模板匹配是在一幅图像中寻找一个相同或相似的对象,如上图所示。

matchTemplate(lnputArray image, lnputArray templ,OutputArray result, int method, lnputArray mask = noArray())

image:待模板匹配的原图像,图像数据类型为CV_8U和CV_32F两者中的一个。
templ:模板图像,需要与image具有相同的数据类型,但是尺寸不能大于image。
result:模板匹配结果输出图像,图像数据类型为CV_32F。如果image的尺寸为W×H,模板图像尺寸为w×h,则输出图像的尺寸为(W-w+1)×(H-h+1) 。
method:模板匹配方法标志。
mask:匹配模板的掩码,必须与模板图像具有相同的数据类型和尺寸,默认情况下不设置,目前仅支持在TM_SQDIFF和ITM_CCORR_NORMED这两种匹配方法时使用。
在这里插入图片描述
使用案例:

int main() {

	//读取图片
	Mat src = imread("1.png");
	Mat src1 = imread("2.png");
	if (src.empty() || src1.empty())
	{
		printf("不能打开空图片");
		return -1;
	}


	//定义要保存结果的Mat类
	Mat result;

	//开始模板匹配
	matchTemplate(src, src1, result, TM_CCOEFF_NORMED);

	//定义存放最大值最小值的变量
	double maxVal, minVal;
	Point maxLoc, minLoc;

	//寻找最大值最小值
	minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);

	//在图像中找到最大值的区域
	rectangle(src, Point(maxLoc.x, maxLoc.y), Point(maxLoc.x + src1.cols, maxLoc.y + src1.rows), Scalar(0, 0, 255), 2);

	imshow("结果", result);
	imshow("框", src);

	waitKey(0);
	return 0;
}

二、图像卷积

在这里插入图片描述

filter2D(InputArray src, OutputArray dst,int ddepth, lnputArray kernel,Point anchor = Point(-1,-1), double delta = e, int borderType = BORDER_DEFAULT)

src:输入图像。
dst:输出图像,与输入图像具有相同的尺寸和通道数。
ddepth:输出图像的数据类型(深度),根据输入图像的数据类型不同拥有不同的取值范围。
kernel:卷积核,cV_32FC1类型的矩阵。
anchor:内核的基准点(锚点),默认值(-1,-1)代表内核基准点位于kernel的中心位置。
delta:偏值,在计算结果中加上偏值。
borderType:像素外推法选择标志。
一个小样例:

int main() {

	//待进行卷积的矩阵
	uchar points[25] = { 1,2,3,4,5,
	6,7,8,9,10,
	11,12,13,14,15,
	16,17,18,19,20,
	21,22,23,24,25 };
	Mat img(5, 5, CV_8UC1, points);

	//卷积模板
	Mat kernel = (Mat_<float>(3, 3) << 1, 2, 1, 2, 0, 2, 1, 2, 1);

	//对卷积模板归一化
	Mat Kernel_norm = kernel / 12;


	//未归一化的结果与归一化后的卷积结果
	Mat result, result_norm;

	filter2D(img, result, CV_32F, kernel, Point(-1, -1), 2, BORDER_CONSTANT);
	filter2D(img, result_norm, CV_32F, Kernel_norm, Point(-1, -1), 2, BORDER_CONSTANT);

	cout << result << endl;

	cout << result_norm << endl;

}

对图像卷积的案例:

int main() {

	//卷积模板
	Mat kernel = (Mat_<float>(3, 3) << 1, 2, 1, 2, 0, 2, 1, 2, 1);

	//对卷积模板归一化
	Mat Kernel_norm = kernel / 12;
	
	//读取图片
	Mat src = imread("1.jpg");
	if (src.empty())
	{
		printf("不能打开空图片");
		return -1;
	}

	//对图像进行卷积
	Mat a_filler;
	filter2D(src, a_filler, -1, Kernel_norm, Point(-1, -1), 2, BORDER_CONSTANT);
	imshow("结果", a_filler);

	waitKey(0);
	return 0;
}

三、图像噪声的产生

图像在获取或者传输过程中会受到随机信号的干扰产生噪声。
椒盐噪声:又被称作脉冲噪声,它会随机改变图像中的像素值,是由相机成像、图像传输、解码处理等过程产生的黑白相间的亮暗点噪声。
高斯噪声:高斯噪声是指噪声分布的概率密度函数服从高斯分布(正态分布)的一类噪声。
在这里插入图片描述
椒盐噪声生成的步骤:
Step1:确定添加椒盐噪声的位置。
Step2:确定噪声的种类。
Step3:修改图像像素灰度值。
Step4:得到含有椒盐噪声的图像。

高斯噪声生成的步骤:
Step1:创建一个与图像尺寸、数据类型以及通道数相同的Mat类变量。
Step2:在Mat类变量中产生符合高斯分布的随机数。
Step3:将原图像和含有高斯分布的随机数矩阵相加。
Step4:得到添加高斯噪声的图像。

filly(InputOutputArray mat,int distType, lnputArraya, lnputArray b, bool saturateRange = false)

mat:用于存放随机数的矩阵,目前只支持低于5通道的矩阵。
disnType:随机数分布形式选择标志。
a:确定分布规律的参数。
b:确定分布规律的参数。
saturateRangea:预饱和标志。仅用于均匀分布。

添加噪声的示例如下:

void saltAndPepper(cv::Mat image, int n)
{

	for (int k = 0; k < n/2; k++)
	{
		//随机确定图像中的位置
		int i, j;

		//保证坐标在图像的列数内
		i = std::rand() % image.cols;

		//保证坐标在图像的行数内
		j = std::rand() % image.rows;

		//判断是否为白色噪声还是黑色噪声的变量
		int write_black = std::rand() % 2;

		//添加白色噪声
		if (write_black == 0)
		{
			//处理灰度图像
			if (image.type() == CV_8UC1)
			{
				//添加白色噪声
				image.at<uchar>(j, i) = 255;
			}

			//处理彩色图像
			else if(image.type() == CV_8UC3)
			{
				//cv::Vec3b定义的一个3个值的向量类型。[]指定通道,B:0, G:1, R:2
				image.at<cv::Vec3b>(j, i)[0] = 255;
				image.at<cv::Vec3b>(j, i)[1] = 255;
				image.at<cv::Vec3b>(j, i)[2] = 255;
			}
		}
		else //添加黑色噪声
		{
			//处理灰度图像
			if (image.type() == CV_8UC1)
			{
				//添加白色噪声
				image.at<uchar>(j, i) = 255;
			}

			//处理彩色图像
			else if (image.type() == CV_8UC3)
			{
				//cv::Vec3b定义的一个3个值的向量类型。[]指定通道,B:0, G:1, R:2
				image.at<cv::Vec3b>(j, i)[0] = 0;
				image.at<cv::Vec3b>(j, i)[1] = 0;
				image.at<cv::Vec3b>(j, i)[2] = 0;
			}
		}
	}
}

int main() {

	//读取图片
	Mat src = imread("1.png");
	if (src.empty())
	{
		printf("不能打开空图片");
		return -1;
	}

	Mat src_G;
	src.copyTo(src_G);

//	imshow("src原图", src);

	//添加椒盐噪声
	saltAndPepper(src, 10000);

	imshow("src椒盐噪声", src);

	//添加高斯噪声
	Mat src_noise = Mat::zeros(src.rows, src.cols, src.type());

	imshow("src原图", src);

	RNG rng;

	//生成三通道的高斯分布随机数均值为10,方差为20
	rng.fill(src_noise, RNG::NORMAL, 10, 20);

//	imshow("src高斯噪声", src_noise);

	//与原图像叠加
	src = src + src_noise;

	//显示图像
	imshow("原图", src);

	waitKey(0);
	return 0;
}
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。