您现在的位置是:首页 >技术教程 >opencv_c++学习(十五)网站首页技术教程
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;
}