opencv4 学习 07 膨胀、腐蚀和开闭运算
膨胀:定义一个核,然后遍历整个图片,对于每个像素,以该像素为中心,使用核包裹范围内最大的像素值代替该像素值。所以最终高亮度的地方会膨胀。
腐蚀:定义一个核,然后遍历整个图片,对于每个像素,以该像素为中心,使用核包裹范围内最小的像素值代替该像素值。所以最终高亮度的地方会缩小。
#include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> #include <iostream> using namespace std; using namespace cv; Mat src, erosion_dst, dilation_dst; int erosion_elem = 0; int erosion_size = 0; int dilation_elem = 0; int dilation_size = 0; int const max_elem = 2; int const max_kernel_size = 21; void erosion(int, void*); void dilation(int, void*); int main(int argc, char* argv[]) { src = imread("LinuxLogo.jpg", IMREAD_COLOR); namedWindow("Erosion Demo", WINDOW_AUTOSIZE); namedWindow("Dilation Demo", WINDOW_AUTOSIZE); moveWindow("Dilation Demo", src.cols, 0); createTrackbar("Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Erosion Demo", &erosion_elem, max_elem, erosion); createTrackbar("kernel size:\n 2n+1", "Erosion Demo", &erosion_size, max_kernel_size, erosion); createTrackbar("Element:\n 0: Rect \n 1: Cross \n 2: Ellipse", "Dilation Demo", &dilation_elem, max_elem, dilation); createTrackbar("kernel size:\n 2n+1", "Dilation Demo", &dilation_size, max_kernel_size,dilation); erosion(0,0); dilation(0,0); waitKey(0); return 0; } void erosion(int, void*){ int erosion_type = 0; if(erosion_elem == 0){ erosion_type = MORPH_RECT;} else if(erosion_elem == 1){ erosion_type = MORPH_CROSS;} else if(erosion_elem == 2){ erosion_type = MORPH_ELLIPSE;} Mat element = getStructuringElement(erosion_type, Size(2*erosion_size+1, 2*erosion_size+1), Point(erosion_size,erosion_size)); erode(src, erosion_dst, element); imshow("Erosion Demo", erosion_dst); } void dilation(int, void *){ int dilation_type = 0; if(dilation_elem == 0){dilation_type = MORPH_RECT;} else if(dilation_elem == 1){ dilation_type = MORPH_CROSS;} else if(dilation_elem == 2){ dilation_type = MORPH_ELLIPSE;} Mat element = getStructuringElement(dilation_type, Size(2*dilation_size+1, 2*dilation_size+1), Point(dilation_size, dilation_size)); dilate(src, dilation_dst, element); imshow("Dilation Demo", dilation_dst); }
开运算:先腐蚀后膨胀,可以有效去除高光噪点
dst=open(src,element)=dilate(erode(src,element))
闭运算:先膨胀后腐蚀,可以有效去除低光的孔洞
dst=close(src,element)=erode(dilate(src,element))
形态学梯度:膨胀后的图像和腐蚀后的图像之间的差
dst=morphgrad(src,element)=dilate(src,element)−erode(src,element)
top hat:原始图想和开运算后的图像之间的差
dst=tophat(src,element)=src−open(src,element)
black hat:闭运算后的图像和原始图像之间的差
dst=blackhat(src,element)=close(src,element)−src
#include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> #include <opencv2/imgproc.hpp> #include <iostream> using namespace std; using namespace cv; Mat src, dst; int morph_elem = 0; int morph_size = 0; int morph_operator = 0; int const max_operator = 4; int const max_elem = 2; int const max_kernel_size = 21; const char* window_name = "Morphology Transformations Demo"; void morphology_operations(int, void*); int main(int argc, char* argv[]) { namedWindow(window_name, WINDOW_AUTOSIZE); src = imread("baboon.jpg", IMREAD_COLOR); createTrackbar("Operator:\n 0: Opening - 1: Closing \n 2: Gradient - 3: Top Hat \n 4: Black Hat", window_name, &morph_operator, max_operator, morphology_operations); createTrackbar("Element:\n 0: Rect - 1: Cross - 2: Ellipse", window_name, &morph_elem, max_elem, morphology_operations); createTrackbar("kernel size:\n 2n+1", window_name, &morph_size, max_kernel_size, morphology_operations); morphology_operations(0,0); waitKey(0); return 0; } void morphology_operations(int, void*){ int operation = morph_operator + 2; Mat element = getStructuringElement(morph_elem, Size(2*morph_size+1,2*morph_size+1),Point(morph_size,morph_size)); morphologyEx(src,dst,operation,element); imshow(window_name,dst); }
参考:
https://docs.opencv.org/3.4/db/df6/tutorial_erosion_dilatation.html
https://docs.opencv.org/3.4/d3/dbe/tutorial_opening_closing_hats.html