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

xiaoxiao2021-02-28  91

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

边缘检测:

在形态学检测边缘时,可以使用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; }

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

转载请注明原文地址: https://www.6miu.com/read-21301.html

最新回复(0)