1、膨脹腐蝕學習筆記
2、代碼及結果分享
#include <opencv2/opencv.hpp> #include <iostream> using namespace std; using namespace cv; //定義腐蝕函數 void myErode(Mat Src, Mat Tem, Mat Dst) { int m = (Tem.rows - 1) / 2; int n = (Tem.cols - 1) / 2; for (int i = m; i < Src.rows - m; i++)//i、j的範圍保證結構元始終在擴展後的圖像內部 { for (int j = n; j < Src.cols - n; j++) { Mat SrcROI = Src(Rect(j - m, i - n, Tem.cols, Tem.rows)); double sum = 0; sum = SrcROI.dot(Tem);//矩陣對應位置相乘後求和 if (sum == 9)//結構元的9個元素均爲1,和爲9才能保證結構元徹底包含於相應集合 Dst.at<uchar>(i, j) = 255; else Dst.at<uchar>(i, j) = 0; } } } //定義膨脹函數 void myDilate(Mat Src, Mat Tem, Mat Dst) { int m = (Tem.rows - 1) / 2; int n = (Tem.cols - 1) / 2; for (int i = m; i < Src.rows - m; i++)//i、j的範圍保證結構元始終在擴展後的圖像內部 { for (int j = n; j < Src.cols - n; j++) { Mat SrcROI = Src(Rect(j - m, i - n, Tem.cols, Tem.rows)); double sum = 0; sum = SrcROI.dot(Tem);//矩陣對應位置相乘後求和 if (sum != 0)//結構元的9個元素均爲1,只要和不爲0,就能說明結構元與相應集合有交集 Dst.at<uchar>(i, j) = 255; else Dst.at<uchar>(i, j) = 0; } } } int main() { Mat mImage = imread("dada.jpg", 0); if (mImage.data == 0) { cerr << "Image reading error !" << endl; system("pause"); return -1; } namedWindow("The original image", WINDOW_NORMAL); imshow("The original image", mImage); //設置閾值將圖像二值化 const int binThreshold = 80; for (int i = 0; i < mImage.rows; i++) { uchar* pImage = mImage.ptr<uchar>(i); for (int j = 0; j < mImage.cols; j++) { if (pImage[j] > binThreshold)//事實上應將灰度值大於閾值的賦值爲255,但爲了方便後續膨脹腐蝕的計算,在這裏將其賦值爲1 pImage[j]= 1; else pImage[j] = 0; } } //定義並初始化結構元 Mat mTemplate(3, 3, CV_8UC1, Scalar(1)); if (mTemplate.rows * mTemplate.cols % 2 == 0) { cerr << "The size doesn't meet the requirement !" << endl; system("pause"); return -1; } //擴展圖像邊界 copyMakeBorder(mImage, mImage, mTemplate.rows, mTemplate.rows, mTemplate.cols, mTemplate.cols, BORDER_CONSTANT, Scalar(0)); //進行圖像腐蝕 Mat mEResult = mImage.clone(); myErode(mImage, mTemplate, mEResult); //進行圖像膨脹 Mat mDResult = mImage.clone(); myDilate(mImage, mTemplate, mDResult); //進行顯示 namedWindow("The eroding image", WINDOW_NORMAL); imshow("The eroding image", mEResult); namedWindow("The dilating image", WINDOW_NORMAL); imshow("The dilating image", mDResult); waitKey(); destroyAllWindows(); return 0; }
膨脹(dilate)和腐蝕(erode)均是對白色區域而言。由結果可明顯看出,膨脹後的白色面積要比腐蝕後的大。由圖像左下角的水印變化也可直觀看出兩種操做對圖像的不一樣影響。ios
3、注意事項
在本次編程實現過程當中,爲了肯定結構元是否包含於集合(或與集合是否有交集),須要讓結構元中各元素與圖像中對應位置像素值相乘後求和。Mat類型中有幾種不一樣類型的乘法,在這裏加以總結。編程
Mat A, B ;函數
3.1A.dot(B)
A、B對應位置元素相乘,以後將全部乘積相加求和,返回值是double型數字。要求A、B size必須相同。學習
#include <opencv2/opencv.hpp> #include <iostream> using namespace std; using namespace cv; int main() { uchar A[3][3] = { {1,2,3},{4,5,6},{7,8,9} }; uchar B[3][3] = { { 1,1,1 },{ 1,1,1 },{ 1,1,1 } }; Mat Src(3, 3, CV_8UC1, A); Mat Dst(3, 3, CV_8UC1, B); double Result = Src.dot(Dst); cout << "Src:" << Src << endl; cout << "Dst:" << Dst << endl; cout << "Result:" << Result << endl; system("pause"); return 0; }
3.2A.mul(B)
A、B對應位置元素相乘,返回值是和A、B等大小,同類型的Mat型矩陣。要求A、B size必須相同。若計算結果溢出,則溢出值自動變爲當前數據類型下容許的的最大值。ui
#include <opencv2/opencv.hpp> #include <iostream> using namespace std; using namespace cv; int main() { uchar A[3][3] = { {1,2,3},{4,5,6},{7,8,9} }; uchar B[3][3] = { { 1,1,1 },{ 1,1,1 },{ 1,1,1 } }; Mat Src(3, 3, CV_8UC1, A); Mat Dst(3, 3, CV_8UC1, B); Mat Result = Src.mul(Dst); cout << "Src:" << Src << endl; cout << "Dst:" << Dst << endl; cout << "Result:" << Result << endl; system("pause"); return 0; }
注:錯誤之處,敬請雅正!spa