阈值化
简易阈值化函数说明
选定一个阈值,可以对原图像各个像素点与阈值相比较,作出判断。
double threshold( InputArray src, OutputArray dst,
double thresh, //阈值
double maxval, //目标最大像素设置值
int type //阈值化输出模式
);
参数src:
1. 常为灰度图.使用cvtColor(src,gray,CV_RGB2GRAY);可转换为灰度图
2. 如果为三通道图片,需要先分通道再处理。使用
a. vector<Mat> mv;
b. split(src,mv); //mv[0]为b通道 mv[1]为g mv[2]为r通道
c. r.create(src.size(),CV_8UC1);
d. mv[2].copyTo(r); //即可获得r通道
参数thresh:
依据实际情况设定,也可以使用bar随机设定。
参数maxval:
阈值化后设置的目标图像最大像素值。
参数type:
阈值化输出图像模式。可选参数为
THRESH_BINARY=CV_THRESH_BINARY, //二值阈值化 dst=(src>T)?m:0
THRESH_BINARY_INV=CV_THRESH_BINARY_INV,//dst=(src>T)?0:M
THRESH_TRUNC=CV_THRESH_TRUNC, //截断阈值化 dst=(src>T)?M:src
THRESH_TOZERO=CV_THRESH_TOZERO,//低阈值化 dst=(src>T)?src:0
THRESH_TOZERO_INV=CV_THRESH_TOZERO_INV,//高阈值化 (src>T)?0:src
THRESH_OTSU=CV_THRESH_OTSU //最大类间方差法 通过方差的计算来寻找一个合适的灰度级别来划分,该算法可以有效的避免图像亮度和对比度带来的影响. 对于OTSU法,因为是对图像的灰度级进行聚类,在执行该算法之前,需要计算图像的灰度直方图。
代码
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/types_c.h>
#include <iostream>
#include <opencv.hpp>
using namespace cv;
using namespace std;
void onBarChange(int,void*); //bar的回调函数
Mat src, src_gray;
Mat src_r,src_g,src_b;
vector<Mat> mv; //用于存储分割的三通道图片
int th_gray,th_r,th_g,th_b; //bar值记录
int main()
{
namedWindow("src");
namedWindow("gray");
namedWindow("r");
namedWindow("g");
namedWindow("b");
src = imread("H:\\cat.jpg");
cvtColor(src,src_gray,CV_RGB2GRAY); //转为灰度图
src_r.create(src.size(),CV_8UC1);
src_g.create(src.size(),CV_8UC1);
src_b.create(src.size(),CV_8UC1);
split(src,mv); //将三通道图片分割为单通道
mv[0].copyTo(src_b);
mv[1].copyTo(src_g);
mv[2].copyTo(src_r);
createTrackbar("gray","src",&th_gray,255,onBarChange); //添加bar 最大值设置为255
createTrackbar("r","src",&th_r,255,onBarChange);
createTrackbar("g","src",&th_g,255,onBarChange);
createTrackbar("b","src",&th_b,255,onBarChange);
waitKey(0);
return 0;
}
void onBarChange(int,void*)
{
Mat r,g,b,gray;
//阈值化操作 模式为二值阈值化
threshold(src_gray,gray,th_gray,255,THRESH_BINARY);
threshold(src_r,r,th_r,255,THRESH_BINARY);
threshold(src_g,g,th_g,255,THRESH_BINARY);
threshold(src_b,b,th_b,255,THRESH_BINARY);
imshow("src",src);
imshow("gray",gray);
imshow("r",r);
imshow("g",g);
imshow("b",b);
}
自适应阈值
针对有很强照明或反射梯度的图像,需要根据梯度进行阈值化时,自适应阈值很有用.
void adaptiveThreshold( InputArray src, OutputArray dst,
double maxValue, //目标图像最大像素值
int adaptiveMethod, //自适应模式
int thresholdType, //阈值化模式
int blockSize, //自适应区域大小
double C //自适应常数
);
自适应阈值化有两种模式:
由参数adaptiveMethod指定.
ADAPTIVE_THRESH_MEAN_C=0, //自适应阈值T在每个像素点都不同,通过计算像素点周围的bxb(blockSize指定b)区域的加权平均,减去一个常数(c指定)得到自适应阈值。
ADAPTIVE_THRESH_GAUSSIAN_C=1 //在计算加权平均时候,在(x,y)周围的像素点依据高斯函数按照它们离中心点的距离进行加权计算。
----------
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/types_c.h>
#include <iostream>
#include <opencv.hpp>
using namespace cv;
using namespace std;
void onBarChange(int,void*); //bar的回调函数
Mat src,gray;
Mat th,th_adapter;
int thre;
int main()
{
src = imread("H:\\adapter.jpg");
cvtColor(src,gray,CV_RGB2GRAY);
namedWindow("src",0);
namedWindow("th",0);
namedWindow("adapter",0);
imshow("src",src);
createTrackbar("th","src",&thre,100,onBarChange);
adaptiveThreshold(gray,th_adapter,255,ADAPTIVE_THRESH_MEAN_C,THRESH_BINARY,3,5);
imshow("adapter",th_adapter);
waitKey(0);
return 0;
}
void onBarChange(int,void*)
{
threshold(gray,th,thre,255,THRESH_BINARY);
imshow("th",th);
}
还有一些其他阈值方法,例如迭代法,最大熵。
常用滤波算法
线性滤波器(领域滤波)
**低通滤波器 --> 模糊处理**
**高通滤波器 --> 锐化处理**
- 方框滤波
`void boxFilter( InputArray src,
OutputArray dst,//目标图像大小应该和原图一致
int ddepth, //输出图像深度 -1为保持原图
Size ksize, //内核大小
Point anchor=Point(-1,-1), //内核中心点
bool normalize=true, //内核是否归一化
int borderType=BORDER_DEFAULT //边界填充
);`
参数ksize:
Size(m,n)即表示mxn的矩阵核
参数normalize:
归一化就是把处理的数据放缩到给定范围,例如把(0,30)归一化即缩小了30倍.归一化后便于直观处理。
当为true时,方框滤波就是均值滤波。
为false时,即计算周围领域的总和。
- 均值滤波
void blur( InputArray src, OutputArray dst,
Size ksize,
Point anchor=Point(-1,-1),
int borderType=BORDER_DEFAULT
);
- 高斯滤波
图像与高斯分布(正态分布)做卷积操作。可以有效的抑制服从正态分布的噪声。
高斯滤波认为图像在空间内的像素是缓慢变化的,在邻近点像素变化时不明显的。可以很好的抑制噪声点的影响。
(一般情况下,我们不希望滤波处理影响到图像的边缘,但是高斯滤波会磨平边缘,达不到想要的结果,这种情况下可以使用"双边滤波算法")
void GaussianBlur( InputArray src,OutputArray dst,
Size ksize,
double sigmaX,
double sigmaY=0,
int borderType=BORDER_DEFAULT
);
参数ksize:
高斯内核的大小,例如Size(m,n)即代表mxn的高斯核.也可以为0,如果为0则由sigmaX和sigmaY计算。
参数sigmaX,sigmaY:
高斯函数在X,Y方向的标准偏差。如果两个值为0的话,则由ksize参数计算(size,x,y不能同时为0)。
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/types_c.h>
#include <iostream>
#include <opencv.hpp>
using namespace cv;
using namespace std;
Mat src,dst_box,dst_blur,dst_guassian;
int main()
{
src = imread("H:\\cat.jpg");
boxFilter(src,dst_box,-1,Size(3,3),Point(-1,-1),false); //不归一化处理
blur(src,dst_blur,Size(5,5)); //均值滤波
GaussianBlur(src,dst_guassian,Size(3,3),0,0,4); //3阶高斯核
namedWindow("src");
namedWindow("box");
namedWindow("blur");
namedWindow("guassians");
imshow("src",src);
imshow("box",dst_box);
imshow("blur",dst_blur);
imshow("guassians",dst_guassian);
waitKey(0);
return 0;
}
非线性滤波器
- 中值滤波
中值滤波器将中心像素的正方形领域内的每个像素值用中间像素值(需要对正方形每个像素值排序)替换。
中值滤波对噪声抑制很有效(噪声点很难入选).但是因为需要做排序操作,故花费时间和资源会更多.
void medianBlur( InputArray src, OutputArray dst,
int ksize
);
参数ksize:
必须是大于1的奇数。3,5,7……
- 双边滤波
双边滤波和高斯滤波相似,会依据每个像素及其邻域构成一个加权平均值,加权分为两个部分.
1.与高斯滤波相似,选定高斯sigma区域
2.选定一个加权值,参考下面sigmaColor参数介绍,利用邻域值的亮度差值来均衡边缘效应。
void bilateralFilter( InputArray src, OutputArray dst,
int d, //滤波像素点直径
double sigmaColor, //颜色控制sigma
double sigmaSpace,
int borderType=BORDER_DEFAULT
);
参数d:
滤波过程中,像素点的邻域直径。该值越大就会糅合更大的区域颜色。也可以设定该值为0或者负数,通过sigmaSpace参数设定来判定该值。
参数sigmaColor:
高斯加权,基于其他像素与中心像素的亮度差值(各种颜色差值)的加权。该值越大,就有更宽广的邻域颜色会被融合进来。
参数sigmaSpace:
该值越大,参与滤波的邻域就越大,当d大于的情况下,该值不起作用。否则邻域正比与该值。
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/types_c.h>
#include <iostream>
#include <opencv.hpp>
using namespace cv;
using namespace std;
Mat src,dst_med,dst_bin;
int main()
{
src = imread("H:\\cat.jpg");
medianBlur(src,dst_med,3); //邻域为3的中值滤波
bilateralFilter(src,dst_bin,20,20*2,20);//半径为10 颜色为40
namedWindow("src");
namedWindow("med");
namedWindow("bin");
imshow("src",src);
imshow("med",dst_med);
imshow("bin",dst_bin);
waitKey(0);
return 0;
}