mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 00:03:03 +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:
@@ -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__)
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user