使用形态学滤波对图像进行腐蚀、膨胀运算

知识点:
1. 形态学理论定义了一系列运算,应用预定义的形状元素来变换一张图像。形状元素与像素相领点相交的方式确定了运算的结果。
2. 结构元素定义为像素的结构(形状),以及一个原点(锚点)。使用形态学滤波设计对图像的每个元素应用这个结构元素。当结构元素的原点与给定的像素对齐时,它与图像的相交部分定义了一组进行形态学运算的像素。
3. 腐蚀:每个像素与结构相交的集合替换成最小的像素值。腐蚀后的图像物体的尺寸会减小,可以观察到非常细小的事物(可以被认为是背景像素中的“噪声”)被完全移除了
4. 膨胀:每个像素与结构相交的集合替换成最小的像素值。膨胀后的物体更大,同时内部的一些“洞”被填满。

5.
void erode( InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );

void dilate( InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );

void erode( const Mat& src, Mat& dst, const Mat& element,Point anchor=Point(-1,-1), int iterations=1,int borderType=BORDER_CONSTANT,
const Scalar& borderValue=morphologyDefaultBorderValue() );
void dilate( const Mat& src, Mat& dst, const Mat& element,Point anchor=Point(-1,-1), int iterations=1,int borderType=BORDER_CONSTANT,
const Scalar& borderValue=morphologyDefaultBorderValue() );

可见,腐蚀和膨胀的参数完全一样。
参数:
src:原图像。
dst:目标图像。
element:腐蚀操作的内核。 如果不指定,默认为一个简单的 3 * 3的方形结构矩阵。
否则,我们就要明确指定它的形状,可以使用函数
`getStructuringElement().anchor`:默认为Point(-1,-1),内核中心点。省略时为默认值。
iterations:腐蚀次数。省略时为默认值1borderType:推断边缘类型,具体参见borderInterpolate函数。默认为BORDER_DEFAULT,省略时为默认值。
borderValue:边缘值,具体可参见createMorphoogyFilter函数。可省略。

通常情况下,我们可以使用函数getStructuringElement()来制作操作内核。

Mat getStructuringElement(int shape, Size esize, Point anchor=Point(-1,-1));


参数:
shape:内核形状,主要有MORPH_RECT,MORPH_CROSS和MORPH_ELLIPSE,分别为矩形、椭圆形和交叉形,对应的值分别为012

enum { MORPH_RECT=0, MORPH_CROSS=1, MORPH_ELLIPSE=2 };


esize:内核大小。
anchor:内核锚点,默认为内核中心点。
例:

Mat element = getStructuringElement( 0,Size( 2*i + 1, 2*i+1 ), Point(i, i ) );


  /// 腐蚀操作

erode( src, dst, element );
Mat element = getStructuringElement( 0,Size( 2*i + 1, 2*i+1 ), Point(i, i ) );


  /// 膨胀操作

dilate( src, dst, element );

6.
首先使用阈值化技术生成二值图像。形态学的管理是高(白色)像素表示为前景物体,用低(黑色)像素表示背景,则需要对图像取反,被称为之前图片的补(Complement)

二值图像:
cv::Mat resrve(cv::Mat src)
{
cv::Mat dst = src < 110;
return dst;
/*等价于if(f<th)
{
    f=255;
}
else
{
    f=0;
}
目的是将二值化的图像反转*/
}n:

main:

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

cv::Mat resrve(cv::Mat src);//二值化图像取反

int main()
{
    // Read input image
    cv::Mat image = cv::imread("D:/1.jpg", 0);
    if (!image.data)
        return 0;

    // Display the image
    cv::namedWindow("Image");
    cv::imshow("Image", image);

    //二值化
    cv::Mat thresholded, result;
    cv::threshold(image, thresholded, 110, 255, cv::THRESH_BINARY);
    cv::namedWindow("thresholded");
    cv::imshow("thresholded", thresholded);

    ///图片的补(图像求反)
    cv::Mat image2;
    image2 = resrve(thresholded);
    cv::namedWindow("resrved");
    cv::imshow("resrved", image2);

    // Erode the image腐蚀图像
    cv::Mat eroded;
    cv::erode(image2, eroded, cv::Mat());

    // Display the eroded image
    cv::namedWindow("Eroded Image");
    cv::imshow("Eroded Image", eroded);

    // Dilate the image膨胀图像
    cv::Mat dilated;
    cv::dilate(image2, dilated, cv::Mat());

    // Display the dialted image
    cv::namedWindow("Dilated Image");
    cv::imshow("Dilated Image", dilated);

    cv::waitKey(0);
    return 0;
}

cv::Mat resrve(cv::Mat src)
{
    cv::Mat dst = src < 110;
    return dst;
    /*等价于if(f<th)
{
    f=255;
}
else
{
    f=0;
}
目的是将二值化的图像反转*/
}

“`

猜你喜欢

转载自blog.csdn.net/a839766550/article/details/78276856