(1)线性混合操作(两幅图像按权重相加)
g(x)=(1-a)*f(x)+h(x) 相关API:addweighted()。
a的取值范围为0到1之间,f(x)和h(x)为参与混合的两幅图像,g(x)表示输出图像,通过对两幅图像的每个像素值做线性加权得到最终的输出图像,两幅图像的大小和类型必须完全一致,(如果把图像当成一个矩阵),则两个矩阵相加的前提是维度必须一致,否则没有相加的意义。
- using namespace cv;
- using namespace std;
- int main(int argc, char** args)
- {
- Mat src1, src2, dst;
- src1 = imread("mogu.jpg");
- src2 = imread("rain.jpg");
- if (!src1.data)
- {
- printf("图像加载错误");
- return -1;
- }
- if (!src2.data)
- {
- printf("图像加载错误");
- return -1;
- }
- double alpha = 0.5;//混合权重
- //混合的两幅图像宽高和类型必须完全一致
- if (src1.rows==src2.rows
- &&src1.cols==src2.cols
- &&src1.type()==src2.type())
- {
- addWeighted(src1,alpha,src2,(1.0-alpha),0.0,dst);//线性混合
- //add(src1,src2,dst);//相加
- //multiply(src1,src2,dst);//相乘
- imshow("原图-1", src1);
- imshow("原图-2",src2);
- imshow("混合后的图",dst);
- }
- else{
- printf("两幅图像的大小或者类型不一致,不能混合!");
- return -1;
- }
- waitKey(0);
- return 0;
- }
注意:两幅图像可以相加,相乘。
(2)调整图像的亮度和对比度
一般来说,图像处理算子是带有一幅或多幅输入图像、产生一幅输出图像的函数。
图像变换可分为以下两种:
点算子(像素变换):图像对比度和亮度,等等,主要是对一点进行操作
邻域(基于区域的)算子:均值滤波,中值滤波,等等,也就是卷积运算,一般为整体特征提取,梯度计算,模式匹配,角点检测,模糊,平滑等。
两种常用的点过程(即点算子),是用常数对点进行乘法和加法运算
两个参数 和
一般称作 增益 和 偏置 参数。我们往往用这两个参数来分别控制 对比度 和 亮度 。
你可以把 看成源图像像素,把
看成输出图像像素。这样一来,上面的式子就能写得更清楚些:
其中, 和
表示像素位于 第i行 和 第j列 。
注意其中的几个函数:
Mat::zeros(src.size(),src.type())表示创建一张与原图像大小和类型完全一致的空白图像,像素值初始化为0.
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat src,dst;
src = imread("1.png");
char name[] = "first"; //注意这里定义字符串与python中不同,必须这样写
if (!src.data) {
printf("could not load image..");
return -1;
}
namedWindow(name,CV_WINDOW_AUTOSIZE);
imshow(name,src);
int height = src.rows;
int width = src.cols;
float alpha = 1.2;
float beta = 10;
dst = Mat::zeros(src.size(), src.type());
for (int row = 0; row < height; row++)
{
for (int col = 0; col < width; col++) {
if (src.channels() == 3) {
float b = src.at<Vec3b>(row,col)[0];//这里是读取图像三通道的每个通道的像素值
float g = src.at<Vec3b>(row,col)[1];//若是类型为Ve3f,先需要用convertTo进行图像数据类型的转换
float r = src.at<Vec3b>(row,col)[2];
dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(b*alpha + beta);//不要忘记保证像素在0到255之间
dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(g*alpha + beta);
dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(r*alpha + beta);
}
else if(src.channels() == 1)
{
float v = src.at<uchar>(row, col);
dst.at<uchar>(row, col) = saturate_cast<uchar>(v*alpha + beta);
}
}
}
char name1[] = "second";
namedWindow(name1, CV_WINDOW_AUTOSIZE);
imshow(name, dst);
cvWaitKey(0);
return 0;
}
(3)绘制形状和文字
常用的数据结构有point(生成点),scalar(颜色向量,注意BGR图像读进去后 为b,g,r),可以绘制线(cv::point)、矩形(cv::rectangle)、圆(cv::circle)、椭圆(cv::ellipse),随机生成与绘制文本等
Point p=point(20,30)
p.x=20,p.y=30
(4)图像模糊
图像滤波,即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制,是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。
均值滤波
1. 原理
均值滤波,是最简单的一种滤波操作,输出图像的每一个像素是核窗口内输入图像对应像素的像素的平均值( 所有像素加权系数相等),求完均值后赋值给中间的那个像素。
均值滤波封装在一个名为blur
的函数中
void blur( InputArray src, OutputArray dst,
Size ksize, Point anchor = Point(-1,-1),
int borderType = BORDER_DEFAULT );
均值滤波的核:
![](http://upload-images.jianshu.io/upload_images/1877813-4f6437eb9e5122b5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/484)
2. 缺陷
均值滤波本身存在着固有的缺陷,即它不能很好地保护图像细节,在图像去噪的同时也破坏了图像的细节部分,从而使图像变得模糊,不能很好地去除噪声点,不能去除椒盐噪声。
3. 实例
核心代码
blur(src, dst, Size(10, 10));
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
int main() {
Mat src = imread("../pics/pig.jpg");
namedWindow("原图");
imshow("原图", src);
Mat dst;
// 均值滤波
blur(src, dst, Size(10, 10));
namedWindow("均值滤波");
imshow("均值滤波", dst);
waitKey(0);
}
高斯滤波
1. 原理
从数学的角度来看,图像的高斯模糊过程就是图像与正态分布做卷积,由于正态分布也被称为高斯分布,因此这项技术被称为高斯模糊。
由于高斯函数的傅立叶变换是另外一个高斯函数,所以高斯模糊对于图像来说就是一个低通滤波操作。
具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的 加权平均灰度值 去替代模板中心像素点的值。
高斯滤波器是一类 根据高斯函数的形状来选择权值的线性平滑滤波器。
高斯平滑滤波器对于 抑制服从正态分布的噪声非常有效。
高斯函数的一般形式,其中 a > 0, b, c 为实数
![](http://upload-images.jianshu.io/upload_images/1877813-c64680b28e256ab6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/700)
- μ:平均值,确定图像位置
- σ:标准差,越大图像越分散(矮胖), 越小图像越集中(高瘦)
一维零均值 高斯函数为:
二维零均值 离散高斯函数
![](http://upload-images.jianshu.io/upload_images/1877813-3b851d7d3e3d3d69.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/297)
图像处理来说,常用二维零均值离散高斯函数作平滑滤波器。
高斯滤波封装在一个名为GaussianBlur
的函数中。
void GaussianBlur( InputArray src, OutputArray dst, Size ksize,
double sigmaX, double sigmaY = 0,
int borderType = BORDER_DEFAULT );
Size ksize
ksize.width 和 ksize.height 可以不同,但他们都必须为正数和奇数,或者为0,可由 sigma 计算而来double sigmaX
高斯核函数在X
方向的的标准差double sigmaY
高斯核函数在Y
方向的的标准差
若 sigmaY 为零,就将它设为 sigmaX;
若 sigmaX 和 sigmaY 都是0,那么就由 ksize.width 和 ksize.height 计算出来
3. 实例
核心代码
// 高斯滤波
// sigmaX 和 sigmaY 都是0,就由 ksize.width 和 ksize.height 计算出来
// Size w,h 必须为奇数
GaussianBlur(src, dst, Size(5, 5), 0, 0);
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
int main() {
Mat src = imread("../pics/pig.jpg");
namedWindow("原图");
imshow("原图", src);
Mat dst;
// 高斯滤波
// sigmaX 和 sigmaY 都是0,就由 ksize.width 和 ksize.height 计算出来
// Size w,h 必须为奇数
GaussianBlur(src, dst, Size(5, 5), 0, 0);
namedWindow("高斯滤波");
imshow("高斯滤波", dst);
waitKey(0);
}
中值滤波
首先,我们复习中值。在一连串数字{1,4,6,8,9}中,数字6就是这串数字的中值。由此我们可以应用到图像处理中。依然我们在图像中去3*3的矩阵,里面有9个像素点,我们将9个像素进行排序,最后将这个矩阵的中心点赋值为这九个像素的中值。中值滤波是一个统计排序滤波器,可以很好的抑制椒盐噪声。
void medianBlur(InputArray src, OutputArray dst, int ksize)
- 参数解释:
. InputArray src: 输入图像,图像为1、3、4通道的图像,当模板尺寸为3或5时,图像深度只能为CV_8U、CV_16U、CV_32F中的一个,如而对于较大孔径尺寸的图片,图像深度只能是CV_8U。
. OutputArray dst: 输出图像,尺寸和类型与输入图像一致,可以使用Mat::Clone以原图像为模板来初始化输出图像dst
. int ksize: 滤波模板的尺寸大小,必须是大于1的奇数,如3、5、7……
双边滤波
相对于传统的高斯blur来说很重要的一个特性即可可以保持边缘(Edge Perseving),这个特点对于一些图像模糊来说很有用。一般的高斯模糊在进行采样时主要考虑了像素间的空间距离关系,但是却并没有考虑像素值之间的相似程度,因此这样我们得到的模糊结果通常是整张图片一团模糊。Bilateral blur的改进就在于在采样时不仅考虑像素在空间距离上的关系,同时加入了像素间的相似程度考虑,因而可以保持原始图像的大体分块进而保持边缘。双边滤波后在进行提高图像提高对比度和亮度,效果会非常的好。
双边滤波其实有两个卷积核,一个是空域核,一个是值域核,空域核就是在空间上进行考虑赋值像素值高斯权重,值域核就是在图像的像素相似度上进行考虑,当像素之间差别很大的时候不去处理,而是处在一定的阈值之内的时候,才进行模糊处理。
右边是输入图像,中间的两个卷积核(一个高斯核(考虑空间分布),一个值域核(考虑图像的像素)),左边就是处理后的图像。
- void bilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace,
- int borderType=BORDER_DEFAULT )
第一个和第二个参数是输入输出图像;
第三个参数是空域窗口半径的大小,半径之内的像数都会被纳入计算,如果提供-1,会从后面的参数sigmaSpace中自动计算。
第四个参数是值域信息,像素值在这个范围以内的才会进行计算,否则不予考虑。
第五个参数,d>0,这个参数无效,否则要根据他来计算d值。