結局、自作してみる… templmatch.cpp 内にある crossCorr 関数で相関平均を計算しているのだが、フーリエ解析を使っているためか値が違う。
後でコードを見直そう。
// 実画像の位置(dx,dy)に対して、相関係数を計算する double crossCorr( const cv::Mat& img, const cv::Mat& templ, const cv::Mat& mask, int dx, int dy ) { int cnt = 0; double templMean = 0.0; // テンプレートの相加平均 double imgMean = 0.0; // 実画像の相加平均 for ( int y=0; y<templ.rows; ++y ) { for ( int x=0; x<templ.cols; ++x ) { if ( mask.at<char>(y,x) == 0 ) continue; cv::Vec3b v1 = templ.at<cv::Vec3b>(y,x); cv::Vec3b v2 = img.at<cv::Vec3b>(y+dy,x+dx); templMean += v1[0] + v1[1] + v1[2]; imgMean += v2[0] + v2[1] + v2[2]; cnt += 3; } } templMean = templMean/(double)cnt; imgMean = imgMean/(double)cnt; // 分子(numerator) double numerator = 0.0; for ( int y=0; y<templ.rows; ++y ) { for ( int x=0; x<templ.cols; ++x ) { if ( mask.at<char>(y,x) == 0 ) continue; cv::Vec3b v1 = templ.at<cv::Vec3b>(y,x); cv::Vec3b v2 = img.at<cv::Vec3b>(y+dy,x+dx); numerator += (v1[0] - templMean)*(v2[0] - imgMean); numerator += (v1[1] - templMean)*(v2[1] - imgMean); numerator += (v1[2] - templMean)*(v2[2] - imgMean); } } // 分母(denominator) double denominator_templ = 0.0; double denominator_img = 0.0; for ( int y=0; y<templ.rows; ++y ) { for ( int x=0; x<templ.cols; ++x ) { if ( mask.at<char>(y,x) == 0 ) continue; cv::Vec3b v1 = templ.at<cv::Vec3b>(y,x); cv::Vec3b v2 = img.at<cv::Vec3b>(y+dy,x+dx); denominator_templ += (v1[0] - templMean)*(v1[0] - templMean); denominator_templ += (v1[1] - templMean)*(v1[1] - templMean); denominator_templ += (v1[2] - templMean)*(v1[2] - templMean); denominator_img += (v2[0] - imgMean)*(v2[0] - imgMean); denominator_img += (v2[1] - imgMean)*(v2[1] - imgMean); denominator_img += (v2[2] - imgMean)*(v2[2] - imgMean); } } double denominator = sqrt(denominator_templ)*sqrt(denominator_img); return numerator/denominator; } // 実画像のすべてに対して相関係数を計算する void MatchTemplate( const cv::Mat& img, const cv::Mat& templ, cv::Mat& result, const cv::Mat& mask ) { cv::Size corrsize(img.cols-templ.cols, img.rows-templ.rows); result.create(corrsize, CV_64F); for ( int y=0; y<corrsize.height; ++y ) { for ( int x=0; x<corrsize.width; ++x ) { double corr = crossCorr( img, templ, mask,x,y ); result.at<double>(y,x) = corr ; } } }
ちなみに、Mat:at<> を使うとデバッグ実行ではひどく遅いのだが、Release ビルドをすると結構速い。
おそらく、mat.hpp に定義されている
template<typename _Tp> inline _Tp& Mat::at(int i0, int i1) { CV_DbgAssert( dims <= 2 && data && (unsigned)i0 < (unsigned)size.p[0] && (unsigned)(i1*DataType<_Tp>::channels) < (unsigned)(size.p[1]*channels()) && CV_ELEM_SIZE1(DataType<_Tp>::depth) == elemSize1()); return ((_Tp*)(data + step.p[0]*i0))[i1]; }
で設定されている CV_DbgAssert の関数が遅いわけで、これはリリースモードでは外れるようになっている。
この部分を、CV_DbgAssert を使わないように展開してやれば、早くなるのではないかなぁと。