标签:inverse 膨胀 加载 iostream 常见 transform 出图 理论 初始化
目的:
结合自定义核,应用两个非常常见的形态学算子(例如,扩张和侵蚀),提取水平和垂直方向的线条。将会用到以下OpenCV函数:
接下里的例子是从乐谱中提取音符(五线谱中音符和乐谱线的分离)
理论
形态学是一组图像处理操作, 基于预定义的structuring elements(也被称为核)。输出图像中的每个像素的值是基于中心像素与输入图像中相邻像素的值的比较确定。通过选择核的大小和形状,可以构造一个对输入图像的特定形状敏感的形态学运算。
两个最基本的形态操作是膨胀和腐蚀。膨胀会将像素添加到图像中的对象的边界,而腐蚀正好相反。添加或删除的像素的量,分别取决于用于处理图像的结构元素的大小和形状。一般来说,这两个操作的规则如下:
膨胀(Dilation):输出像素的值是在结构元素的大小和形状上的所有像素的最大值。例如,在一个二值图像中,如果在核的范围内的输入图像的任何一个像素都被设置为值1,则输出图像的相应的像素将被设置为1。后者适用于任何类型的图像(如灰度,BGR,等)。
Erosion: 反之腐蚀操作的应用亦然,输出像素的值是在结构元素的大小和形状上的所有像素的最小值。下图是例子:
Structuring Elements(结构元素)
正如前面所述,在任何形态操作中,用于探测输入图像的结构元素是最重要的一部分。一个结构元素是一个只包含0和1的矩阵,可以有任何任意形状和大小。通常情况下,远小于被处理的图像,值为1的元素定义的是相邻的邻域。结构元素的中心像素,称为原点,标识感兴趣的像素(正在处理的像素)。例如,下面说是一个菱形结构元素,有7x7个元素。
一个结构元素可以有许多常见的形状(如线,菱形,圆盘状,周期线,和圆圈)和大小。你通常会选择一个大小形状和待处理/提取的对象一致的结构元素。例如,在图像中查找线条,创建一个线性结构元素,稍后将看到。
代码
/** * @file Morphology_3(Extract_Lines).cpp * @brief Use morphology transformations for extracting horizontal and vertical lines sample code * @author OpenCV team */ #include <iostream> #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main(int, char** argv) { //! [load_image] // Load the image Mat src = imread(argv[1]); // Check if image is loaded fine if(!src.data) cerr << "Problem loading image!!!" << endl; // Show source image imshow("src", src); //! [load_image] //! [gray] // Transform source image to gray if it is not Mat gray; if (src.channels() == 3) { cvtColor(src, gray, CV_BGR2GRAY); } else { gray = src; } // Show gray image imshow("gray", gray); //! [gray] //! [bin] // Apply adaptiveThreshold at the bitwise_not of gray, notice the ~ symbol Mat bw; adaptiveThreshold(~gray, bw, 255, CV_ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2); // Show binary image imshow("binary", bw); //! [bin] //! [init] // Create the images that will use to extract the horizontal and vertical lines Mat horizontal = bw.clone(); Mat vertical = bw.clone(); //! [init] //! [horiz] // Specify size on horizontal axis int horizontalsize = horizontal.cols / 30; // Create structure element for extracting horizontal lines through morphology operations Mat horizontalStructure = getStructuringElement(MORPH_RECT, Size(horizontalsize,1)); // Apply morphology operations erode(horizontal, horizontal, horizontalStructure, Point(-1, -1)); dilate(horizontal, horizontal, horizontalStructure, Point(-1, -1)); // Show extracted horizontal lines imshow("horizontal", horizontal); //! [horiz] //! [vert] // Specify size on vertical axis int verticalsize = vertical.rows / 30; // Create structure element for extracting vertical lines through morphology operations Mat verticalStructure = getStructuringElement(MORPH_RECT, Size( 1,verticalsize)); // Apply morphology operations erode(vertical, vertical, verticalStructure, Point(-1, -1)); dilate(vertical, vertical, verticalStructure, Point(-1, -1)); // Show extracted vertical lines imshow("vertical", vertical); //! [vert] //! [smooth] // Inverse vertical image bitwise_not(vertical, vertical); imshow("vertical_bit", vertical); // Extract edges and smooth image according to the logic // 1. extract edges // 2. dilate(edges) // 3. src.copyTo(smooth) // 4. blur smooth img // 5. smooth.copyTo(src, edges) // Step 1 Mat edges; adaptiveThreshold(vertical, edges, 255, CV_ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 3, -2); imshow("edges", edges); // Step 2 Mat kernel = Mat::ones(2, 2, CV_8UC1); dilate(edges, edges, kernel); imshow("dilate", edges); // Step 3 Mat smooth; vertical.copyTo(smooth); // Step 4 blur(smooth, smooth, Size(2, 2)); // Step 5 smooth.copyTo(vertical, edges); // Show final result imshow("smooth", vertical); //! [smooth] waitKey(0); return 0; }
// Load the image Mat src = imread(argv[1]); // Check if image is loaded fine if(!src.data) cerr << "Problem loading image!!!" << endl; // Show source image imshow("src", src);
// Transform source image to gray if it is not Mat gray; if (src.channels() == 3) { cvtColor(src, gray, CV_BGR2GRAY); } else { gray = src; } // Show gray image imshow("gray", gray);
// Apply adaptiveThreshold at the bitwise_not of gray, notice the ~ symbol Mat bw; adaptiveThreshold(~gray, bw, 255, CV_ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 15, -2); // Show binary image imshow("binary", bw);
4. 在我们已经准备好应用形态学操作,以提取水平和垂直线,作为从乐谱中分离音符的结果,但首先让我们初始化的输出图像:
// Create the images that will use to extract the horizontal and vertical lines Mat horizontal = bw.clone(); Mat vertical = bw.clone();
5. 正如我们在理论中所说的,为了提取我们所希望的对象,我们需要创建相应的结构元素。由于这里我们要提取水平线,一个相应的结构元素有以下形状:
在代码的实现方式如下:
// Specify size on horizontal axis int horizontalsize = horizontal.cols / 30; // Create structure element for extracting horizontal lines through morphology operations Mat horizontalStructure = getStructuringElement(MORPH_RECT, Size(horizontalsize,1)); // Apply morphology operations erode(horizontal, horizontal, horizontalStructure, Point(-1, -1)); dilate(horizontal, horizontal, horizontalStructure, Point(-1, -1)); // Show extracted horizontal lines imshow("horizontal", horizontal);
6. 垂直线条的的用法也是这样,相应的结构元素如下:
// Specify size on vertical axis int verticalsize = vertical.rows / 30; // Create structure element for extracting vertical lines through morphology operations Mat verticalStructure = getStructuringElement(MORPH_RECT, Size( 1,verticalsize)); // Apply morphology operations erode(vertical, vertical, verticalStructure, Point(-1, -1)); dilate(vertical, vertical, verticalStructure, Point(-1, -1)); // Show extracted vertical lines imshow("vertical", vertical);
7. 正如你所看到的,你会注意到,音符的边缘是有点粗糙的。由于这个原因,我们需要光顺处理边缘,以获得更平滑的结果
// Inverse vertical image bitwise_not(vertical, vertical); imshow("vertical_bit", vertical); // Extract edges and smooth image according to the logic // 1. extract edges // 2. dilate(edges) // 3. src.copyTo(smooth) // 4. blur smooth img // 5. smooth.copyTo(src, edges) // Step 1 Mat edges; adaptiveThreshold(vertical, edges, 255, CV_ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 3, -2); imshow("edges", edges); // Step 2 Mat kernel = Mat::ones(2, 2, CV_8UC1); dilate(edges, edges, kernel); imshow("dilate", edges); // Step 3 Mat smooth; vertical.copyTo(smooth); // Step 4 blur(smooth, smooth, Size(2, 2)); // Step 5 smooth.copyTo(vertical, edges); // Show final result imshow("smooth", vertical);
标签:inverse 膨胀 加载 iostream 常见 transform 出图 理论 初始化
原文地址:http://blog.csdn.net/real_myth/article/details/53088649