/*------------------------------------------------------------------------------------------*\ This file contains material supporting chapter 5 of the cookbook: Computer Vision Programming using the OpenCV Library. by Robert Laganiere, Packt Publishing, 2011. This program is free software; permission is hereby granted to use, copy, modify, and distribute this source code, or portions thereof, for any purpose, without fee, subject to the restriction that the copyright notice may not be removed or altered from any source or altered source distribution. The software is released on an as-is basis and without any warranties of any kind. In particular, the software is not guaranteed to be fault-tolerant or free from failure. The author disclaims all warranties with regard to this software, any use, and any consequent failure, is purely the responsibility of the user. Copyright (C) 2010-2011 Robert Laganiere, www.laganiere.name \*------------------------------------------------------------------------------------------*/ #if !defined MORPHOF #define MORPHOF #include #include 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(2,i)= 1; cross.at(i,2)= 1; } // Creating the diamond-shaped structuring element diamond.at(0,0)= 0; diamond.at(0,1)= 0; diamond.at(1,0)= 0; diamond.at(4,4)= 0; diamond.at(3,4)= 0; diamond.at(4,3)= 0; diamond.at(4,0)= 0; diamond.at(4,1)= 0; diamond.at(3,0)= 0; diamond.at(0,4)= 0; diamond.at(0,3)= 0; diamond.at(1,4)= 0; // Creating the x-shaped structuring element for (int i=0; i<5; i++) { x.at(i,i)= 1; x.at(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_::const_iterator it= binary.begin(); cv::Mat_::const_iterator itend= binary.end(); // 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