在本节我将为大家介绍Opencv的模糊处理与形态学基本操作
1.Smooth/Blur 是图像处理中最简单和常用的操作之一。
2.使用该操作的原因之一就为了给图像预处理时候减低噪声。
3.使用Smooth/Blur操作其背后是数学的卷积计算。
注:h(k,l)称为卷积核或卷积算子。
卷积过程:6x6上面是个3x3的窗口,从左向右,从上向下移动,黄色的每个像个像素点值之和取平均值赋给中心红色像素作为它卷积处理之后新的像素值。每次移动一个像素格。
1.归一化盒子滤波(均值滤波)
将结构元素内的各像素点的均值赋予锚点,从而达到降低对比度,达到滤波降噪目的,卷积算子均为1。
3.中值滤波
特点:
统计排序滤波器。
中值对椒盐噪声有很好的抑制作用。
注:中值滤波将结构元素中像素点的中值像素赋予给锚点。
椒盐噪声:形象比喻,好比一锅白粥里面洒了一些胡椒和盐粒,使得整个图像有那种极大或极小的噪声点。
4.高斯双边滤波
均值模糊无法克服边缘像素信息丢失缺陷。原因是均值滤波是基于平均权重。
高斯模糊部分克服了该缺陷,但是无法完全避免,因为没有考虑像素值的不同。
高斯双边模糊 – 是边缘保留的滤波方法,避免了边缘信息丢失,保留了图像轮廓不变。
高斯双边模糊考虑的结构元素像素点之间的差异,若像素点差异过大,超过规定阈值,则不做模糊操作即添加值域核。若像素点差异未超过规定阈值,则进行模糊操作,考虑空间差异,即添加空域核。空域核和值域核共同组成了高斯双边模糊的卷积核。
1.均值模糊
- blur(Mat src, Mat dst, Size(xradius, yradius), Point(-1,-1));
参数说明:
src:源图像
dst:目标图像
Size(xradius, yradius):结构元素尺寸,为奇数
Point(-1,-1):锚点位置,一般用(-1,-1),表示结构元素中心位置
2.高斯模糊
-GaussianBlur(Mat src, Mat dst, Size(11, 11), sigmax, sigmay);
参数说明:
src:源图像
dst:目标图像
Size(xradius, yradius):结构元素尺寸,为奇数
sigmax, sigmay:影响正态分布函数的取值从而影响卷积算子的取值,可都不输入,则根据size确定取值
其中Size(x, y), x, y 必须是正数而且是奇数
3.中值模糊
medianBlur(Mat src, Mat dest, ksize);
参数说明:
src:源图像
dst:目标图像
ksize:结构元素尺寸,为奇数
中值模糊的ksize大小必须是大于1而且必须是奇数。
4.高斯双边滤波
bilateralFilter(src, dest, d=15, 150, 3);
参数说明:
- 15 –计算的半径,半径之内的像数都会被纳入计算,如果提供-1 则根据sigma space参数取值
- 150 – sigma color 决定多少差值之内的像素会被计算
- 3 – sigma space 如果d的值大于0则声明无效,否则根据它来计算d值
1.均值模糊与高斯模糊
#include
#include
using namespace cv;
int main(int argc, char** argv) {
Mat src, dst;
src = imread("D:/photos/2.jpg");
if (!src.data) {
printf("could not load image...\n");
return -1;
}
char input_title[] = "input image";
char output_title[] = "blur image";
namedWindow(input_title, CV_WINDOW_AUTOSIZE);
namedWindow(output_title, CV_WINDOW_AUTOSIZE);
imshow(input_title, src);
blur(src, dst, Size(11, 11), Point(-1, -1));//均值模糊
imshow(output_title, dst);
Mat gblur;
GaussianBlur(src, gblur, Size(11, 11), 11, 11);//高斯模糊,sigmax,sigay均取11
imshow("gaussian blur", gblur);
waitKey(0);
return 0;
}
运行效果:
2.中值模糊
#include
#include
using namespace cv;
int main(int argc, char** argv) {
Mat src, dst;
src = imread("D:/photos/21.jpg");
if (!src.data) {
printf("could not load image...\n");
return -1;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src);
medianBlur(src, dst, 3);//中值模糊
imshow("medianBlur image", dst);//去椒盐噪声效果较好
waitKey(0);
return 0;
}
#include
#include
using namespace cv;
int main(int argc, char** argv) {
Mat src, dst;
src = imread("D:/photos/21.jpg");
if (!src.data) {
printf("could not load image...\n");
return -1;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src);
bilateralFilter(src, dst, 15, 100, 5);//双边模糊
namedWindow("BiBlur Filter Result", CV_WINDOW_AUTOSIZE);
imshow("BiBlur Filter Result", dst);//双边模糊
Mat resultImg;
Mat kernel = (Mat_<int>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);//掩膜算子,提高对比度
filter2D(dst, resultImg, -1, kernel, Point(-1, -1), 0);
imshow("Final Result", resultImg);//双边模糊后再提高其图像对比度
waitKey(0);
return 0;
}
运行效果:
1.形态学操作(morphology operators)-膨胀
形态学操作-膨胀
跟卷积操作类似,假设有图像A和结构元素B,结构元素B在A上面移动,其中B定义其中心为锚点,计算B覆盖下A的最大像素值用来替换锚点的像素,其中B作为结构体可以是任意形状。
注:以结构元素中各像素点的最大值来替代锚点中的值
2.形态学操作-腐蚀
腐蚀跟膨胀操作的过程类似,唯一不同的是以最小值替换锚点重叠下图像的像素值。
注:以结构元素中的最小值替代锚点重叠下图像的像素值。
3.开操作- open
1.创建结构元素
getStructuringElement(int shape, Size ksize, Point anchor);//创建结构元素
参数说明:
shape:结构元素形状,可选参数:MORPH_RECT(矩形)\MORPH_CROSS(十字架型) \MORPH_ELLIPSE(椭圆)
ksize:结构元素形状
anchor:锚点位置,默认是Point(-1, -1)意思就是中心像素
2.动态调整结构元素大小——TrackBar功能
createTrackbar(const String & trackbarname, const String winName, int* value, int count, Trackbarcallback func, void* userdata=0);
参数说明:
trackbarname:工具条名称
winName:所需要用到的图像窗口明辰
value:需要动态改变的变量指针
count:需要动态变化的变量的最大值
func:拉动滑条时,所想要调用的函数名
3.膨胀函数API——dilate
dilate(src, dst, kernel) ;
参数说明:
src:源图像
dst:目标图像
kernel:函数所需结构元素
erode(src, dst, kernel);
参数说明:
src:源图像
dst:目标图像
kernel:函数所需结构元素
morphologyEx(src, dest, int OPT , kernel);
参数说明:
- Mat src – 输入图像
- Mat dest – 输出结果
- int OPT – CV_MOP_OPEN(开操作)/ CV_MOP_CLOSE(闭操作)/ CV_MOP_GRADIENT(梯度操作) / CV_MOP_TOPHAT(顶帽)/ CV_MOP_BLACKHAT(黑帽) 形态学操作类型
- kernel:函数所需结构元素
- int Iteration 迭代次数,默认是1
eg:morphologyEx(src, dest, CV_MOP_BLACKHAT, kernel)
1.腐蚀与膨胀
#include
using namespace cv;
Mat src, dst;
char OUTPUT_WIN[] = "output image";
int element_size = 3;
int max_size = 21;
void CallBack_Demo(int, void*);
int main(int argc, char** argv) {
src = imread("D:/photos/21.jpg");
if (!src.data) {
printf("could not load image...\n");
return -1;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src);
namedWindow(OUTPUT_WIN, CV_WINDOW_AUTOSIZE);
createTrackbar("Element Size :", OUTPUT_WIN, &element_size, max_size, CallBack_Demo);//动态调整结构元素尺寸
CallBack_Demo(0, 0);
waitKey(0);
return 0;
}
void CallBack_Demo(int, void*) {
int s = element_size * 2 + 1;
Mat structureElement = getStructuringElement(MORPH_RECT, Size(s, s), Point(-1, -1));//创建结构元素
// dilate(src, dst, structureElement, Point(-1, -1), 1);//膨胀操作
erode(src, dst, structureElement);//腐蚀操作
imshow(OUTPUT_WIN, dst);
return;
}
#include
#include
using namespace cv;
int main(int argc, char** argv) {
Mat src, dst;
src = imread("D:/photos/21.jpg");
if (!src.data) {
std::cout << "could not find image...\n";
return -1;
}
namedWindow("input_image", CV_WINDOW_AUTOSIZE);
imshow("input_image", src);
char output_title[] = "morphology demo";
namedWindow(output_title, CV_WINDOW_AUTOSIZE);
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));//定义结构元素
morphologyEx(src, dst, CV_MOP_TOPHAT, kernel);//顶帽操作,原图像与开操作(先腐蚀后膨胀)的差值
imshow(output_title, dst);
waitKey(0);
return 0;
}
图像形态学操作时候,可以通过自定义的结构元素实现结构元素
对输入图像一些对象敏感、另外一些对象不敏感,这样就会让敏
感的对象改变而不敏感的对象保留输出。通过使用两个最基本的
形态学操作 – 膨胀与腐蚀,使用不同的结构元素实现对输入图像
的操作、得到想要的结果。
#include
#include
using namespace cv;
int main(int argc, char** argv) {
Mat src, dst;
src = imread("D:/photos/31.png");
if (!src.data) {
std::cout << "could not find image...\n";
return -1;
}
char INPUT_WIN[] = "input_image";
char OUTPUT_WIN[] = "output_image";
namedWindow(INPUT_WIN, CV_WINDOW_AUTOSIZE);
imshow(INPUT_WIN, src);
Mat gray_src;
cvtColor(src, gray_src, CV_BGR2GRAY);
imshow("gray image", gray_src);
Mat binIma;
adaptiveThreshold(~gray_src, binIma, 255, ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2);
imshow("binary_image", binIma);
Mat hline = getStructuringElement(MORPH_RECT, Size(src.cols / 16, 1), Point(-1, -1));
Mat vline = getStructuringElement(MORPH_RECT, Size(1,src.rows / 16), Point(-1, -1));
Mat kernel= getStructuringElement(MORPH_RECT, Size(5,5 ),Point(-1, -1));
Mat temp;
morphologyEx(binIma, dst, CV_MOP_OPEN, kernel);//开操作
//erode(binIma, temp, hline);
//dilate(temp, dst, hline);
bitwise_not(dst, dst);//背景变白色
blur(dst, dst, Size(3, 3), Point(-1, -1));
imshow("final_image", dst);
waitKey(0);
return 0;
}