腐蝕與膨脹
膨脹(求局部最大值)(dilate函數)
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
//-----------------------------------【命名空間聲明部分】---------------------------------------
// 描述:包含程序所使用的命名空間
//-----------------------------------------------------------------------------------------------
using namespace std;
using namespace cv;
//-----------------------------------【main( )函數】--------------------------------------------
// 描述:控制台應用程序的入口函數,我們的程序從這里開始
//-----------------------------------------------------------------------------------------------
int main()
{
//載入原圖
Mat image = imread("1.jpg");
//創建窗口
namedWindow("【原圖】膨脹操作");
namedWindow("【效果圖】膨脹操作");
//顯示原圖
imshow("【原圖】膨脹操作", image);
//進行膨脹操作
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
Mat out;
dilate(image, out, element);
//顯示效果圖
imshow("【效果圖】膨脹操作", out);
waitKey(0);
return 0;
}
腐蝕(求局部最小值)(erode)
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
//-----------------------------------【main( )函數】--------------------------------------------
// 描述:控制台應用程序的入口函數,我們的程序從這里開始
//-----------------------------------------------------------------------------------------------
int main()
{
//載入原圖
Mat srcImage = imread("1.jpg");
//顯示原圖
imshow("【原圖】腐蝕操作", srcImage);
//進行腐蝕操作
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
Mat dstImage;
erode(srcImage, dstImage, element);
//顯示效果圖
imshow("【效果圖】腐蝕操作", dstImage);
waitKey(0);
return 0;
}
腐蝕與膨脹滑動條實例
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace std;
using namespace cv;
//-----------------------------------【全局變量聲明部分】--------------------------------------
// 描述:全局變量聲明
//-----------------------------------------------------------------------------------------------
Mat g_srcImage, g_dstImage;//原始圖和效果圖
int g_nTrackbarNumer = 0;//0表示腐蝕erode, 1表示膨脹dilate
int g_nStructElementSize = 3; //結構元素(內核矩陣)的尺寸
//-----------------------------------【全局函數聲明部分】--------------------------------------
// 描述:全局函數聲明
//-----------------------------------------------------------------------------------------------
void Process();//膨脹和腐蝕的處理函數
void on_TrackbarNumChange(int, void *);//回調函數
void on_ElementSizeChange(int, void *);//回調函數
void ShowHelpText();
//-----------------------------------【main( )函數】--------------------------------------------
// 描述:控制台應用程序的入口函數,我們的程序從這里開始
//-----------------------------------------------------------------------------------------------
int main()
{
//改變console字體顏色
system("color 2F");
//載入原圖
g_srcImage = imread("1.jpg");
if (!g_srcImage.data) { printf("讀取srcImage錯誤~! \n"); return false; }
ShowHelpText();
//顯示原始圖
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_nTrackbarNumer, 1, on_TrackbarNumChange);
createTrackbar("內核尺寸", "【效果圖】", &g_nStructElementSize, 21, on_ElementSizeChange);
//輸出一些幫助信息
cout << endl << "\t運行成功,請調整滾動條觀察圖像效果~\n\n"
<< "\t按下“q”鍵時,程序退出。\n";
//輪詢獲取按鍵信息,若下q鍵,程序退出
while (char(waitKey(1)) != 'q') {}
return 0;
}
//-----------------------------【Process( )函數】------------------------------------
// 描述:進行自定義的腐蝕和膨脹操作
//-----------------------------------------------------------------------------------------
void Process()
{
//獲取自定義核
Mat element = getStructuringElement(MORPH_RECT, Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1), Point(g_nStructElementSize, g_nStructElementSize));
//進行腐蝕或膨脹操作
if (g_nTrackbarNumer == 0) {
erode(g_srcImage, g_dstImage, element);
}
else {
dilate(g_srcImage, g_dstImage, element);
}
//顯示效果圖
imshow("【效果圖】", g_dstImage);
}
//-----------------------------【on_TrackbarNumChange( )函數】------------------------------------
// 描述:腐蝕和膨脹之間切換開關的回調函數
//-----------------------------------------------------------------------------------------------------
void on_TrackbarNumChange(int, void *)
{
//腐蝕和膨脹之間效果已經切換,回調函數體內需調用一次Process函數,使改變后的效果立即生效並顯示出來
Process();
}
//-----------------------------【on_ElementSizeChange( )函數】-------------------------------------
// 描述:腐蝕和膨脹操作內核改變時的回調函數
//-----------------------------------------------------------------------------------------------------
void on_ElementSizeChange(int, void *)
{
//內核尺寸已改變,回調函數體內需調用一次Process函數,使改變后的效果立即生效並顯示出來
Process();
}
//-----------------------------------【ShowHelpText( )函數】-----------------------------
// 描述:輸出一些幫助信息
//----------------------------------------------------------------------------------------------
void ShowHelpText()
{
//輸出歡迎信息和OpenCV版本
printf("\n\n\t\t\t 當前使用的OpenCV版本為:" CV_VERSION);
printf("\n\n ----------------------------------------------------------------------------\n");
}
開運算、閉運算、形態學梯度、頂帽、黑帽(morphologyEx函數)
開運算(先腐蝕后膨脹)
閉運算(先膨脹后腐蝕)
形態學梯度(膨脹圖與腐蝕圖之差)
頂帽(原圖像與開運算之差)
黑帽(閉運算與原圖像之差)
核心API函數(morphologyEx函數)
范例
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
//-----------------------------------【main( )函數】------------------------------------------
// 描述:控制台應用程序的入口函數,我們的程序從這里開始
//-----------------------------------------------------------------------------------------------
int main( )
{
//載入原始圖
Mat image = imread("1.jpg"); //工程目錄下應該有一張名為1.jpg的素材圖
//創建窗口
namedWindow("【原始圖】形態學梯度");
namedWindow("【效果圖】形態學梯度");
//顯示原始圖
imshow("【原始圖】形態學梯度", image);
//定義核
Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
//進行形態學操作
morphologyEx(image, image, MORPH_GRADIENT, element);
//顯示效果圖
imshow("【效果圖】形態學梯度", image);
waitKey(0);
return 0;
}
綜合實例
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
//-----------------------------------【全局變量聲明部分】-----------------------------------
// 描述:全局變量聲明
//-----------------------------------------------------------------------------------------------
Mat g_srcImage, g_dstImage;//原始圖和效果圖
int g_nElementShape = MORPH_RECT;//元素結構的形狀
//變量接收的TrackBar位置參數
int g_nMaxIterationNum = 10;
int g_nOpenCloseNum = 0;
int g_nErodeDilateNum = 0;
int g_nTopBlackHatNum = 0;
//-----------------------------------【全局函數聲明部分】--------------------------------------
// 描述:全局函數聲明
//-----------------------------------------------------------------------------------------------
static void on_OpenClose(int, void*);//回調函數
static void on_ErodeDilate(int, void*);//回調函數
static void on_TopBlackHat(int, void*);//回調函數
static void ShowHelpText();
//-----------------------------------【main( )函數】--------------------------------------------
// 描述:控制台應用程序的入口函數,我們的程序從這里開始
//-----------------------------------------------------------------------------------------------
int main()
{
//改變console字體顏色
system("color 2F");
ShowHelpText();
//載入原圖
g_srcImage = imread("1.jpg");
if (!g_srcImage.data) { printf("Oh,no,讀取srcImage錯誤~! \n"); return false; }
//顯示原始圖
namedWindow("【原始圖】");
imshow("【原始圖】", g_srcImage);
//創建三個窗口
namedWindow("【開運算/閉運算】", 1);
namedWindow("【腐蝕/膨脹】", 1);
namedWindow("【頂帽/黑帽】", 1);
//參數賦值
g_nOpenCloseNum = 9;
g_nErodeDilateNum = 9;
g_nTopBlackHatNum = 2;
//分別為三個窗口創建滾動條
createTrackbar("迭代值", "【開運算/閉運算】", &g_nOpenCloseNum, g_nMaxIterationNum * 2 + 1, on_OpenClose);
createTrackbar("迭代值", "【腐蝕/膨脹】", &g_nErodeDilateNum, g_nMaxIterationNum * 2 + 1, on_ErodeDilate);
createTrackbar("迭代值", "【頂帽/黑帽】", &g_nTopBlackHatNum, g_nMaxIterationNum * 2 + 1, on_TopBlackHat);
//輪詢獲取按鍵信息
while (1)
{
int c;
//執行回調函數
on_OpenClose(g_nOpenCloseNum, 0);
on_ErodeDilate(g_nErodeDilateNum, 0);
on_TopBlackHat(g_nTopBlackHatNum, 0);
//獲取按鍵
c = waitKey(0);
//按下鍵盤按鍵Q或者ESC,程序退出
if ((char)c == 'q' || (char)c == 27)
break;
//按下鍵盤按鍵1,使用橢圓(Elliptic)結構元素結構元素MORPH_ELLIPSE
if ((char)c == 49)//鍵盤按鍵1的ASII碼為49
g_nElementShape = MORPH_ELLIPSE;
//按下鍵盤按鍵2,使用矩形(Rectangle)結構元素MORPH_RECT
else if ((char)c == 50)//鍵盤按鍵2的ASII碼為50
g_nElementShape = MORPH_RECT;
//按下鍵盤按鍵3,使用十字形(Cross-shaped)結構元素MORPH_CROSS
else if ((char)c == 51)//鍵盤按鍵3的ASII碼為51
g_nElementShape = MORPH_CROSS;
//按下鍵盤按鍵space,在矩形、橢圓、十字形結構元素中循環
else if ((char)c == ' ')
g_nElementShape = (g_nElementShape + 1) % 3;
}
return 0;
}
//-----------------------------------【on_OpenClose( )函數】----------------------------------
// 描述:【開運算/閉運算】窗口的回調函數
//-----------------------------------------------------------------------------------------------
static void on_OpenClose(int, void*)
{
//偏移量的定義
int offset = g_nOpenCloseNum - g_nMaxIterationNum;//偏移量
int Absolute_offset = offset > 0 ? offset : -offset;//偏移量絕對值
//自定義核
Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
//進行操作
if (offset < 0)
//此句代碼的OpenCV2版為:
//morphologyEx(g_srcImage, g_dstImage, CV_MOP_OPEN, element);
//此句代碼的OpenCV3版為:
morphologyEx(g_srcImage, g_dstImage, MORPH_OPEN, element);
else
//此句代碼的OpenCV2版為:
//morphologyEx(g_srcImage, g_dstImage, CV_MOP_CLOSE, element);
//此句代碼的OpenCV3版為:
morphologyEx(g_srcImage, g_dstImage, MORPH_CLOSE, element);
//顯示圖像
imshow("【開運算/閉運算】", g_dstImage);
}
//-----------------------------------【on_ErodeDilate( )函數】----------------------------------
// 描述:【腐蝕/膨脹】窗口的回調函數
//-----------------------------------------------------------------------------------------------
static void on_ErodeDilate(int, void*)
{
//偏移量的定義
int offset = g_nErodeDilateNum - g_nMaxIterationNum; //偏移量
int Absolute_offset = offset > 0 ? offset : -offset;//偏移量絕對值
//自定義核
Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
//進行操作
if (offset < 0)
erode(g_srcImage, g_dstImage, element);
else
dilate(g_srcImage, g_dstImage, element);
//顯示圖像
imshow("【腐蝕/膨脹】", g_dstImage);
}
//-----------------------------------【on_TopBlackHat( )函數】--------------------------------
// 描述:【頂帽運算/黑帽運算】窗口的回調函數
//----------------------------------------------------------------------------------------------
static void on_TopBlackHat(int, void*)
{
//偏移量的定義
int offset = g_nTopBlackHatNum - g_nMaxIterationNum;//偏移量
int Absolute_offset = offset > 0 ? offset : -offset;//偏移量絕對值
//自定義核
Mat element = getStructuringElement(g_nElementShape, Size(Absolute_offset * 2 + 1, Absolute_offset * 2 + 1), Point(Absolute_offset, Absolute_offset));
//進行操作
if (offset < 0)
morphologyEx(g_srcImage, g_dstImage, MORPH_TOPHAT, element);
else
morphologyEx(g_srcImage, g_dstImage, MORPH_BLACKHAT, element);
//顯示圖像
imshow("【頂帽/黑帽】", g_dstImage);
}
//-----------------------------------【ShowHelpText( )函數】----------------------------------
// 描述:輸出一些幫助信息
//----------------------------------------------------------------------------------------------
static void ShowHelpText()
{
//輸出歡迎信息和OpenCV版本
printf("\n\n\t\t\t 當前使用的OpenCV版本為:" CV_VERSION);
printf("\n\n ----------------------------------------------------------------------------\n");
//輸出一些幫助信息
printf("\n\t請調整滾動條觀察圖像效果\n\n");
printf("\n\t按鍵操作說明: \n\n"
"\t\t鍵盤按鍵【ESC】或者【Q】- 退出程序\n"
"\t\t鍵盤按鍵【1】- 使用橢圓(Elliptic)結構元素\n"
"\t\t鍵盤按鍵【2】- 使用矩形(Rectangle )結構元素\n"
"\t\t鍵盤按鍵【3】- 使用十字型(Cross-shaped)結構元素\n"
"\t\t鍵盤按鍵【空格SPACE】- 在矩形、橢圓、十字形結構元素中循環\n");
}