參考:https://blog.csdn.net/DeepVL/article/details/52346821
https://blog.csdn.net/bagboy_taobao_com/article/details/5574159
https://blog.csdn.net/kksc1099054857/article/details/76552976
形態學是基於形狀的一系列圖像處理操作,基本運算包括:腐蝕、膨脹、開、閉等。
基本原理
膨脹:就是利用一個核(叫做結構元素)與圖像進行卷積。隨着核的移動,每次都取核覆蓋區域的最大像素值,因此最終完成的效果是將高亮區域擴大。
腐蝕:也是卷積操作。隨着核的移動,每次都取核覆蓋區域的最小像素值,因此最終完成的效果是將高亮區域縮小。
形態學可應用於二值圖、灰度圖,甚至彩色圖
詳細的
腐蝕是一種消除邊界點,使邊界向內部收縮的過程。可以用來消除小且無意義的物體。
腐蝕的算法:
用3x3的結構元素,掃描圖像的每一個像素
用結構元素與其覆蓋的二值圖像做“與”操作
如果都爲1,結果圖像的該像素爲1。否則爲0。
結果:使二值圖像減小一圈
膨脹是將與物體接觸的所有背景點合併到該物體中,使邊界向外部擴張的過程。可以用來填補物體中的空洞。
膨脹的算法:
用3x3的結構元素,掃描圖像的每一個像素
用結構元素與其覆蓋的二值圖像做“與”操作
如果都爲0,結果圖像的該像素爲0。否則爲1
結果:使二值圖像擴大一圈
基本功能
去除噪聲
分離出獨立的元素或則連接獨立的元素
可以求圖像梯度或則圖像中的小洞
函數原型:
膨脹:dilate函數
函數原型:
void dilate(InputArray src,
OutputArray dst,
InputArray kernel,
Point anchor=Point(-1,-1),
int iterations=1,
int borderType=BORDER_CONSTANT,
const Scalar& borderValue=morphologyDefaultBorderValue()
);
參數解析:
第一個參數:InputArray類型的src,源圖像,Mat類的對象。
第二個參數:OutputArray類型的dst,目標圖像,與源圖像有相同的尺寸和類型。
第三個參數:InputArray類型的kernel,膨脹操作的核。當爲NULL是,表示使用參考點位於中心3X3的核。
一般與getStructuringElement函數配合使用。函數介紹:http://blog.csdn.net/kksc1099054857/article/details/76569718
第四個參數:Point類型的anchor,錨的位置,有默認值(-1,-1),表示錨的中心。
第五個參數:int類型的iterations,迭代使用dilate()函數的次數,默認值爲。
第六個參數:int類型的borderType,用於推斷圖像外部像素的某種邊界模式。
第七個參數:const Scalar&類型的borderValue,當邊界爲常數時的邊界值,用默認值morphologyDefaultBorderValue(),一般不去管它。
結論:
橢圓形邊界結構效果更好
例子
python:
import cv2
import numpy as np
img = cv2.imread(‘j.png’,0)
kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(img,kernel,iterations = 1)
c++
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "highgui.h"
#include <stdlib.h>
#include <stdio.h>
using namespace cv;
/// 全局變量
Mat src, erosion_dst, dilation_dst;
int erosion_elem = 0;
int erosion_size = 0;
int dilation_elem = 0;
int dilation_size = 0;
int const max_elem = 2;
int const max_kernel_size = 21;
/** Function Headers */
void Erosion(int, void*);//腐蝕操作
void Dilation(int, void*);//膨脹操作
/** @function main */
int main()
{
/// Load an image
src = imread("D:/xingtaixue//xx.png");
if (!src.data)
{
return -1;
}
/// Create windows
namedWindow("Erosion Demo", CV_WINDOW_AUTOSIZE);
namedWindow("Dilation Demo", CV_WINDOW_AUTOSIZE);
//Element:\n 0: Rect \n 1: Cross \n 2: Ellipse
/// 腐蝕操作滾動條
createTrackbar("Element:", "Erosion Demo", &erosion_elem, max_elem, Erosion);
createTrackbar("Kernel", "Erosion Demo", &erosion_size, max_kernel_size, Erosion);
/// 膨脹操作滾動條
createTrackbar("Element:", "Dilation Demo", &dilation_elem, max_elem, Dilation);
createTrackbar("Kernel", "Dilation Demo", &dilation_size, max_kernel_size, Dilation);
// 開始
Erosion(0, 0);
Dilation(0, 0);
waitKey(0);
return 0;
}
/** @function Erosion */
void Erosion(int, void*)
{
int erosion_type;
if (erosion_elem == 0)
{
erosion_type = MORPH_RECT; //矩形結構元素
}
else if (erosion_elem == 1)
{
erosion_type = MORPH_CROSS; //十字結構元素
}
else if (erosion_elem == 2)
{
erosion_type = MORPH_ELLIPSE;//橢圓結構元素
}
//生成核(結構元素)
Mat element = getStructuringElement(erosion_type, Size(2 * erosion_size + 1, 2 * erosion_size + 1),
Point(erosion_size, erosion_size));
//腐蝕操作
erode(src, erosion_dst, element);
imshow("Erosion Demo", erosion_dst);
}
/** @function Dilation */
void Dilation(int, void*)
{
int dilation_type;
if (dilation_elem == 0)
{
dilation_type = MORPH_RECT; //矩形結構元素
}
else if (dilation_elem == 1)
{
dilation_type = MORPH_CROSS; //十字結構元素
}
else if (dilation_elem == 2)
{
dilation_type = MORPH_ELLIPSE; //橢圓結構元素
}
//生成核(結構元素)
Mat element = getStructuringElement(dilation_type, Size(2 * dilation_size + 1, 2 * dilation_size + 1),
Point(dilation_size, dilation_size));
//腐蝕操作
dilate(src, dilation_dst, element);
imshow("Dilation Demo", dilation_dst);
}