形态学应用-开闭运算

不调用函数实现开闭运算,c++代码实现

开运算:先腐蚀后膨胀;

闭运算:先膨胀后腐蚀。

开运算:

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
    //读入图片,将彩色图片转化为二值图片
    Mat srcImg = imread("F:\\work_three_grade\\DigitalImage\\fish.jpg");
    Mat grayImg(srcImg.size(), CV_8U);
    cvtColor(srcImg, grayImg, CV_RGB2GRAY, 0);
    Mat binaryImg(grayImg.size(), grayImg.type());
    threshold(grayImg, binaryImg, 100, 255, THRESH_BINARY);

    //cout << "binaryImg" << binaryImg.channels() << endl;//1个通道
    
    int h = binaryImg.rows;
    int w = binaryImg.cols;

    //模板,把中心的点作为锚点,即(1,1)点,作为理想中的原点
    //uchar s[3][3] = { {1,1,0},{1,1,0},{1,0,0} };
    uchar s[5][5] = { {1,1,1,0,0},{1,1,0,0,0},{1,0,0,0,0},{1,0,0,0,0},{1,1,0,0,0} };

    //定义一个新的图片,进行第一步,先腐蚀
    Mat erodeImg(binaryImg.rows, binaryImg.cols,binaryImg.type()); 
    for (int i = 0; i < h; i++)
    {
        for (int j = 0; j < w; j++)
        {
            erodeImg.at<uchar>(i, j) = 0;
        }
    } 
      
    //下面是对二值图片进行腐蚀操作
    int j1 = 0;
    for (int i = 0; i < h - 4; i++) //原图像
    {
        for (int j = 0; j < w - 4; j++)
        {

            for (int i1 = 0; i1 < 5; i1++) //模板
            {
                for (j1 = 0; j1 < 5; j1++)
                {
                    if (s[i1][j1] == 1) //若是模板为1,查看二值图片的像素值是否为255
                    {
                        if (binaryImg.at<uchar>(i1 + i, j1 + j) != 255) //如果有不是的,就跳出循环
                        {
                            break;
                        }

                    }
                }
                if (i1 == 4 && j1 == 5) //遍历完模板,符合要求,将锚点所在位置像素设为255
                {
                    erodeImg.at<uchar>(i + 2, j + 2) = 255;
                }
                if (j1 != 5) //里面的循环通过break跳出的
                {
                    break;
                }
            }
        }
    }

    //定义一个新的图片,进行第二步,后膨胀,使用同一个模板
    Mat dilImg(erodeImg.rows, erodeImg.cols, erodeImg.type());
    for (int i = 0; i < h; i++)
    {
        for (int j = 0; j < w; j++)
        {
            dilImg.at<uchar>(i, j) = 0;
        }
    }
    //下面是对二值图片进行膨胀操作
    int j2 = 0;
    for (int i = 0; i < h - 4; i++)
    {
        for (int j = 0; j < w - 4; j++)
        {

            for (int i1 = 0; i1 < 5; i1++)
            {
                for (j2 = 0; j2 < 5; j2++)
                {
                    if (s[i1][j2] == 1)
                    {
                        if (erodeImg.at<uchar>(i+i1, j+j2) == 255) 
                        {
                 //只要有一个点 dilImg.at
<uchar>(i + 2, j + 2) = 255; break; } } } if (i1 != 4 || j2 != 5) //说明是上面是break出来的 { break; } } } } namedWindow("srcimgwindow", CV_WINDOW_NORMAL); namedWindow("binaryImgwindow", CV_WINDOW_NORMAL); namedWindow("erodeImgImgwindow", CV_WINDOW_NORMAL); namedWindow("dilImgImgwindow", CV_WINDOW_NORMAL); //原图片 imshow("srcimgwindow", srcImg); //二值图片 imshow("binaryImgwindow",binaryImg ); //先腐蚀之后的图片 imshow("erodeImgImgwindow", erodeImg); //后膨胀之后的图片 imshow("dilImgImgwindow", dilImg); waitKey(1000000); return 0; }
 

 

 闭运算;

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
    //读入图片,将彩色图片转化为二值图片
    Mat srcImg = imread("F:\\work_three_grade\\DigitalImage\\fish.jpg");
    Mat grayImg(srcImg.size(), CV_8U);
    cvtColor(srcImg, grayImg, CV_RGB2GRAY, 0);
    Mat binaryImg(grayImg.size(), grayImg.type());
    threshold(grayImg, binaryImg, 100, 255, THRESH_BINARY);

    //cout << "binaryImg" << binaryImg.channels() << endl;//1个通道

    int h = binaryImg.rows;
    int w = binaryImg.cols;

    //模板,把中心的点作为锚点,即(1,1)点,作为理想中的原点
    //uchar s[3][3] = { {1,1,0},{1,1,0},{1,0,0} };
    uchar s[5][5] = { {1,1,1,0,0},{1,1,0,0,0},{1,0,0,0,0},{1,0,0,0,0},{1,1,0,0,0} };

    //对模板做关于原点的映射
    uchar ss[5][5];
    for (int i = 0; i < 5; i++)
    {
        for (int j = 0; j < 5; j++)
        {
            ss[i][j] = s[j][i];
        }
    }

    //定义一个新的图片,进行第一步,膨胀
    Mat dilImg(binaryImg.rows, binaryImg.cols, binaryImg.type());
    for (int i = 0; i < h; i++)
    {
        for (int j = 0; j < w; j++)
        {
            dilImg.at<uchar>(i, j) = 0;
        }
    }

    //下面是对二值图片进行膨胀操作
    int j2 = 0;
    for (int i = 0; i < h - 4; i++)
    {
        for (int j = 0; j < w - 4; j++)
        {

            for (int i1 = 0; i1 < 5; i1++)
            {
                for (j2 = 0; j2 < 5; j2++)
                {
                    if (ss[i1][j2] == 1)
                    {
                        if (binaryImg.at<uchar>(i + i1, j + j2) == 255)
                        {
                            //只要有一个点
                            dilImg.at<uchar>(i + 2, j + 2) = 255;
                            break;
                        }

                    }
                }
                if (i1 != 4 || j2 != 5) //说明是上面是break出来的
                {
                    break;
                }
            }
        }
    }
    //定义一个新的图片,进行第二步,腐蚀
    Mat erodeImg(dilImg.rows, dilImg.cols, dilImg.type());
    for (int i = 0; i < h; i++)
    {
        for (int j = 0; j < w; j++)
        {
            erodeImg.at<uchar>(i, j) = 0;
        }
    }

    //下面是对二值图片进行腐蚀操作
    int j1 = 0;
    for (int i = 0; i < h - 4; i++) //原图像
    {
        for (int j = 0; j < w - 4; j++)
        {

            for (int i1 = 0; i1 < 5; i1++) //模板
            {
                for (j1 = 0; j1 < 5; j1++)
                {
                    if (s[i1][j1] == 1) //若是模板为1,查看二值图片的像素值是否为255
                    {
                        if (dilImg.at<uchar>(i1 + i, j1 + j) != 255) //如果有不是的,就跳出循环
                        {
                            break;
                        }

                    }
                }
                if (i1 == 4 && j1 == 5) //遍历完模板,符合要求,将锚点所在位置像素设为255
                {
                    erodeImg.at<uchar>(i + 2, j + 2) = 255;
                }
                if (j1 != 5) //里面的循环通过break跳出的
                {
                    break;
                }
            }
        }
    }
      
    namedWindow("srcimgwindow", CV_WINDOW_NORMAL);
    namedWindow("binaryImgwindow", CV_WINDOW_NORMAL);
    namedWindow("erodeImgImgwindow", CV_WINDOW_NORMAL);
    namedWindow("dilImgImgwindow", CV_WINDOW_NORMAL);
    //原图片
    imshow("srcimgwindow", srcImg);
    //二值图片
    imshow("binaryImgwindow", binaryImg);
    //先膨胀之后的图片
    imshow("dilImgImgwindow", dilImg);
    //后腐蚀之后的图片
    imshow("erodeImgImgwindow", erodeImg);
    

    waitKey(1000000); 
    return 0;
}

srcImgwindow:第一张原图;

binaryImgwindow:第二张二值图片;

erodeImgwindow:第三张先腐蚀后的图片;

dilImgwindow:第四张腐蚀后又膨胀的图片,即开运算结果。

猜你喜欢

转载自www.cnblogs.com/loyolh/p/10125804.html