Goal
In this tutorial you will learn how to:html
- Apply two very common morphological operators: Erosion and Dilation. For this purpose, you will use the following OpenCV functions:
Morphological Operations
- In short: A set of operations that process images based on shapes. Morphological operations apply a structuring element to an input image and generate an output image.
- The most basic morphological operations are: Erosion and Dilation. They have a wide array of uses, i.e. :
- Removing noise
- Isolation of individual elements and joining disparate elements in an image.
- Finding of intensity bumps or holes in an image
Dilation 膨脹
- This operations consists of convolving an image A with some kernel ( B), which can have any shape or size, usually a square or circle.
- The kernel B has a defined anchor point, usually being the center of the kernel.
- As the kernel B is scanned over the image, we compute the maximal pixel value overlapped by B and replace the image pixel in the anchor point position with that maximal value. As you can deduce, this maximizing operation causes bright regions within an image to "grow" (therefore the name dilation).
- The dilatation operation is: dst(x,y)=max(x′,y′):element(x′,y′)≠0src(x+x′,y+y′)
-
Take the above image as an example. Applying dilation we can get:python
Erosion
- This operation is the sister of dilation. It computes a local minimum over the area of given kernel.
- As the kernel B is scanned over the image, we compute the minimal pixel value overlapped by B and replace the image pixel under the anchor point with that minimal value.
- The erosion operation is: dst(x,y)=min(x′,y′):element(x′,y′)≠0src(x+x′,y+y′)
-
Analagously to the example for dilation, we can apply the erosion operator to the original image (shown above). You can see in the result below that the bright areas of the image get thinner, whereas the dark zones gets bigger.ios
#include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> using namespace cv; using namespace std; 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) { //CommandLineParser parser(argc, argv, "{@input | LinuxLogo.jpg | input image}"); //src = imread(samples::findFile(parser.get<String>("@input")), IMREAD_COLOR); src = imread("NWPUSZ.jpg"); resize(src, src, Size(src.cols / 4, src.rows / 4)); if (src.empty()) { cout << "Could not open or find the image!\n" << endl; cout << "Usage: " << argv[0] << " <Input image>" << endl; return -1; } 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); }
from __future__ import print_function import cv2 as cv erosion_size = 0 max_elem = 2 max_kernel_size = 21 title_trackbar_element_type = 'Element:\n 0: Rect \n 1: Cross \n 2: Ellipse' title_trackbar_kernel_size = 'Kernel size:\n 2n +1' title_erosion_window = 'Erosion Demo' title_dilatation_window = 'Dilation Demo' def erosion(val): erosion_size = cv.getTrackbarPos(title_trackbar_kernel_size, title_erosion_window) erosion_type = 0 val_type = cv.getTrackbarPos(title_trackbar_element_type, title_erosion_window) if val_type == 0: erosion_type = cv.MORPH_RECT elif val_type == 1: erosion_type = cv.MORPH_CROSS elif val_type == 2: erosion_type = cv.MORPH_ELLIPSE element = cv.getStructuringElement(erosion_type, (2*erosion_size + 1, 2*erosion_size+1), (erosion_size, erosion_size)) erosion_dst = cv.erode(src, element) cv.imshow(title_erosion_window, erosion_dst) def dilatation(val): dilatation_size = cv.getTrackbarPos(title_trackbar_kernel_size, title_dilatation_window) dilatation_type = 0 val_type = cv.getTrackbarPos(title_trackbar_element_type, title_dilatation_window) if val_type == 0: dilatation_type = cv.MORPH_RECT elif val_type == 1: dilatation_type = cv.MORPH_CROSS elif val_type == 2: dilatation_type = cv.MORPH_ELLIPSE element = cv.getStructuringElement(dilatation_type, (2*dilatation_size + 1, 2*dilatation_size+1), (dilatation_size, dilatation_size)) dilatation_dst = cv.dilate(src, element) cv.imshow(title_dilatation_window, dilatation_dst) src = cv.imread("brid.jpg") src = cv.resize(src, (int(src.shape[1]/4), int(src.shape[0]/4))) # width = int(img.shape[1] ) # height = int(img.shape[0]) if src is None: print('Could not open or find the image: ') exit(0) cv.namedWindow(title_erosion_window) cv.createTrackbar(title_trackbar_element_type, title_erosion_window , 0, max_elem, erosion) cv.createTrackbar(title_trackbar_kernel_size, title_erosion_window , 0, max_kernel_size, erosion) cv.namedWindow(title_dilatation_window) cv.createTrackbar(title_trackbar_element_type, title_dilatation_window , 0, max_elem, dilatation) cv.createTrackbar(title_trackbar_kernel_size, title_dilatation_window , 0, max_kernel_size, dilatation) erosion(0) dilatation(0) cv.waitKey()