OpenCv3编程学习八

    技术2022-07-13  87

    本章开始进行对imgpro的学习 也就是各种各样对图像的处理 1.平滑处理: 也就是模糊处理,用途主要体现在减少图像上的噪点和失真,也就是减低图像的分辨率。 2.图像滤波和滤波器: 滤波的意思就是在保留图像细节的条件下,对图像的噪音进行处理的操作。 滤波的目的:1.抽出对象的特征作为图像识别的特征模式,2.消除图像数字化所产生的噪音。 滤波器就相当于是一个包含加权系数的窗口,当使用滤波器处理图像时,也就是把这个窗口放在图像之上,我们透过这个窗口来看到图像。

    常见的分别有五种滤波方式: 1.方框滤波 2.均值滤波 3.高斯滤波 4.中值滤波 5.双边滤波

    3.线性滤波器 作用是选择频率,可以是选择低频通过,比如低通滤波器,也可以是高频通过,比如高通滤波器,也可以是允许一定范围的频率通过,比如带通滤波器等等。 总结来说就是:高斯滤波就是高斯函数作为滤波函数的滤波操作,而其中高斯模糊就是高斯低通滤波。

    4.领域算子和线性邻域滤波

    方框滤波

    :box Filter这些参数依次是:输入图像,目标图像,图像的深度,size的类型,其中(x,y)表示的是x*y的核大小。 然后是point类型的anchor,也就是锚点(被平滑的点),再是bool形态的normalize,来确认是不是需要区域归一化,最后就是一个基本上不太关注的点。

    均值滤波 最简单的意思就是,归一化后的方框滤波。使用的方法是领域平均法,也就是一片图像区的各个像素的均值来代替原图像的各个像素值。所以关键在于求平均值。 blur函数第一个参数是输入图像src,第二个参数是目标图像dst,第三个参数就是内核大小(x,y)就是x*y大小的内核

    高斯滤波 它的具体操作就是:用一个模板扫描图像中的每一个像素,然后用模板里确定的加权平均灰度值去替代模板中心像素点的值。 也就是GaussianBlur函数,就是用高斯滤波器来模糊一张图片,与之前函数不同在于,有两个参数是sigmaX和sigmaY分别代表高斯核函数在X和Y方向的标准偏差。

    接下来开始用代码实现其效果

    boxFilter函数:

    #include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<time.h> using namespace cv; int main() { Mat image = imread("1.jpg"); //再创建窗口 namedWindow("均值滤波[原图]"); namedWindow("均值滤波[效果图]"); //先显示原图 imshow("均值滤波[原图]", image); //再进行滤波操作 Mat out; boxFilter(image, out, -1, Size(5, 5)); //再显示效果图 imshow("均值滤波[效果图]", out); waitKey(0); return 0; }

    blur函数:

    #include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<time.h> using namespace cv; int main() { Mat image = imread("1.jpg"); //再创建窗口 namedWindow("均值滤波[原图]"); namedWindow("均值滤波[效果图]"); //先显示原图 imshow("均值滤波[原图]", image); //再进行滤波操作 Mat out; blur(image, out, Size(7, 7)); //再显示效果图 imshow("均值滤波[效果图]", out); waitKey(0); return 0; }

    高斯滤波,GaussianBlurhanshu

    #include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<time.h> using namespace cv; int main() { Mat image = imread("1.jpg"); //再创建窗口 namedWindow("均值滤波[原图]"); namedWindow("均值滤波[效果图]"); //先显示原图 imshow("均值滤波[原图]", image); //再进行滤波操作 Mat out; GaussianBlur(image, out, Size(7, 7),0,0); //再显示效果图 imshow("均值滤波[效果图]", out); waitKey(0); return 0; }

    一个整体的代码如下:

    #include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<iostream> using namespace cv; using namespace std; Mat g_srcImage, g_dstImage1, g_dstImage2, g_dstImage3; //方框滤波参数值 int g_nBoxFilterValue = 3; //均值滤波参数值 int g_nMeanBlurValue = 3; //高斯滤波参数值 int g_nGaussianBlurValue = 3; //再是一些回调函数 static void on_BoxFilter(int, void *); static void on_MeanBlur(int, void *); static void on_GaussianBlur(int, void *); int main() { //先改变字体的颜色 system("color5E"); //再载入原图 g_srcImage = imread("1.jpg", 1); if (!g_srcImage.data) { printf_s("读取失败"); return false; } //再将原图进行复制 g_dstImage1 = g_srcImage.clone(); g_dstImage2 = g_srcImage.clone(); g_dstImage3 = g_srcImage.clone(); //再将原图显示 namedWindow("[<0>原图窗口]", 1); imshow("[<0>原图窗口]", g_srcImage); //进行方框滤波 //先创建窗口 namedWindow("[<1>方框滤波]", 1); //创建轨迹条 createTrackbar("内核值:", "[<1>方框滤波]", &g_nBoxFilterValue,40, on_BoxFilter); on_BoxFilter(g_nBoxFilterValue, 0); imshow("[<1>方框滤波]", g_dstImage1); //均值滤波 namedWindow("[<2>均值滤波]", 1); //创建轨迹条 createTrackbar("内核值:", "[<2>均值滤波]", &g_nMeanBlurValue,40, on_MeanBlur); on_MeanBlur(g_nMeanBlurValue, 0); //进行高斯滤波 //先创建窗口 namedWindow("[<3>高斯滤波]", 1); //创建轨迹条 createTrackbar("内核值:", "[<3>高斯滤波]", &g_nGaussianBlurValue,40,on_GaussianBlur); on_GaussianBlur(g_nGaussianBlurValue, 0); //再输入一些帮助信息 cout<< endl << "\t,请调整滚动条观察图像效果~\n\n" << "\t按下“q“键时,程序退出~\n"; while (char(waitKey(1) != 'q')) {} return 0; } //再开始重新构建这几个函数 static void on_BoxFilter(int, void *) { //方框滤波操作 boxFilter(g_srcImage, g_dstImage1, -1, Size(g_nBoxFilterValue + 1, g_nBoxFilterValue + 1)); //再显示窗口 imshow("[<1>方框滤波]", g_dstImage1); } //然后是均值滤波操作 static void on_MeanBlur(int, void *) { //均值滤波操作 blur(g_srcImage, g_dstImage2, Size(g_nMeanBlurValue + 1, g_nMeanBlurValue + 1), Point(-1, -1)); //再显示窗口 imshow("[<2>均值滤波]", g_dstImage2); } //最后是高斯滤波 static void on_GaussianBlur(int, void *) { GaussianBlur(g_srcImage, g_dstImage3, Size(g_nGaussianBlurValue * 2 + 1, g_nGaussianBlurValue * 2 + 1), 0, 0); //再显示窗口 imshow("[<3>高斯滤波]", g_dstImage3); }

    非线性滤波:中值滤波和双边滤波

    1.中值滤波: 用像素点领域灰度值的中值来提到这个像素点的灰度值,并且是基于排序统计理论的。 中值滤波器和均值滤波器之间的比较:由于噪音成分不会放入到平均计算当中,使用中值滤波器是不会被噪音成分所干扰,这样出来的效果更好,但是需要付出5倍以上时间的代价。 中值选取的方法就是:1.选按照强度值大小排列像素点 2.再按照排序出来的像素点的中间值作为新值。

    2.双边滤波 他最大的好处就是可以做到对边缘的保存

    3.对应的api函数 中值滤波:medianBlur函数:参数分别是1.输入图像src,2输出图像dst,int类型的ksize,孔径的线性尺寸。

    #include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<iostream> using namespace cv; using namespace std; int main() { Mat image = imread("1.jpg"); //创建窗口 namedWindow("中值滤波[原图]"); namedWindow("中值滤波[效果图]"); //显示原图 imshow("中值滤波[原图]", image); //再进行中值滤波操作 Mat out; medianBlur(image, out, 7);//第三个参数是孔径 //显示效果图 imshow("中值滤波[效果图]", out); waitKey(0); return 0; }

    双边滤波:bilateralFilter函数:参数中包含像素领域的直径,颜色空间和坐标空间滤波器的值,

    #include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<iostream> using namespace cv; using namespace std; int main() { Mat image = imread("1.jpg"); //创建窗口 namedWindow("双边滤波[原图]"); namedWindow("双边滤波[效果图]"); //显示原图 imshow("双边滤波[原图]", image); //再进行中值滤波操作 Mat out; bilateralFilter(image, out, 25, 25 * 2, 25 / 2); //显示效果图 imshow("双边滤波[效果图]", out); waitKey(0); return 0; }

    腐蚀与膨胀

    两者能实现的功能:1.消除噪音 2.分隔出独立的图像元素 3.寻找图像中明显的极大值和极小值区域 4.求出图像的梯度 并且都是针对白色,也就是高亮部分的。膨胀是求其中的最大值,而腐蚀则是求其中的最小值。 对应api函数讲解; 1.膨胀:dilate:参数分别有:1.输入和输出图像 2.膨胀操作的核 ,有矩形,交叉形和椭圆形三种。3.point类型的值,代表锚的位置 4.int类型的值,代表函数迭代使用的次数 5.int 类型的边界模式 一般都是填前面三个参数,其他人按照默认参数就行。 参考代码:

    #include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<iostream> using namespace cv; using namespace std; int main() { Mat image = imread("1.jpg"); //创建窗口 namedWindow("膨胀操作[原图]"); namedWindow("膨胀操作[效果图]"); //显示原图 imshow("膨胀操作[原图]", image); //再进行中值滤波操作 Mat out; //再获取一个自定义的核 Mat element = getStructuringElement(MORPH_RECT, Size(15, 15)); dilate(image, out, element); //显示效果图 imshow("膨胀操作[效果图]", out); waitKey(0); return 0; }

    1.腐蚀,在代码部分基本上和膨胀的作用相同,只是刚好都取反方向。 代码几近相同。

    再写一次综合各个功能的代码示例:

    #include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<iostream> using namespace cv; using namespace std; //先声明一些全局变量 Mat g_srcImage, g_dstImage; int g_nTrackbarNumber = 0;//其中0代表腐蚀,1 代表膨胀 int g_nStructElementSize = 3;//这个是内核的尺寸 void Process();//膨胀和腐蚀的处理函数 void on_TrackbarNumChange(int, void *);//进行回调的函数 void on_ElementSizeChange(int, void *);//也是回调函数 int main() { system("color5E");//字体颜色 g_srcImage = imread("1.jpg"); if (!g_srcImage.data) { printf_s("读取文件失败\n"); return false; } //再先显示原始图 namedWindow("[原始图]"); imshow("[原始图]", g_srcImage); //进行初次腐蚀操作并显示效果图 namedWindow("[效果图]"); //获取自定义核 Mat element = getStructuringElement(MORPH_RECT, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1), Point(g_nStructElementSize, g_nStructElementSize)); //再调用腐蚀的 erode(g_srcImage, g_dstImage, element); imshow("[效果图]", g_dstImage); //创建轨迹条 createTrackbar("腐蚀/膨胀", "[效果图]",&g_nTrackbarNumber, 1, on_TrackbarNumChange); createTrackbar("内核尺寸", "[效果图]", &g_nStructElementSize, 21, on_ElementSizeChange); while(char(waitKey(1))!='q') { } return 0; } //再开始写各个函数 void Process() { Mat element = getStructuringElement(MORPH_RECT, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1), Point(g_nStructElementSize, g_nStructElementSize)); if (g_nTrackbarNumber == 0) { //说明是腐蚀 erode(g_srcImage, g_dstImage, element); } else { dilate(g_srcImage, g_dstImage, element); } //并显示效果图 imshow("[效果图]", g_dstImage); } void on_TrackbarNumChange(int, void*) { //切换效果的函数已经写好,所以这里就是直接调用切换就行了 Process(); } void on_ElementSizeChange(int, void *) { Process(); }

    形态学滤波:1.开运算2.闭运算 形态学梯度,顶帽和黑帽

    morphologyEx函数 1.开运算: 也就是先腐蚀(erode)再膨胀(dilate) dst=open(src,element)=dilate(erode(src,element)) 2.闭运算 先膨胀(dilate)再腐蚀(erode) dst=close(src,element)=erode(dilate(src,element)) 3.形态学梯度 作为膨胀图和腐蚀图之差 dst=morph-grad(src,element)=dilate(src,element)-erode(src,element) 4.顶帽 是作为原图和“开运算”的结果图之差 dst=tophat(src,element)=src-open(src,element) 5.黑帽 dst=blackhat(src,element)=close(src,element)-src

    核心API函数:morphologyEx() 参数如下:1.输入和输出图像 2.op:形态学的运算类型 3.形态学运算的内核,如果是null的话,那就是默认中心位置 4.锚的位置 5.iterations,迭代使用函数的次数 还有两个一般都是默认的参数

    #include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<iostream> using namespace cv; using namespace std; int main() { //先读取原图 Mat image = imread("1.jpg"); //创建窗口 namedWindow("[原始图]"); namedWindow("[效果图]"); //再显示效果图 imshow("[原始图]", image); //再定义核 Mat element = getStructuringElement(MORPH_RECT, Size(15, 15)); morphologyEx(image, image, MORPH_OPEN,element); imshow("[效果图]", image); waitKey(0); return 0; }
    Processed: 0.018, SQL: 9