6,027次阅读

形态学角点检测

角点

– 一阶导数(即灰度的梯度)的局部最大所对应的像素点；

– 两条及两条以上边缘的交点；

– 图像中梯度值和梯度方向的变化速率都很高的点；

– 角点处的一阶导数最大，二阶导数为零，指示物体边缘变化不连续的方向。

形态学

二 数学形态学的定义和分类

（2）灰度数学形态学

1. 如果结构元素的值都为正的，则输出图像会比输入图像亮（或暗）；

2. 根据输入图像中暗（或亮）细节的灰度值以及它们的形状相对于结构元素的关系，它们在运算中或被消减或被除掉。灰度数学形态学中开启和闭合运算的定义与在二值数学形态学中的定义一致。用b对f进行开启和闭合运算的定义为：

实验分析

//MORPHOF.h
#pragma once
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

#include <stdio.h>
#include <tchar.h>

#if !defined MORPHOF
#define MORPHOF

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>

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)){

// 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;

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

return result;
}

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

cv::Mat result;
//添加这么显示窗口是为了看到每一步的处理结果，仅用于debug使用，方便理解
// Dilate with a cross
cv::dilate(image,result,cross);
cv::namedWindow("cross Image");
cv::imshow("cross Image",result);
///cv::waitKey(0);
// Erode with a diamond
cv::erode(result,result,diamond);
cv::namedWindow("erode Image");
cv::imshow("erode Image",result);
//cv::waitKey(0);
cv::Mat result2;
// Dilate with a X
cv::dilate(image,result2,x);
cv::namedWindow("X Image");
cv::imshow("X Image",result2);
//cv::waitKey(0);
// Erode with a square
cv::erode(result2,result2,square);
cv::namedWindow("square Image");
cv::imshow("square Image",result2);
//cv::waitKey(0);
// Corners are obtained by differencing
// the two closed images
cv::absdiff(result2,result,result);
cv::namedWindow("absdiff Image");
cv::imshow("absdiff Image",result);
cv::waitKey(0);
// Apply threshold to obtain a binary image
applyThreshold(result);
//添加这么显示窗口是为了看到每一步的处理结果，仅用于debug使用，方便理解
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));
}
}
};

#endif

//MAIN.CPP
#include"MORPHOF.h"
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

int main()
{
// Read input image
//binanry test
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);

// Get the corners
morpho.setThreshold(-1);
cv::Mat corners;
corners= morpho.getCorners(image);
cv::morphologyEx(corners,corners,cv::MORPH_TOPHAT,cv::Mat());
cv::threshold(corners, corners, 40, 255, cv::THRESH_BINARY_INV);

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

// Display the corner on the image
morpho.drawOnImage(corners,image);
cv::namedWindow("Corners on Image");
cv::imshow("Corners on Image",image);
cv::waitKey(0);
}

>> image=zeros(200,200);

>> image(50:150,50:150)=1;

>> imshow(image,[]);

>> saveas(gcf,'binary3','bmp');

cross十字型膨胀之后：

diamond腐蚀之后：

x模板膨胀之后：

Square腐蚀之后：