OpenCV基础API函数一
OpenCV基础API函数二
OpenCV基础API函数三
OpenCV基础API函数四
OpenCV基础API函数五
GaussianBlur 高斯模糊
void GaussianBlur( InputArray src, OutputArray dst, Size ksize,
double sigmaX, double sigmaY = 0,
int borderType = BORDER_DEFAULT );
返回值: 空
src:原图像
dst: 结果图像
ksize:模糊窗口的大小
sigmaX: X轴方向的卷积核标准差
sigmaY: Y轴方向的卷积核标准差,默认为零表示X=Y,当sigmaX,sigmaY同时为零的时候会从ksize中进行推算出sigmaX,sigmaY,
borderType: 边界处理方式
例子:利用你高斯模糊处理图片
void Demo::Gaussian_Blur(Mat &src){
Mat dst;
GaussianBlur(src, dst, Size(17, 17), 3);
imshow("高斯模糊", dst);
GaussianBlur(src, dst, Size(17, 17), 13);
//ksize或sigmaX,sigmaY越大模糊程度越大
imshow("高斯模糊1", dst);
}
bilateralFilter 双边模糊–美颜效果
void bilateralFilter( InputArray src, OutputArray dst, int d,
double sigmaColor, double sigmaSpace,
int borderType = BORDER_DEFAULT );
返回值:空
src:输入的原图像
dst:结果图像
d: 模糊的窗口的大小,如果为零 则从sigmaSpace中计算得出
sigmaColor:颜色控件的卷积核标准差
sigmaSpace:xy空间上面的卷积和标准差,当d>0不考虑sigmaSpace的大小
borderType :边界处理的模式
例子: 利用双边模糊对任务进行美颜
void Demo::mybilateralFilter(Mat &src){
Mat dst;
//双边模糊
bilateralFilter(src,dst,0,100,10);
imshow("高斯双边模糊1", dst);
}
相对于高斯模糊和均值模糊双边模糊有一个更大的优点,就是他能够保留图片中的边界 而不会把边界进行模糊从而达到美颜的效果
blur 卷积模糊
void blur( InputArray src, OutputArray dst,
Size ksize, Point anchor = Point(-1,-1),
int borderType = BORDER_DEFAULT );
返回值: 空
src:输入的圆图像
dst: 输出的结果图像
ksize: 卷积核的大小
anchor:卷积核的锚定点(中心点)
borderType: 边界处理模式
例子 对图像进行模糊
Mat dst;
blur(src, dst, Size(9, 9));
imshow("卷积模糊", dst);
copyMakeBorder 边界处理
void copyMakeBorder(InputArray src, OutputArray dst,
int top, int bottom, int left, int right,
int borderType, const Scalar& value = Scalar() );
返回值:空
src 输入的原图像
dst:输出的结果图像
top:插入顶边界的宽
bottom:插入底边界的宽
left:插入左边界的宽
right:插入右边界的宽
borderType:边界处理的方法
Scalar:颜色值
borderType | 意思 |
---|---|
BORDER_CONSTANT | 对边界指定一个常数 |
BORDER_REPLICATE | 复制图形边上的一个像素填充到边界上 aaaaaa |a bcdefgh |hhhhhhh |
BORDER_REFLECT | 边界对图像进行映射 fedcba|abcdefgh|hgfedcb |
BORDER_WRAP | 左右上下颠倒 把底边的像素填充到上边界,把上边的像素填充到地辩解 cdefgh |
BORDER_REFLECT_101 | gfedcb |abcdefgh| gfedcba |
由以上图骗我们可以看出各个方法区别所在
void Demo::myBlury(Mat &src){
Mat dst;
copyMakeBorder(src,dst,16,16,16,16,BORDER_CONSTANT,Scalar(0,0,255) );
namedWindow("BORDER_CONSTANT", WINDOW_FREERATIO);
imshow("BORDER_CONSTANT", dst);
copyMakeBorder(src,dst,16,16,16,16,BORDER_REPLICATE );
namedWindow("BORDER_REPLICATE", WINDOW_FREERATIO);
imshow("BORDER_REPLICATE", dst);
copyMakeBorder(src,dst,16,16,16,16,BORDER_REFLECT );
namedWindow("BORDER_REFLECT", WINDOW_FREERATIO);
imshow("BORDER_REFLECT", dst);
copyMakeBorder(src,dst,16,16,16,16,BORDER_WRAP );
namedWindow("BORDER_WRAP", WINDOW_FREERATIO);
imshow("BORDER_WRAP", dst);
copyMakeBorder(src,dst,16,16,16,16,BORDER_REFLECT_101 );
namedWindow("BORDER_REFLECT_101", WINDOW_FREERATIO);
imshow("BORDER_REFLECT_101", dst);
//blur(src, dst, Size(9, 9));
// imshow("BORDER_CONSTANT ", dst);
}
LUT 颜色查找表—添加滤镜
void LUT(InputArray src, InputArray lut, OutputArray dst);
返回值:空
src:原图像
lut:颜色查找表大小为(256,1)的Mat数组
dst:结果图像
例子:给一个图片添加一个滤镜
我们用到的颜色条
void Demo::myLut(Mat &src,Mat &src1){
Mat dst;
cout << src.cols << endl;
Mat myLut = Mat::zeros(256, 1, CV_8UC3);
// 填充颜色对照表
for (int i = 0; i < 256; ++i)
{
myLut.at<Vec3b>(i, 0) = src1.at<Vec3b>(10, i);
}
//给原图像替换颜色对照表
LUT(src, myLut, dst);
namedWindow("添加滤镜",WINDOW_FREERATIO);
imshow("添加滤镜", dst);
}
颜色查找表的意思就是我们首先建立一张颜色对照表,灰度从0~255,然后我们的图片根据这张表格进行进行替换颜色
filter2D 自定义滤波器
void filter2D( InputArray src, OutputArray dst, int ddepth,
InputArray kernel, Point anchor = Point(-1,-1),
double delta = 0, int borderType = BORDER_DEFAULT );
返回值:空
src:输入原图像
dst:输出结果图像
ddepth:图像的深度不同的卷积核图像的深度是不同的,-1表示和src的深度一样,当卷积核为小数是,深度为CV_32F,当卷积核为整数时深度为CV_32S
kernel:卷积核
anchor:卷积核的锚定点
dalta:当图像太暗是,添加他增加亮度
norderType:边界填充模式
例子:利用自定义滤波器模糊图像
void customFilter(Mat &src){
Mat dst;
//自定义卷积核
Mat kernel=Mat::ones(15,15,CV_32F);
//滤波函数
filter2D(src, dst, CV_32S, kernel, Point(-1, -1), 127, BORDER_DEFAULT);
namedWindow("模糊",WINDOW_FREERATIO);
imshow("模糊", dst);
}
robot 梯度
robot梯度需要我们自定义算子,同时还需要我们利用自定义滤波器进行计算
例子:对一张图片执行robot算子
我们发现梯度可以很好的发先我的图片里面的边缘
void Demo::myCustomGrad(Mat &src)
{
Mat dst;
Mat dst_x, dst_y;
//X轴方向的算子
Mat robot_x=(Mat_<int>(2, 2) << 1,0,0,-1);
//Y轴方向的算子
Mat robot_y=(Mat_<int>(2, 2) << 0,1,-1,0);
//我们对图像结果增加127是因为我们robot图像结果太暗
filter2D(src, dst_x, CV_32F, robot_x,Point(-1,-1),127);
filter2D(src, dst_y, CV_32F, robot_y,Point(-1,-1),127);
//执行算子过会我们图像的灰度值在[-255,255]范围之间所以需要对灰度值取绝对值
convertScaleAbs(dst_x, dst_x);
convertScaleAbs(dst_y, dst_y);
//为了放置放置图片相加之后图片发白我们采取addWighted方式进行相加
addWeighted(dst_x,0.5,dst_y,0.5,0,dst);
namedWindow("robot-输出", WINDOW_FREERATIO);
imshow("robot-输出", dst);
}
Sobel 梯度
void Sobel( InputArray src, OutputArray dst, int ddepth,
int dx, int dy, int ksize = 3,
double scale = 1, double delta = 0,
int borderType = BORDER_DEFAULT );
返回值:空
src:输入的图像
dst:输出的图像
ddpth:图像的深度,绝对不允许为8位的深度 需要CV_32F
dx:执行X轴方向的算子
dy:执行Y轴方向的算子,ds,dy同时只能有一个为1另一个为0
ksize:卷积窗口大小
scal:伸缩比例因子,正常情况下我们不应用伸缩比例因子
dalta:是否给结果图像增加亮度
borderType:边界填充方式
索贝尔梯度算子在opencv中已经集成好了,所以我们直接调用API函数
例子:执索贝尔算子
通过对比robot算子可以发现,Sobel算子发现边缘的能力更强
void Demo::myCustomGrad(Mat &src)
{
Mat dst;
Mat dst_x, dst_y;
Sobel(src, dst_x, CV_32F, 1, 0);
Sobel(src, dst_y, CV_32F, 0, 1);
convertScaleAbs(dst_x, dst_x);
convertScaleAbs(dst_y, dst_y);
addWeighted(dst_x,0.5,dst_y,0.5,0,dst);
namedWindow("Sobel-输出", WINDOW_FREERATIO);
imshow("Sobel-输出", dst);
Scharr 梯度
void Scharr( InputArray src, OutputArray dst, int ddepth,
int dx, int dy, double scale = 1, double delta = 0,
int borderType = BORDER_DEFAULT );
Scharr的参数意思和Sobel完全一样
例子: 执行Scharr算子
Scharr算子发现图像边缘的能力大于Sobel
void Demo::myCustomGrad(Mat &src)
{
Mat dst;
Mat dst_x, dst_y;
Scharr(src, dst_x, CV_32F, 1, 0);
Scharr(src, dst_y, CV_32F, 0, 1);
convertScaleAbs(dst_x, dst_x);
convertScaleAbs(dst_y, dst_y);
addWeighted(dst_x,0.5,dst_y,0.5,0,dst);
namedWindow("Scharr-输出", WINDOW_FREERATIO);
imshow("Scharr-输出", dst);
}
Laplacian 拉普拉斯梯度
void Laplacian( InputArray src, OutputArray dst, int ddepth,
int ksize = 1, double scale = 1, double delta = 0,
int borderType = BORDER_DEFAULT );
返回值:空
src:输入原图像
dst:输出结果图像
ddepth:输出结果图像的深度 -1表示和src的深度一样,但是应该使用CV_32F类型的深度
ksize:卷积核的窗口大小
scale:缩放比例因子
delta:结果图像增加的值
borderType:边界填充方式
拉普拉斯算子发线边缘的能力大于Scharr算子
例子:执行laplacian算子
void Demo::myCustomGrad(Mat &src)
{
Mat dst;
Laplacian(src, dst, -1,3);
namedWindow("Laplacian-输出", WINDOW_FREERATIO);
imshow("Laplacian-输出", dst);
}
消除美颜 - - - 拉普拉斯锐化
例子:执行锐化算子—消除美颜
void Demo::myCustomGrad(Mat &src)
{
Mat dst;
//拉普拉斯锐化算子
Mat kernel=(Mat_<int>(3,3) <<
0,-1,0,
-1,5-1,
0,-1,0);
filter2D(src, dst, CV_32F, kernel, Point(-1, -1));
convertScaleAbs(dst,dst);
namedWindow("Laplacian锐化-输出", WINDOW_FREERATIO);
imshow("Laplacian锐化-输出", dst);
}
随机产生椒盐噪声
无API
椒盐噪声是一种在图像中随机出现的黑白像素点要么是(0,0,0)要么是(255,255,255),去除椒盐噪声我们可以使用中值滤波
例子:随机创建2W个椒盐噪声
void creatNoise(Mat &src){
//产生随机数种子
srand(time(NULL));
int row = src.rows;
int col=src.cols;
//产生2W个噪声点
for (int i = 0; i < 20000; ++i)
{
//获取随机位置
int r = rand() % row;
int c = rand() % col;
//若取余为零则产生黑点否则为白点
if (i % 2 == 0)
{
src.at<Vec3b>(r, c)=Vec3b(0,0,0);
}
else{
src.at<Vec3b>(r, c)=Vec3b(255,255,255);
}
}
namedWindow("椒盐噪声", WINDOW_FREERATIO);
imshow("椒盐噪声", src);
}
创建高斯噪声
randn: 利用均值和标准差向矩阵中填充正态分布随机数---生成随机图像
void randn(InputOutputArray dst, InputArray mean, InputArray stddev);
返回值:空
mean:平均值
stddev:标准差
例子:产生高斯噪声
void Demo::creatNoise(Mat &src)
{
//生成的噪声图像和原图像大小类型相同
Mat gaussianNoise = Mat::zeros(src.size(), src.type());
//产生随机数矩阵,利用提供的均值和方差进行生成矩阵
randn(gaussianNoise, Scalar(25, 25, 25), Scalar(50, 50, 50));
namedWindow("随机高斯噪声", WINDOW_FREERATIO);
imshow("随机高斯噪声", gaussianNoise);
addWeighted(src, 1, gaussianNoise, 1, 0, src);
namedWindow("高斯噪声", WINDOW_FREERATIO);
imshow("高斯噪声", src);
}
medianBlur 中值滤波—消除椒盐噪声
void medianBlur( InputArray src, OutputArray dst, int ksize );
返回值:空
src:输出图像
dst:输出图像
ksize:卷积核窗口大小---基本上为奇数
中值滤波: 是一种排序滤波; 首先对卷积核窗口内的像素进行排序选择中值填充到窗口中心位置
例子:去除椒盐噪声
// 产生随机数种子
Mat dst;
srand(time(NULL));
int row = src.rows;
int col=src.cols;
//产生2W个噪声点
for (int i = 0; i < 20000; ++i)
{
//获取随机位置
int r = rand() % row;
int c = rand() % col;
//若取余为零则产生黑点否则为白点
if (i % 2 == 0)
{
src.at<Vec3b>(r, c)=Vec3b(0,0,0);
}
else{
src.at<Vec3b>(r, c)=Vec3b(255,255,255);
}
}
namedWindow("椒盐噪声", WINDOW_FREERATIO);
imshow("椒盐噪声", src);
//中值滤波--去除椒盐噪声
medianBlur(src, dst, 3);
namedWindow("消除椒盐噪声", WINDOW_FREERATIO);
imshow("消除椒盐噪声", dst);
Canny 边缘提取
void Canny( InputArray image, OutputArray edges,
double threshold1, double threshold2,
int apertureSize = 3, bool L2gradient = false );
返回值:空
edges:边缘图像
threshold1:最小阈值
threshold2:最大阈值
apertureSize:Sobel 算子卷积核窗口的大小
L2gradient :是否使二阶导数的梯度
边缘提取规则:
1.首先采用Sobel算子对图像进行模糊
2标记出小于最小阈值的像素`(丢弃)`大于最大阈值的像素`(边界)`和在最大最小阈值中间的像素`(用于连接边缘)`
例子:图像边缘
//tracBar回调函数
void edgesTrackbar(int pos, void *userdata){
Mat dst;
Mat src = *(Mat *) userdata;
Canny(src, dst, pos, pos * 3, 3, true);
imshow("边缘提取", dst);
}
void Demo::myEdges(Mat &src){
namedWindow("边缘提取", WINDOW_FREERATIO);
int value = 20;
createTrackbar("阈值", "边缘提取", &value, 300, edgesTrackbar, &src);
edgesTrackbar(20, &src);
}
OTSU阈值 平均阈值和三角法阈值 二值化
void MyThreshold(Mat &src)
{
Mat dst;
//获取平均值
if (src.channels() >= 3)
{
cvtColor(src, src, COLOR_BGR2GRAY);
}
namedWindow("灰度图像", WINDOW_FREERATIO);
imshow("灰度图像", src);
//平均阈值
Scalar m = mean(src);
cout << "平均值 " << m[0] << endl;
threshold(src, dst, m[0], 255, THRESH_BINARY);
namedWindow("基于平均值 二值图像分割", WINDOW_FREERATIO);
imshow("基于平均值 二值图像分割", dst);
double T = 0;
//otsu全局阈值
T = threshold(src, dst, 0, 255, THRESH_BINARY | THRESH_OTSU);
namedWindow("基于OTSU 二值图像分割", WINDOW_FREERATIO);
imshow("基于OTSU 二值图像分割", dst);
cout << "OTSU " << T << endl;
//三角法
T = threshold(src, dst, 0, 255, THRESH_BINARY | THRESH_TRIANGLE);
namedWindow("基于三角法 二值图像分割", WINDOW_FREERATIO);
imshow("基于三角法 二值图像分割", dst);
cout << "三角法 " << T << endl;
}
adaptiveThreshold 自适应阈值二值化
自适应阈值二值化比较适合处理光照不均的图片
void adaptiveThreshold( InputArray src, OutputArray dst,
double maxValue, int adaptiveMethod,
int thresholdType, int blockSize, double C );
返回值:空
src:输入灰度图像
dst:结果图像
maxValue:二值图像的最大值
adaptiveMethod:自适应阈值算法 包括高斯算法,均值算法
thresholdType:二值化算法
blockSize:自适应阈值的窗口大小
C:加权的常数
例子:二值化图像
void adaptiveThresholdMonth(int pos,void *use)
{
Mat dst;
Mat src = *(Mat *) use;
if(src.channels()>=3)
{
cvtColor(src, src, COLOR_BGR2GRAY);
}
adaptiveThreshold(src, dst, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 5, pos);
imshow("自适应阈值", dst);
}
void Demo::YadapterThreshold(Mat &src){
namedWindow("自适应阈值", WINDOW_FREERATIO);
int value = 10;
createTrackbar("增量", "自适应阈值", &value, 80, adaptiveThresholdMonth, &src);
adaptiveThresholdMonth(value, &src);
}