W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
在本教程中,您將學(xué)習(xí)如何:
形態(tài)學(xué)是一組圖像處理操作,其基于預(yù)定義的也稱為內(nèi)核的結(jié)構(gòu)元素來處理圖像。輸出圖像中的每個(gè)像素的值基于輸入圖像中的對(duì)應(yīng)像素與其鄰居的比較。通過選擇內(nèi)核的大小和形狀,您可以構(gòu)建對(duì)輸入圖像的特定形狀敏感的形態(tài)操作。
兩個(gè)最基本的形態(tài)操作是擴(kuò)張和侵蝕。擴(kuò)散將像素添加到圖像中對(duì)象的邊界,而侵蝕恰恰相反。添加或刪除的像素?cái)?shù)量分別取決于用于處理圖像的結(jié)構(gòu)元素的大小和形狀。一般來說,這兩個(gè)操作遵循的規(guī)則如下:
二進(jìn)制圖像的擴(kuò)張
灰度圖像的擴(kuò)張
侵蝕:反之亦然適用于侵蝕作業(yè)。輸出像素的值是落在結(jié)構(gòu)元素的大小和形狀內(nèi)的所有像素的最小值??聪旅娴睦樱?/p>
侵蝕二進(jìn)制圖像
灰度圖像侵蝕
如上所述,通常在任何形態(tài)學(xué)操作中,用于探測(cè)輸入圖像的結(jié)構(gòu)元素是最重要的部分。
一個(gè)結(jié)構(gòu)化元素是一個(gè)由只有0和1組成的矩陣,可以有任意的任意形狀和大小。通常比正在處理的圖像小得多,而值為1的像素定義鄰域。稱為原點(diǎn)的結(jié)構(gòu)元素的中心像素標(biāo)識(shí)感興趣的像素 - 正在處理的像素。
例如,下面示出了7×7尺寸的菱形結(jié)構(gòu)元件。
鉆石形結(jié)構(gòu)元件及其起源
結(jié)構(gòu)元素可以具有許多常見的形狀,例如線,菱形,圓盤,周期線以及圓和尺寸。您通常選擇與要在輸入圖像中處理/提取的對(duì)象相同的大小和形狀的結(jié)構(gòu)元素。例如,要在圖像中查找行,請(qǐng)創(chuàng)建一個(gè)線性結(jié)構(gòu)元素,您將在后面看到。
本教程代碼如下所示。您也可以從這里下載。
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main(int, char** argv)
{
// 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);
// Create the images that will use to extract the horizontal and vertical lines
Mat horizontal = bw.clone();
Mat vertical = bw.clone();
// 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);
// 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);
// 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);
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);
// Create the images that will use to extract the horizontal and vertical lines
Mat horizontal = bw.clone();
Mat vertical = bw.clone();
正如我們?cè)诶碚撝兄付ǖ?,為了提取我們想要的?duì)象,我們需要?jiǎng)?chuàng)建相應(yīng)的結(jié)構(gòu)元素。因?yàn)檫@里我們要提取水平線,所以用于此目的的相應(yīng)結(jié)構(gòu)元素將具有以下形狀:
在源代碼中,它由以下代碼片段代表:
// 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);
這又表示如下:
// 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);
// 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);
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: