From e8d3732aafa8e757f8c5fd191878582bb1a78502 Mon Sep 17 00:00:00 2001 From: lluis Date: Mon, 9 Sep 2013 11:37:58 +0200 Subject: [PATCH 1/2] added computeNMChannels helper function to compute the diferent channels to be processed independently in the N&M algorithm. --- .../include/opencv2/objdetect/erfilter.hpp | 23 ++++ modules/objdetect/src/erfilter.cpp | 116 ++++++++++++++++++ 2 files changed, 139 insertions(+) diff --git a/modules/objdetect/include/opencv2/objdetect/erfilter.hpp b/modules/objdetect/include/opencv2/objdetect/erfilter.hpp index 275ed422a7..78b5847662 100644 --- a/modules/objdetect/include/opencv2/objdetect/erfilter.hpp +++ b/modules/objdetect/include/opencv2/objdetect/erfilter.hpp @@ -193,5 +193,28 @@ CV_EXPORTS Ptr createERFilterNM1(const Ptr& cb = P CV_EXPORTS Ptr createERFilterNM2(const Ptr& cb = Ptr(), float minProbability = 0.3); + +// computeNMChannels operation modes +enum { ERFILTER_NM_RGBLGrad = 0, + ERFILTER_NM_IHSGrad = 1 + }; + +/*! + Compute the different channels to be processed independently in the N&M algorithm + Neumann L., Matas J.: Real-Time Scene Text Localization and Recognition, CVPR 2012 + + In N&M algorithm, the combination of intensity (I), hue (H), saturation (S), and gradient + magnitude channels (Grad) are used in order to obtain high localization recall. + This implementation also provides an alternative combination of red (R), green (G), blue (B), + lightness (L), and gradient magnitude (Grad). + + \param _src Source image. Must be RGB CV_8UC3. + \param _channels Output vector where computed channels are stored. + \param _mode Mode of operation. Currently the only available options are + ERFILTER_NM_RGBLGrad (by default) and ERFILTER_NM_IHSGrad. + +*/ +CV_EXPORTS void computeNMChannels(InputArray _src, OutputArrayOfArrays _channels, int _mode = ERFILTER_NM_RGBLGrad); + } #endif // _OPENCV_ERFILTER_HPP_ diff --git a/modules/objdetect/src/erfilter.cpp b/modules/objdetect/src/erfilter.cpp index 76603afd3e..01b75ca4ae 100644 --- a/modules/objdetect/src/erfilter.cpp +++ b/modules/objdetect/src/erfilter.cpp @@ -1141,4 +1141,120 @@ Ptr createERFilterNM2(const Ptr& cb, float minProb filter->setMinProbability(minProbability); return (Ptr)filter; } + + +/* ------------------------------------------------------------------------------------*/ +/* -------------------------------- Compute Channels NM -------------------------------*/ +/* ------------------------------------------------------------------------------------*/ + + +void get_gradient_magnitude(Mat& _grey_img, Mat& _gradient_magnitude); + +void get_gradient_magnitude(Mat& _grey_img, Mat& _gradient_magnitude) +{ + Mat C = Mat_(_grey_img); + + Mat kernel = (Mat_(1,3) << -1,0,1); + Mat grad_x; + filter2D(C, grad_x, -1, kernel, Point(-1,-1), 0, BORDER_DEFAULT); + + Mat kernel2 = (Mat_(3,1) << -1,0,1); + Mat grad_y; + filter2D(C, grad_y, -1, kernel2, Point(-1,-1), 0, BORDER_DEFAULT); + + for(int i=0; i(i,j) = sqrt(pow(grad_x.at(i,j),2)+pow(grad_y.at(i,j),2)); +} + + +/*! + Compute the diferent channels to be processed independently in the N&M algorithm + Neumann L., Matas J.: Real-Time Scene Text Localization and Recognition, CVPR 2012 + + In N&M algorithm, the combination of intensity (I), hue (H), saturation (S), and gradient + magnitude channels (Grad) are used in order to obatin high localization recall. + This implementation also the alternative combination of red (R), grren (G), blue (B), + lightness (L), and gradient magnitude (Grad). + + \param _src Source image. Must be RGB CV_8UC3. + \param _channels Output vector where computed channels are stored. + \param _mode Mode of operation. Currently the only available options are + ERFILTER_NM_RGBLGrad and ERFILTER_NM_IHSGrad. + +*/ +void computeNMChannels(InputArray _src, OutputArrayOfArrays _channels, int _mode) +{ + + CV_Assert( ( _mode == ERFILTER_NM_RGBLGrad ) || ( _mode == ERFILTER_NM_IHSGrad ) ); + + Mat src = _src.getMat(); + if( src.empty() ) + { + _channels.release(); + return; + } + + // assert RGB image + CV_Assert(src.type() == CV_8UC3); + + if (_mode == ERFILTER_NM_IHSGrad) + { + _channels.create( 4, 1, src.depth()); + + Mat hsv; + cvtColor(src, hsv, COLOR_RGB2HSV); + vector channelsHSV; + split(hsv, channelsHSV); + + for (int i = 0; i < src.channels(); i++) + { + _channels.create(src.rows, src.cols, CV_8UC1, i); + Mat channel = _channels.getMat(i); + channelsHSV.at(i).copyTo(channel); + } + + Mat grey; + cvtColor(src, grey, COLOR_RGB2GRAY); + Mat gradient_magnitude = Mat_(grey.size()); + get_gradient_magnitude( grey, gradient_magnitude); + gradient_magnitude.convertTo(gradient_magnitude, CV_8UC1); + + _channels.create(src.rows, src.cols, CV_8UC1, 3); + Mat channelGrad = _channels.getMat(3); + gradient_magnitude.copyTo(channelGrad); + + } else if (_mode == ERFILTER_NM_RGBLGrad) { + + _channels.create( 5, 1, src.depth()); + + vector channelsRGB; + split(src, channelsRGB); + for (int i = 0; i < src.channels(); i++) + { + _channels.create(src.rows, src.cols, CV_8UC1, i); + Mat channel = _channels.getMat(i); + channelsRGB.at(i).copyTo(channel); + } + + Mat hls; + cvtColor(src, hls, COLOR_RGB2HLS); + vector channelsHLS; + split(hls, channelsHLS); + + _channels.create(src.rows, src.cols, CV_8UC1, 3); + Mat channelL = _channels.getMat(3); + channelsHLS.at(1).copyTo(channelL); + + Mat grey; + cvtColor(src, grey, COLOR_RGB2GRAY); + Mat gradient_magnitude = Mat_(grey.size()); + get_gradient_magnitude( grey, gradient_magnitude); + gradient_magnitude.convertTo(gradient_magnitude, CV_8UC1); + + _channels.create(src.rows, src.cols, CV_8UC1, 4); + Mat channelGrad = _channels.getMat(4); + gradient_magnitude.copyTo(channelGrad); + } +} } From ad9462803892b4d883e95b9e7c151bf474bfb55b Mon Sep 17 00:00:00 2001 From: lluis Date: Mon, 9 Sep 2013 18:37:55 +0200 Subject: [PATCH 2/2] Using cv::magnitude instead of custom loop and Mat instead of Mat to compute gradient magnitude channel. --- modules/objdetect/src/erfilter.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/modules/objdetect/src/erfilter.cpp b/modules/objdetect/src/erfilter.cpp index 01b75ca4ae..c231a513c5 100644 --- a/modules/objdetect/src/erfilter.cpp +++ b/modules/objdetect/src/erfilter.cpp @@ -1152,19 +1152,17 @@ void get_gradient_magnitude(Mat& _grey_img, Mat& _gradient_magnitude); void get_gradient_magnitude(Mat& _grey_img, Mat& _gradient_magnitude) { - Mat C = Mat_(_grey_img); + Mat C = Mat_(_grey_img); - Mat kernel = (Mat_(1,3) << -1,0,1); + Mat kernel = (Mat_(1,3) << -1,0,1); Mat grad_x; filter2D(C, grad_x, -1, kernel, Point(-1,-1), 0, BORDER_DEFAULT); - Mat kernel2 = (Mat_(3,1) << -1,0,1); + Mat kernel2 = (Mat_(3,1) << -1,0,1); Mat grad_y; filter2D(C, grad_y, -1, kernel2, Point(-1,-1), 0, BORDER_DEFAULT); - for(int i=0; i(i,j) = sqrt(pow(grad_x.at(i,j),2)+pow(grad_y.at(i,j),2)); + magnitude( grad_x, grad_y, _gradient_magnitude); } @@ -1216,7 +1214,7 @@ void computeNMChannels(InputArray _src, OutputArrayOfArrays _channels, int _mode Mat grey; cvtColor(src, grey, COLOR_RGB2GRAY); - Mat gradient_magnitude = Mat_(grey.size()); + Mat gradient_magnitude = Mat_(grey.size()); get_gradient_magnitude( grey, gradient_magnitude); gradient_magnitude.convertTo(gradient_magnitude, CV_8UC1); @@ -1248,7 +1246,7 @@ void computeNMChannels(InputArray _src, OutputArrayOfArrays _channels, int _mode Mat grey; cvtColor(src, grey, COLOR_RGB2GRAY); - Mat gradient_magnitude = Mat_(grey.size()); + Mat gradient_magnitude = Mat_(grey.size()); get_gradient_magnitude( grey, gradient_magnitude); gradient_magnitude.convertTo(gradient_magnitude, CV_8UC1);