OpenCV2编程手册笔记之 5.4形态学滤波进行边缘与角点检测

本文介绍了如何使用OpenCV的形态学滤波进行边缘和角点检测。通过MorphoFeatures类,实现了MORPH_GRADIENT进行边缘检测,并展示了自定义结构元素进行角点检测的方法,包括菱形、十字和X型结构元素的应用。
摘要由CSDN通过智能技术生成

形态学滤波还可以进行边缘和角点的检测

边缘检测:

在形态学检测边缘时,可以使用opencv库中自带的函数morphologyEx,并将其中的参数设置为MORPH_GRADIENT

实现上,先定义一个MorphoFeatures类,getEdges方法通过morphologyEx函数可以很容易地得到边缘。代码如下:

class MorphoFeatures
{
private:
    int threshold;
public:
    void setThreshold(int t);
    cv::Mat getEdges(const cv::Mat &image);
    void applyThreshold(cv::Mat &result);
};


void MorphoFeatures::setThreshold(int t)
{
    threshold = t;
}

cv::Mat MorphoFeatures::getEdges(const cv::Mat &image)
{
    cv::Mat result;
    cv::Mat element = cv::getStructuringElement(0,
        cv::Size(5, 5),
        cv::Point(3, 3));
    cv::morphologyEx(image, result, cv::MORPH_GRADIENT, element);
    applyThreshold(result);
    return result;
}

void MorphoFeatures::applyThreshold(cv::Mat &result)
{
    if (threshold > 0)
    {
        cv::threshold(result, result, threshold, 255, cv::THRESH_BINARY);
    }
}


int main()
{
    cv::Mat image = cv::imread("F:\\building.jpg", 0);
    MorphoFeatures morpho;
    morpho.setThreshold(80);
    cv::Mat edges;
    edges = morpho.getEdges(image);
    cv::imshow("1", edges);
    cv::waitKey(0);
    return 0;
}

即可很容易得到边缘图片



角点检测:

由于opencv没有直接实现形态学检测角点,因而我们需要使用非方形结构,包括菱形、十字、X型等等,这在类中会有体现。

在MorphoFeatures类的最开始,使用重构,初始化private中的变量;然后再进行创建元素

原理想法:

如果将图像以灰度图的形式显示, 那么边缘可以看作是明亮和灰暗像素的快速过渡,可以看作陡峭的悬崖

因而,在角点检测的时候,可以采取:

十字膨胀+菱形腐蚀->结果1

X型膨胀+方形腐蚀->结果2

二者相减得到角点图片

(具体原理等我搞明白数学之后补充)

在这之后,我改动了书上的代码,使用了另一种形式:

采用二值化图像+0判断选取角点,具体代码如下:


MorphoFeatures类:

class MorphoFeatures
{
private:
    int threshold;
    cv::Mat cross;
    cv::Mat diamond;
    cv::Mat square;
    cv::Mat x;
public:
    void setThreshold(int t);
    cv::Mat getEdges(const cv::Mat &image);
    void applyThreshold(cv::Mat &result);
    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))
    {
        for (int i = 0; i<5; i++)
        {
            cross.at<uchar>(2, i) = 1;
            cross.at<uchar>(i, 2) = 1;
        }

        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;

        for (int i = 0; i<5; i++) {

            x.at<uchar>(i, i) = 1;
            x.at<uchar>(4 - i, i) = 1;
        }
    }
    cv::Mat getCorners(const cv::Mat &image);
    void drawOnImage(const cv::Mat& binary, cv::Mat& image);
};


MorphoFeatures的cpp:

void MorphoFeatures::setThreshold(int t)
{
    threshold = t;
}

cv::Mat MorphoFeatures::getEdges(const cv::Mat &image)
{
    cv::Mat result;
    cv::Mat element = cv::getStructuringElement(0,
        cv::Size(5, 5),
        cv::Point(3, 3));
    cv::morphologyEx(image, result, cv::MORPH_GRADIENT, element);
    applyThreshold(result);
    return result;
}

void MorphoFeatures::applyThreshold(cv::Mat &result)
{
    if (threshold > 0)
    {
        cv::threshold(result, result, threshold, 255, cv::THRESH_BINARY);
    }
}

cv::Mat MorphoFeatures::getCorners(const cv::Mat &image)
{
    cv::Mat result;
    cv::dilate(image, result, cross);
    cv::erode(result, result, diamond);
    cv::Mat result2;
    cv::dilate(image, result2, x);
    cv::erode(result2, result2, square);
    cv::absdiff(result2, result, result);
    applyThreshold(result);
    return result;
}

void MorphoFeatures::drawOnImage(const cv::Mat& binary, cv::Mat& image)
{
    for (int i = 0; i < binary.rows; i++)
    {
        for (int j = 0; j < binary.cols; j++)
        {
            if (binary.at<uchar>(i, j) != 0)
            {
                cv::circle(image, cv::Point(j, i), 5, cv::Scalar(255, 0, 0));
            }
        }
    }
}


主函数:

int main()
{
    cv::Mat image = cv::imread("F:\\building.jpg", 0);
    cv::Mat image2 = cv::imread("F:\\building.jpg");
    cv::Mat corners;
    cv::Mat twoValue;
    MorphoFeatures morpho;
    corners = morpho.getCorners(image);
    cv::imshow("1", corners);
    cv::threshold(corners, twoValue, 30, 255, 0);
    morpho.drawOnImage(twoValue, image2);
    cv::imshow("12", image2);
    cv::waitKey(0);
    return 0;
}


先这样吧,接着看数学了。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值