#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;
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));
}
}
}; #endif #include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "morphoFeatures.h" int main()
{
// Read input image
cv::Mat image= cv::imread("d:/test/opencv/building.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); // 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(); return 0;
}