數學形態學中運算有 膨脹(或擴張)、腐蝕(或侵蝕)、開啓、閉合、骨架抽取、極線腐蝕、擊中擊不中變換、Top-hat變換、顆粒分析、流域變換、形態學梯度等,其中腐蝕與擴張就是我們今天所有講的要點。opencv中對腐蝕和擴張有相對的函數去實現,多用於圖像的取噪、分割出獨立的圖像元素,在圖像中連接相鄰的元素、尋找圖像中明顯的極大值或極小值區、求圖像的梯度。
腐蝕
腐蝕是求圖片局部最小值算法,定義一個任何的形狀和大小的積卷核,定義一個參考點爲錨點,通常情況下積卷核爲矩形或者圓形,在opencv中MorphShapes枚舉中有三個形狀(MORPH_RECT【矩形】、MORPH_CROSS【十字結構】、MORPH_ELLIPSE【橢圓】),可將核稱爲模板或掩膜。積卷核與圖像進行積卷,計算核覆蓋區域的像素點的最小值,並將最小值賦值給錨點,這樣圖像中的高亮區域就會逐漸減小。
JNIEXPORT jintArray JNICALL
Java_com_xy_opencv_ndk_1opencv002_MainActivity_erodeORdilate(JNIEnv *env, jclass type,
jintArray pixels_, jint w, jint h) {
jint *pixels = env->GetIntArrayElements(pixels_, NULL);
Mat img(h,w,CV_8UC4,pixels);
// 形態學
//
// 簡而言之:一組基於形狀處理圖像的操作。形態操作將結構元素應用於輸入圖像並生成輸出圖像。
// 最基本的形態作用是:侵蝕和擴張。它們有廣泛的用途,即:
// 消除噪音
// 隔離單個元素並連接圖像中的不同元素。
// 查找圖像中的強度凸點或孔
// 我們可以爲我們的內核選擇三種形狀:
// 矩形框:MORPH_RECT
// 十字架:MORPH_CROSS
// 橢圓:MORPH_ELLIPSE
Mat pp = getStructuringElement(MORPH_RECT,Size(10,10));
//腐蝕(侵蝕)圖像,向內有坍縮,10*10爲基準,消除周邊的顏色,用中心的顏色去填充周邊顏色。
// 這個操作是擴張的姊妹。它計算給定內核區域的局部最小值。
// 當內核在圖像上掃描時,我們計算由重疊的最小像素值,並用該最小值替換錨點下的圖像像素。
// 對於擴張的例子,我們可以將侵蝕算子應用於原始圖像
// src:源圖像
// erosion_dst:輸出圖像
// element:這是我們將用來執行操作的內核。如果我們不指定,默認是一個簡單的3x3矩陣。否則,我們可以指定它的形狀。爲此,我們需要使用函數cv :: getStructuringElement:
erode(img,img,pp);
int size = w * h;
jintArray result = env->NewIntArray(size);
env->SetIntArrayRegion(result,0,size,pixels);
env->ReleaseIntArrayElements(pixels_, pixels, 0);
return result;
}
擴張
擴張是求局部最大值算法,與腐蝕相反操作是積卷核與圖像進行積卷計算,計算出核覆蓋區域的像素點的最大值,並將最大值賦值給錨點,這樣圖像中的高亮區域就會逐漸增大。
JNIEXPORT jintArray JNICALL
Java_com_xy_opencv_ndk_1opencv002_MainActivity_erodeORdilate(JNIEnv *env, jclass type,
jintArray pixels_, jint w, jint h) {
jint *pixels = env->GetIntArrayElements(pixels_, NULL);
Mat img(h,w,CV_8UC4,pixels);
// 形態作業
//
// 簡而言之:一組基於形狀處理圖像的操作。形態操作將結構元素應用於輸入圖像並生成輸出圖像。
// 最基本的形態作用是:侵蝕和擴張。它們有廣泛的用途,即:
// 消除噪音
// 隔離單個元素並連接圖像中的不同元素。
// 查找圖像中的強度凸點或孔
// 我們可以爲我們的內核選擇三種形狀:
// 矩形框:MORPH_RECT
// 十字架:MORPH_CROSS
// 橢圓:MORPH_ELLIPSE
Mat pp = getStructuringElement(MORPH_RECT,Size(10,10));
// src:源圖像
// erosion_dst:輸出圖像
// element:這是我們將用來執行操作的內核。如果我們不指定,默認是一個簡單的3x3矩陣。否則,我們可以指定它的形狀。爲此,我們需要使用函數cv :: getStructuringElement:
//擴張
// 擴張,向外擴張
//
// 該操作包括將圖像與某些內核進行卷積,其可以具有任何形狀或尺寸,通常爲正方形或圓形。
// 內核具有定義的錨點,通常是內核的中心。
// 當內核在圖像上掃描時,我們計算由核重疊的最大像素值,並用該最大值替換錨點位置中的圖像像素。您可以推斷,這種最大化的操作會使圖像中的亮區“增長”(因此稱爲擴張)。
dilate(img,img,pp);
int size = w * h;
jintArray result = env->NewIntArray(size);
env->SetIntArrayRegion(result,0,size,pixels);
env->ReleaseIntArrayElements(pixels_, pixels, 0);
return result;
}