在之前我们都是把图像当作图像数组进行处理的,而滤波与卷积同样是在图像结构体上根据图像像素之间的联系对之进行高级处理。而非将图像当作一个整体进行颠倒,切割等操作。
所谓滤波器,可以简单理解为对图像的每一个像素点(锚点)及其附近的点进行卷积,而所谓卷积,就是以一个特定大小的核(比如5*5)对原像素值进行乘积,而对整幅图像进行滤波操作,便会得到一个新的图像。
我们在对一幅图像进行完一些基本处理之后,可能希望可以将高于某一个像素值的像素点置为零或某一定值,而其他像素值不变等等类似的操作,这就是设定阈值。
cv::threshold(
cv::InputArray src,
cv::OutputArray dst,
double thresh,
double maxValue,
int thresholdType
);
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src,dst;
src = imread("1.jpg",0);
imshow("原图", src);
threshold(src,dst,40,255,0);
imshow("阈值化操作", dst);
waitKey(0);
return 0;
}
除了自己设置阈值,还可以使用自适应阈值操作函数adaptiveThreshold(),在这个函数中,阈值可以自己产生:
cv::adaptiveThreshold(
cv::InputArray src, //输入图像
cv::OutputArray dst, //输出图像
double maxValue, //当thresholdType参数为THRESH_BINARY或者THRESH_BINARY_INV时的最大值
int adaptiveMethod,//自适应阈值算法方法,有两种:ADAPTIVE_THRESH_MEAN_C或者ADAPTIVE_THRESH_GAUSSIAN_C
int thresholdType,//取阈值类型,THRESH_BINARY或者THRESH_BINARY_INV
int blockSize, //用来计算阈值的像素邻域大小:3,5,7...
double C //可调参数
);
该函数一些参数和上面的阈值函数是一样的,下面我们写个程序读取一张单通道图像,再对其进行阈值化操作和自适应阈值操作,来看看二者的区别:
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src,dst1,dst2;
src = imread("1.jpg",0); //读入一张图像
imshow("原图", src); //显示该图像
//阈值化操作,取阈值类型为二值化阈值操作
threshold(src, dst1,40,255,0);
imshow("阈值化操作", dst1);
//自适应阈值,取阈值类型为反二值化操作
adaptiveThreshold(src, dst2, 255, ADAPTIVE_THRESH_MEAN_C, 1, 3, 10);
imshow("自适应阈值化操作", dst2);
waitKey(0);
return 0;
}
运行效果图:
中间一幅为自适应阈值处理后的图像,可以看到效果还是比较不错的。
平滑也称“模糊”,是一种简单而又常用的图像处理操作。平滑图像目的很多,例如降低噪声或伪影。
#图像平滑化//滤波操作:
消除图像中的噪声成分叫做图像的平滑化或滤波操作:信号和图像的能量大多计征再幅度谱的低频和中频,而在高频区有用信息往往被噪声掩盖,降低高频成分幅度就可以起到降噪的功能。
图像滤波目的有两个:一个是抽出对象的特征作为图像识别的特征模式,另一个是为适应图像处理的要求,消除图像数字化时混入的噪声。
#平滑滤波:
平滑滤波是低频增强的空间滤波技术,它的目的有两类:一类是模糊,一类是消除噪声。
关于滤波器,滤波器时我们实现上述功能的工具,opencv中提供了物种常用的滤波器:
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src,dst1,dst2,dst3;
src = imread("2.jpg", 1);
blur(src, dst1, Size(5, 5)); //均值滤波
boxFilter(src, dst2, src.depth(), Size(5, 5)); //方框滤波
GaussianBlur(src, dst3, Size(5, 5), 0, 0); //高斯滤波
imshow("原图", src);
imshow("均值滤波", dst1);
imshow("方框滤波", dst2);
imshow("高斯滤波", dst3);
waitKey(0);
return 0;
}
最基础的形态学操作就是腐蚀和膨胀,他们在消除噪声,元素分割以及连接等方面有广泛应用。
膨胀是一种卷积操作,它将目标像素值替换为卷积核覆盖区域的局部最大值。图中黑色区域并不是黑色像素点,而是表示高亮部分。
与膨胀对应,腐蚀是与之相反的操作,它是计算核覆盖区域内的局部最小值,如图:
简单来说,膨胀就是扩大白色(高亮)像素,腐蚀就是扩大黑色像素;另外,膨胀填充凹面,腐蚀消除突起。下面是函数实现:
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat src, dst1, dst2;
src = imread("3.jpg", 1);
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5)); //定义核大小
erode(src, dst1, element); //腐蚀操作
dilate(src, dst2, element); //膨胀操作
imshow("原图", src);
imshow("腐蚀", dst1);
imshow("膨胀", dst2);
waitKey(0);
return 0;
}
在上面代码中,我们看到里面有一行
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5)); //自定义核大小
这是自定义一个5*5大小的核,用到函数getStructuringElement();
cv::getStructuringElement(
int shape, #生成核的形状
cv::Size ksize, #生成核的大小
cv::Point anchor = cv::Point(-1,-1) #默认锚点在元素中心
);
#第一个参数:
MORPH_RECT 矩形
MORPH_ELLIPSE 椭圆形
MORPH_CROSS 交叉形
当处理的对象是二值图像和像素只可能是开(>0)或关(=0)的图像腌膜时,基本的腐蚀和膨胀操作就够了,需要对灰度图或者彩色图进行处理时,一些其他的操作就非常有用,这些操作可以通过cv::morphologyEx()实现:
是否需要临时图像
cv::MOP_OPEN 开操作 否
cv::MOP_CLOSE 闭操作 否
cv::MOP_GRADIENT 形态学梯度 总是需要
cv::MOP_TOPHAT 顶帽操作 就地调用需要(src=dst)
cv::MOP_BLACKHAT 低帽操作 就地调用需要(src=dst)
dst = open(src,element) = dilate(erode(src,element),element);
开操作是对图像先腐蚀,再对腐蚀的图像进行膨胀的操作
dst = close(src,element) = erode(dilate(src,element),element);
闭操作是对图像先膨胀,再对膨胀后的图像进行腐蚀的操作
dst = morph_grad(src) = dilate(src) - erode(src) ;
形态学梯度就是膨胀操作的结果减腐蚀操作的结果,得到原图像的边缘;
dst = tophat(src) = src - open(src) ;
顶帽操作显示与邻域相比更亮的部分。可以提取图像中的明亮局部
dst = blackhat(src) = close(src) - src ;
黑帽操作显示与邻域相比更暗的部分。可以提取图像中的暗洞