第五章 使用形态学滤波对图像进行边缘及角点检测

知识点:
直线检测:原图膨胀-原图腐蚀
角点检测:result1 = 膨胀(十字)+腐蚀(菱形)(对原图进行的连续形态学滤波)
result2 = 膨胀(x 型 )+腐蚀(方形)(对原图进行的连续形态学运算)
result = abs(result1 - result2)

具体语言叙述:
1.直线检测:计算膨胀后的图像与腐蚀后图像的差值。由于这两个变换的图像不同的地方主要在边缘处,图像边缘将通过求差得到强化。这整是cv::morphologyEx在参数cv::MORPH_GRADIENT的作用原理
2.角点检测:原理是使用膨胀来进行闭运算,并使用两种不同的结构元素来应用腐蚀运算。挑选的这些元素可以确保连续的边缘不受改变,但是由于他们的重复效应,角点出的边缘仍受到影响。

MorphoFeatures.cpp:

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;

class MorphoFeatures {

private:

    // threshold to produce binary image
    //生成二值图像的阈值
    int threshold;
    // structuring elements used in corner detection
    //角点检测中用到的结构元素
    cv::Mat cross;
    cv::Mat diamond;
    cv::Mat square;
    cv::Mat x;

    //获取二值的边缘图像
    void applyThreshold(cv::Mat& result) {

        // Apply threshold on result
        //使用阈值化
        if (threshold>0)
            cv::threshold(result, result, threshold, 255, cv::THRESH_BINARY_INV);
    }

public:

    MorphoFeatures() : threshold(-1), cross(5, 5, CV_8U, cv::Scalar(0)),
        diamond(5, 5, CV_8U, cv::Scalar(1)),
        square(5, 5, CV_8U, cv::Scalar(1)),
        x(5, 5, CV_8U, cv::Scalar(0))
        //初始化列表,括号内为初始值,更适用于成员变量的常量const型。


    {

        // Creating the cross-shaped structuring element
        for (int i = 0; i<5; i++) {

            cross.at<uchar>(2, i) = 1;
            cross.at<uchar>(i, 2) = 1;
        }

        // Creating the diamond-shaped structuring element
        //菱形
        diamond.at<uchar>(0, 0) = 0;
        diamond.at<uchar>(0, 1) = 0;
        diamond.at<uchar>(1, 0) = 0;
        diamond.at<uchar>(4, 4) = 0;
        diamond.at<uchar>(3, 4) = 0;
        diamond.at<uchar>(4, 3) = 0;
        diamond.at<uchar>(4, 0) = 0;
        diamond.at<uchar>(4, 1) = 0;
        diamond.at<uchar>(3, 0) = 0;
        diamond.at<uchar>(0, 4) = 0;
        diamond.at<uchar>(0, 3) = 0;
        diamond.at<uchar>(1, 4) = 0;

        // Creating the x-shaped structuring element
        for (int i = 0; i<5; i++) {

            x.at<uchar>(i, i) = 1;
            x.at<uchar>(4 - i, i) = 1;
        }
    }

    void setThreshold(int t) {

        threshold = t;
    }

    int getThreshold() const {

        return threshold;
    }
    //直线的检测
    cv::Mat getEdges(const cv::Mat &image) {

        // Get the gradient image 形态学梯度=膨胀-腐蚀
        //得到梯度图
        cv::Mat result;
        cv::morphologyEx(image, result, cv::MORPH_GRADIENT, cv::Mat());

        // Apply threshold to obtain a binary image 阈值化以得到二值化图像
        applyThreshold(result);
        return result;
    }

    cv::Mat getCorners(const cv::Mat &image) {

        cv::Mat result;

        // Dilate with a cross
        //十字膨胀
        cv::dilate(image, result, cross);

        // Erode with a diamond
        cv::erode(result, result, diamond);

        cv::Mat result2;
        // Dilate with a X  
        cv::dilate(image, result2, x);

        // Erode with a square
        cv::erode(result2, result2, square);

        // Corners are obtained by differencing
        // the two closed images
        cv::absdiff(result2, result, result);

        // Apply threshold to obtain a binary image
        applyThreshold(result);

        return result;
    }

    //为了更好的可视化,在二值图像中的每个监测点上绘制圆
    void drawOnImage(const cv::Mat& binary, cv::Mat& image) {

        cv::Mat_<uchar>::const_iterator it = binary.begin<uchar>();
        cv::Mat_<uchar>::const_iterator itend = binary.end<uchar>();

        // for each pixel   
        for (int i = 0; it != itend; ++it, ++i) {
            if (!*it)
                cv::circle(image, cv::Point(i%image.step, i / image.step), 5, cv::Scalar(255, 0, 0));
        }
    }
};

main.cpp:

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "MorphoFeatures.cpp"
    using namespace std;
    using namespace cv;

int main()
{
        // Read input image

        cv::Mat image = cv::imread("D:/test.jpg", 0);
        if (!image.data)
            return 0;

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

        // Create the morphological features instance

        MorphoFeatures morpho;
        morpho.setThreshold(40);

        // Get the edges
        //得到边缘图像
        cv::Mat edges;
        edges = morpho.getEdges(image);

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

        cv::Mat corners;
        corners = morpho.getCorners(image);
        morpho.drawOnImage(corners, image);
        cv::namedWindow("Corners on Image");
        cv::imshow("Corners on Image", image);
        cv::waitKey();
        return 0;
    }

猜你喜欢

转载自blog.csdn.net/a839766550/article/details/78278572
今日推荐