1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-31 08:13:04 +04:00

Merge pull request #29464 from Akansha-977:templatematch_IPP_4.x

Extracting IPP to HAL for matchTemplate function in 4.x #29464

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
Akansha-977
2026-07-10 14:46:45 +05:30
committed by GitHub
parent 93cd614472
commit 7230c1ce08
5 changed files with 193 additions and 130 deletions
+26
View File
@@ -1572,6 +1572,32 @@ inline int hal_ni_calcHist(const uchar* src_data, size_t src_step, int src_type,
#define cv_hal_calcHist hal_ni_calcHist
//! @endcond
/**
@brief Compares a template against overlapped image regions.
@param src_data Source image (single-channel, CV_8U or CV_32F) data
@param src_step Source image step
@param src_width Source image width
@param src_height Source image height
@param templ_data Template image data (same type as source)
@param templ_step Template image step
@param templ_width Template image width
@param templ_height Template image height
@param result_data Destination map data (single-channel CV_32F, size (src_width-templ_width+1) x (src_height-templ_height+1))
@param result_step Destination map step
@param depth Depth of source and template images (CV_8U or CV_32F)
@param cn Number of channels
@param method Comparison method (cv::TemplateMatchModes)
@sa matchTemplate
*/
inline int hal_ni_matchTemplate(const uchar* src_data, size_t src_step, int src_width, int src_height,
const uchar* templ_data, size_t templ_step, int templ_width, int templ_height,
float* result_data, size_t result_step, int depth, int cn, int method)
{ return CV_HAL_ERROR_NOT_IMPLEMENTED; }
//! @cond IGNORED
#define cv_hal_matchTemplate hal_ni_matchTemplate
//! @endcond
//! @}
#if defined(__clang__)
+16 -130
View File
@@ -1034,135 +1034,6 @@ static void common_matchTemplate( Mat& img, Mat& templ, Mat& result, int method,
}
}
#if defined HAVE_IPP
namespace cv
{
typedef IppStatus (CV_STDCALL * ippimatchTemplate)(const void*, int, IppiSize, const void*, int, IppiSize, Ipp32f* , int , IppEnum , Ipp8u*);
static bool ipp_crossCorr(const Mat& src, const Mat& tpl, Mat& dst, bool normed)
{
CV_INSTRUMENT_REGION_IPP();
IppStatus status;
IppiSize srcRoiSize = {src.cols,src.rows};
IppiSize tplRoiSize = {tpl.cols,tpl.rows};
IppAutoBuffer<Ipp8u> buffer;
int bufSize=0;
int depth = src.depth();
ippimatchTemplate ippiCrossCorrNorm =
depth==CV_8U ? (ippimatchTemplate)ippiCrossCorrNorm_8u32f_C1R:
depth==CV_32F? (ippimatchTemplate)ippiCrossCorrNorm_32f_C1R: 0;
if (ippiCrossCorrNorm==0)
return false;
IppEnum funCfg = (IppEnum)(+ippAlgAuto | ippiROIValid);
if(normed)
funCfg |= ippiNorm;
else
funCfg |= ippiNormNone;
status = ippiCrossCorrNormGetBufferSize(srcRoiSize, tplRoiSize, funCfg, &bufSize);
if ( status < 0 )
return false;
buffer.allocate( bufSize );
status = CV_INSTRUMENT_FUN_IPP(ippiCrossCorrNorm, src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr<Ipp32f>(), (int)dst.step, funCfg, buffer);
return status >= 0;
}
static bool ipp_sqrDistance(const Mat& src, const Mat& tpl, Mat& dst)
{
CV_INSTRUMENT_REGION_IPP();
IppStatus status;
IppiSize srcRoiSize = {src.cols,src.rows};
IppiSize tplRoiSize = {tpl.cols,tpl.rows};
IppAutoBuffer<Ipp8u> buffer;
int bufSize=0;
int depth = src.depth();
ippimatchTemplate ippiSqrDistanceNorm =
depth==CV_8U ? (ippimatchTemplate)ippiSqrDistanceNorm_8u32f_C1R:
depth==CV_32F? (ippimatchTemplate)ippiSqrDistanceNorm_32f_C1R: 0;
if (ippiSqrDistanceNorm==0)
return false;
IppEnum funCfg = (IppEnum)(+ippAlgAuto | ippiROIValid | ippiNormNone);
status = ippiSqrDistanceNormGetBufferSize(srcRoiSize, tplRoiSize, funCfg, &bufSize);
if ( status < 0 )
return false;
buffer.allocate( bufSize );
status = CV_INSTRUMENT_FUN_IPP(ippiSqrDistanceNorm, src.ptr(), (int)src.step, srcRoiSize, tpl.ptr(), (int)tpl.step, tplRoiSize, dst.ptr<Ipp32f>(), (int)dst.step, funCfg, buffer);
dst = cv::max(dst, 0); // handle edge case from rounding in variance computation which can result in negative values
return status >= 0;
}
static bool ipp_matchTemplate( Mat& img, Mat& templ, Mat& result, int method)
{
CV_INSTRUMENT_REGION_IPP();
if(img.channels() != 1)
return false;
// These functions are not efficient if template size is comparable with image size
if(templ.size().area()*4 > img.size().area())
return false;
// CV_8U SQDIFF/SQDIFF_NORMED suffer from float32 catastrophic cancellation
// in IPP's internal accumulators; fall through to the double-precision path instead.
if(img.depth() == CV_8U && (method == cv::TM_SQDIFF || method == cv::TM_SQDIFF_NORMED))
return false;
if(method == cv::TM_SQDIFF)
{
if(ipp_sqrDistance(img, templ, result))
return true;
}
else if(method == cv::TM_SQDIFF_NORMED)
{
if(ipp_crossCorr(img, templ, result, false))
{
common_matchTemplate(img, templ, result, cv::TM_SQDIFF_NORMED, 1);
return true;
}
}
else if(method == cv::TM_CCORR)
{
if(ipp_crossCorr(img, templ, result, false))
return true;
}
else if(method == cv::TM_CCORR_NORMED)
{
if(ipp_crossCorr(img, templ, result, true))
return true;
}
else if(method == cv::TM_CCOEFF || method == cv::TM_CCOEFF_NORMED)
{
if(ipp_crossCorr(img, templ, result, false))
{
common_matchTemplate(img, templ, result, method, 1);
return true;
}
}
return false;
}
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////////
void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result, int method, InputArray _mask )
@@ -1196,7 +1067,22 @@ void cv::matchTemplate( InputArray _img, InputArray _templ, OutputArray _result,
_result.create(corrSize, CV_32F);
Mat result = _result.getMat();
CV_IPP_RUN_FAST(ipp_matchTemplate(img, templ, result, method))
{
int hal_res = cv_hal_matchTemplate(img.data, img.step, img.cols, img.rows,
templ.data, templ.step, templ.cols, templ.rows,
result.ptr<float>(), result.step, depth, cn, method);
if (hal_res == CV_HAL_ERROR_OK)
{
if (method == cv::TM_SQDIFF_NORMED || method == cv::TM_CCOEFF || method == cv::TM_CCOEFF_NORMED)
common_matchTemplate(img, templ, result, method, 1);
return;
}
else if (hal_res != CV_HAL_ERROR_NOT_IMPLEMENTED)
{
CV_Error_(cv::Error::StsInternal,
("HAL implementation matchTemplate ==> cv_hal_matchTemplate returned %d (0x%08x)", hal_res, hal_res));
}
}
bool use64f = (depth == CV_8U) && (method == cv::TM_SQDIFF || method == cv::TM_SQDIFF_NORMED);
Mat result64f;