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

来源:互联网 发布:自动归类的软件 编辑:程序博客网 时间:2024/05/29 18:17

知识点:
直线检测:原图膨胀-原图腐蚀
角点检测: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;    }
阅读全文
0 0
原创粉丝点击