基於OpenCV的影象形態學處理
阿新 • • 發佈:2018-11-21
1、形態學概述
一詞通常表示生物學的個分支,該主要研究動植形態 和結構 。 而我們影象處理中的形態學,往指是數學形態學。
最基本的形態學操作有兩種:膨脹和腐蝕
膨脹:(dilate)就是求區域性最大值的操作。從數學角度來說,膨脹或者腐蝕操作就是講影象(或影象的一部分割槽域,稱之為A)與核(稱之為B)進行卷積。
膨脹和腐蝕:(erode)是相反的一對操作,所以腐蝕就是求區域性最小值的操作。
開運算:(Opening Operation),其實就是先腐蝕後膨脹的過程,開運算可以用來消除小物體,在纖細點處分離物體,並且在平滑較大物體的邊界的同時部明顯改變其面積。
閉運算:先膨脹後腐蝕的過程稱為閉運算(Closing Operation)。
2、實現影象的膨脹和腐蝕操作,開運算、閉運算
程式碼實現思路
1)載入原影象並顯示
2)建立兩個視窗並建立滾動條
3)輪詢獲取按鍵資訊
4)開運算和閉運算回撥函式
5)膨脹和腐蝕回撥函式
原始碼:
#include <iostream> #include <opencv2/opencv.hpp> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace cv; using namespace std; Mat g_srcImage,g_dstImage;//原始圖和效果圖 int g_nElementShape =MORPH_RECT; //變數接受的TrackBar位置引數 int g_nMaxIterationNum =10; int g_nOpencloseNum =0; int g_nErodeDilateNum =0; //回撥函式.. static void on_OpenClose(int,void*); static void on_ErodeDilate(int,void*); static void on_TopBlackHat(int,void*); int main() { //載入原圖 g_srcImage=imread("3.jpg"); namedWindow("原始圖"); imshow("原始圖",g_srcImage); //建立兩個創就並建立滾動條 namedWindow("開運算/閉運算",1); namedWindow("腐蝕/膨脹",1); //引數賦值 g_nOpencloseNum=9; g_nErodeDilateNum=9; createTrackbar("迭代值","開運算/閉運算",&g_nOpencloseNum,g_nMaxIterationNum*2+1,on_OpenClose); createTrackbar("迭代值","腐蝕/膨脹",&g_nErodeDilateNum,g_nMaxIterationNum*2+1,on_ErodeDilate); on_OpenClose(g_nOpencloseNum,0); on_ErodeDilate(g_nErodeDilateNum,0); while(1) { int c; c=waitKey(0); if((char)c=='q'||(c)==27) break; } return 0; } 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)); //核的形狀 0:矩形 1:十字交叉形 2: 橢圓 Size ksize,//核大小 Point anchor=Point(-1,-1) //核中心位置,預設位於形狀中心處 if(offset<0) { morphologyEx(g_srcImage,g_dstImage,CV_MOP_OPEN,element); } else { morphologyEx(g_srcImage,g_dstImage,CV_MOP_CLOSE,element); } imshow("開運算/閉運算",g_dstImage); } 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); }
顯示的效果:
3、利用膨脹腐蝕提取灰度圖邊界
#include <iostream> #include <opencv2/opencv.hpp> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace cv; using namespace std; Mat g_srcImage,g_dstImage,g_dstImage1,g_dstImage2; Mat g_srcImageA,g_srcImageB,g_dstImage3,g_dstImage4,g_dstImage5; int g_nElementShape =MORPH_RECT;// 矩形: MORPH_RECT 交叉形: MORPH_CROSS 橢圓形: MORPH_ELLIPSE int main() { //載入原圖 g_srcImage=imread("3.jpg"); namedWindow("原始圖"); imshow("原始圖",g_srcImage); Mat element =getStructuringElement(g_nElementShape,Size(3,3),Point(-1,-1)); erode(g_srcImage,g_dstImage,element); dilate(g_srcImage,g_dstImage1,element); g_dstImage2=g_dstImage1-g_dstImage; imshow("實驗圖",g_dstImage2); waitKey(); }
效果圖:
4、根據擊中擊不中變換的原理,用程式碼實現影象的擊中尋找到B 圖(B.png)在A 圖(A.png)中的位置。
原始碼:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
using namespace std;
Mat g_srcImage,g_dstImage,g_dstImage1,g_dstImage2;
Mat g_srcImageA,g_srcImageB,g_dstImage3,g_dstImage4,g_dstImage5;
int g_nElementShape =MORPH_RECT;// 矩形: MORPH_RECT 交叉形: MORPH_CROSS 橢圓形: MORPH_ELLIPSE
int main()
{
g_srcImageA=imread("A.png");
g_srcImageB=imread("B.png");
cvtColor(g_srcImageA, g_srcImageA, CV_RGB2GRAY);
cvtColor(g_srcImageB, g_srcImageB, CV_RGB2GRAY); //灰度值處理
int threhold = 180;
threshold(g_srcImageA, g_srcImageA, threhold, 255, CV_THRESH_BINARY);
threshold(g_srcImageB, g_srcImageB, threhold, 255, CV_THRESH_BINARY); //二值化處理
Mat ma = Mat::ones(g_srcImageA.size(), g_srcImageA.type());
Mat g_srcImageA1=ma*255-g_srcImageA;
Mat img_b;
copyMakeBorder(g_srcImageB,img_b,1,1,1,1,IPL_BORDER_CONSTANT,Scalar(255));
//imshow("加邊框",img_b);
//imshow("A圖",g_srcImageA);
Mat mb = Mat::ones(img_b.size(), img_b.type());
Mat g_srcImageB1=mb*255-img_b;
//imshow("B圖取反",g_srcImageB1);
//imshow("A圖取反",g_srcImageA1);
Mat hit_result, hit_result1, hit_result2;
erode(g_srcImageA, hit_result1,img_b, Point(-1,-1), 1 );
imshow("第一次腐蝕", hit_result1);
erode(g_srcImageA1, hit_result2,g_srcImageB1, Point(-1,-1), 1);
imshow("第二次腐蝕", hit_result2);
hit_result = hit_result1 & hit_result2;
imshow("擊中擊不中", hit_result);
waitKey();
}