计算机视觉讨论群162501053
收入囊中
- 形态学膨胀腐蚀实现角点检测
葵花宝典
角点检测的方法仁者见仁,智者见智。
今天,我挑选了OpenCV2_Computer_Vision_Application_Programming_Cookbook里面的代码带来角点检测。
另外,附上自己在之前实现的harris角点检测openCV2马拉松第19圈——Harris角点检测(自己实现)
首先给大家看一下4种结构矩阵
我的原始矩阵如下
用cross膨胀再用diamond腐蚀后得到
发现角被磨掉了
用x膨胀再用square腐蚀后磨损的更多。
然后两个结果相减,角点就被检测出来了。
荷枪实弹
下面是创建4个结构矩阵的代码
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;
}
}
Mat getCorners(const Mat &image) {
Mat result;
// Dilate with a cross
dilate(image,result,cross);
// Erode with a diamond
erode(result,result,diamond);
Mat result2;
// Dilate with a X
dilate(image,result2,x);
// Erode with a square
erode(result2,result2,square);
// Corners are obtained by differencing
// the two closed images
absdiff(result2,result,result);
// Apply threshold to obtain a binary image
applyThreshold(result);
return result;
}
完整实现
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace cv;
using namespace std;
class MorphoFeatures {
private:
int threshold;
Mat cross;
Mat diamond;
Mat square;
Mat x;
void applyThreshold(Mat& result) {
if (threshold>0)
cv::threshold(result, result,threshold, 255, 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 x) {
threshold = x;
}
Mat getCorners(const Mat &image) {
Mat result;
// Dilate with a cross
dilate(image,result,cross);
// Erode with a diamond
erode(result,result,diamond);
Mat result2;
// Dilate with a X
dilate(image,result2,x);
// Erode with a square
erode(result2,result2,square);
// Corners are obtained by differencing
// the two closed images
absdiff(result2,result,result);
// Apply threshold to obtain a binary image
applyThreshold(result);
return result;
}
void drawOnImage(const Mat& binary, Mat& image) {
Mat_<uchar>::const_iterator it = binary.begin<uchar>();
Mat_<uchar>::const_iterator itend = binary.end<uchar>();
for (int i=0; it!= itend; ++it,++i) {
if (!*it)
circle(image,Point(i%image.step,i/image.step),5,Scalar(255,0,0));
}
}
};
int main( int, char** argv )
{
Mat image;
image = imread( argv[1] );
cvtColor( image, image, CV_RGB2GRAY );
MorphoFeatures morpho;
morpho.setThreshold(40);
Mat corners;
corners= morpho.getCorners(image);
morpho.drawOnImage(corners,image);
namedWindow("Corners on Image");
imshow("Corners on Image",image);
waitKey();
return 0;
}