const float h) :
src_(src), dst_(dst)
{
- CV_Assert(src.channels() == sizeof(T)); //T is Vec1b or Vec2b or Vec3b
+ CV_Assert(src.channels() == pixelInfo<T>::channels);
template_window_half_size_ = template_window_size / 2;
search_window_half_size_ = search_window_size / 2;
border_size_ = search_window_half_size_ + template_window_half_size_;
copyMakeBorder(src_, extended_src_, border_size_, border_size_, border_size_, border_size_, BORDER_DEFAULT);
- const IT max_estimate_sum_value = (IT)search_window_size_ * (IT)search_window_size_ * 255;
+ const IT max_estimate_sum_value =
+ (IT)search_window_size_ * (IT)search_window_size_ * (IT)pixelInfo<T>::sampleMax();
fixed_point_mult_ = std::numeric_limits<IT>::max() / max_estimate_sum_value;
// precalc weight for every possible l2 dist between blocks
// additional optimization of precalced weights to replace division(averaging) by binary shift
+ // squared distances are truncated to 16 bits to get a reasonable table size
CV_Assert(template_window_size_ <= 46340); // sqrt(INT_MAX)
int template_window_size_sq = template_window_size_ * template_window_size_;
- almost_template_window_size_sq_bin_shift_ = getNearestPowerOf2(template_window_size_sq);
+ almost_template_window_size_sq_bin_shift_ =
+ getNearestPowerOf2(template_window_size_sq) + 2*pixelInfo<T>::sampleBits() - 16;
double almost_dist2actual_dist_multiplier = ((double)(1 << almost_template_window_size_sq_bin_shift_)) / template_window_size_sq;
- IT max_dist = 255 * 255 * sizeof(T);
+ IT max_dist =
+ (IT)pixelInfo<T>::sampleMax() * (IT)pixelInfo<T>::sampleMax() * (IT)pixelInfo<T>::channels;
int almost_max_dist = (int)(max_dist / almost_dist2actual_dist_multiplier + 1);
almost_dist2weight_.resize(almost_max_dist);
using namespace cv;
-template <typename T, typename IT> struct calcDist_
+template <typename T> struct pixelInfo_
{
- static inline IT f(const T a, const T b);
+ static const int channels = 1;
+ typedef T sampleType;
};
-template <typename IT> struct calcDist_<uchar, IT>
+template <typename ET, int n> struct pixelInfo_<Vec<ET, n> >
{
- static inline IT f(uchar a, uchar b)
+ static const int channels = n;
+ typedef ET sampleType;
+};
+
+template <typename T> struct pixelInfo: public pixelInfo_<T>
+{
+ using typename pixelInfo_<T>::sampleType;
+
+ static inline sampleType sampleMax()
+ {
+ return std::numeric_limits<sampleType>::max();
+ }
+
+ static inline sampleType sampleMin()
+ {
+ return std::numeric_limits<sampleType>::min();
+ }
+
+ static inline size_t sampleBytes()
+ {
+ return sizeof(sampleType);
+ }
+
+ static inline size_t sampleBits()
+ {
+ return 8*sampleBytes();
+ }
+};
+
+template <typename T, typename IT> struct calcDist_
+{
+ static inline IT f(const T a, const T b)
{
return (IT)(a-b) * (IT)(a-b);
}
};
-template <typename IT> struct calcDist_<Vec2b, IT>
+template <typename ET, typename IT> struct calcDist_<Vec<ET, 2>, IT>
{
- static inline IT f(const Vec2b a, const Vec2b b)
+ static inline IT f(const Vec<ET, 2> a, const Vec<ET, 2> b)
{
return (IT)(a[0]-b[0])*(IT)(a[0]-b[0]) + (IT)(a[1]-b[1])*(IT)(a[1]-b[1]);
}
};
-template <typename IT> struct calcDist_<Vec3b, IT>
+template <typename ET, typename IT> struct calcDist_<Vec<ET, 3>, IT>
{
- static inline IT f(const Vec3b a, const Vec3b b)
+ static inline IT f(const Vec<ET, 3> a, const Vec<ET, 3> b)
{
return
(IT)(a[0]-b[0])*(IT)(a[0]-b[0]) +
{
static inline IT f(T a_up, T a_down, T b_up, T b_down)
{
- return calcDist<T, IT>(a_down, b_down) - calcDist<T, IT>(a_up, b_up);
+ IT A = a_down - b_down;
+ IT B = a_up - b_up;
+ return (A-B)*(A+B);
}
};
-template <typename IT> struct calcUpDownDist_<uchar, IT>
+template <typename ET, int n, typename IT> struct calcUpDownDist_<Vec<ET, n>, IT>
{
- static inline IT f(uchar a_up, uchar a_down, uchar b_up, uchar b_down)
+private:
+ typedef Vec<ET, n> T;
+public:
+ static inline IT f(T a_up, T a_down, T b_up, T b_down)
{
- IT A = a_down - b_down;
- IT B = a_up - b_up;
- return (A-B)*(A+B);
+ return calcDist<T, IT>(a_down, b_down) - calcDist<T, IT>(a_up, b_up);
}
};
template <typename T, typename IT> struct incWithWeight_
{
- static inline void f(IT* estimation, IT weight, T p);
-};
-
-template <typename IT> struct incWithWeight_<uchar, IT>
-{
- static inline void f(IT* estimation, IT weight, uchar p)
+ static inline void f(IT* estimation, IT weight, T p)
{
estimation[0] += weight * p;
}
};
-template <typename IT> struct incWithWeight_<Vec2b, IT>
+template <typename ET, typename IT> struct incWithWeight_<Vec<ET, 2>, IT>
{
- static inline void f(IT* estimation, IT weight, Vec2b p)
+ static inline void f(IT* estimation, IT weight, Vec<ET, 2> p)
{
estimation[0] += weight * p[0];
estimation[1] += weight * p[1];
}
};
-template <typename IT> struct incWithWeight_<Vec3b, IT>
+template <typename ET, typename IT> struct incWithWeight_<Vec<ET, 3>, IT>
{
- static inline void f(IT* estimation, IT weight, Vec3b p)
+ static inline void f(IT* estimation, IT weight, Vec<ET, 3> p)
{
estimation[0] += weight * p[0];
estimation[1] += weight * p[1];
template <typename T, typename IT> struct saturateCastFromArray_
{
- static inline T f(IT* estimation);
-};
-
-template <typename IT> struct saturateCastFromArray_<uchar, IT>
-{
- static inline uchar f(IT* estimation)
+ static inline T f(IT* estimation)
{
- return saturate_cast<uchar>(estimation[0]);
+ return saturate_cast<T>(estimation[0]);
}
};
-template <typename IT> struct saturateCastFromArray_<Vec2b, IT>
+template <typename ET, typename IT> struct saturateCastFromArray_<Vec<ET, 2>, IT>
{
- static inline Vec2b f(IT* estimation)
+ static inline Vec<ET, 2> f(IT* estimation)
{
- Vec2b res;
- res[0] = saturate_cast<uchar>(estimation[0]);
- res[1] = saturate_cast<uchar>(estimation[1]);
+ Vec<ET, 2> res;
+ res[0] = saturate_cast<ET>(estimation[0]);
+ res[1] = saturate_cast<ET>(estimation[1]);
return res;
}
};
-template <typename IT> struct saturateCastFromArray_<Vec3b, IT>
+template <typename ET, typename IT> struct saturateCastFromArray_<Vec<ET, 3>, IT>
{
- static inline Vec3b f(IT* estimation)
+ static inline Vec<ET, 3> f(IT* estimation)
{
- Vec3b res;
- res[0] = saturate_cast<uchar>(estimation[0]);
- res[1] = saturate_cast<uchar>(estimation[1]);
- res[2] = saturate_cast<uchar>(estimation[2]);
+ Vec<ET, 3> res;
+ res[0] = saturate_cast<ET>(estimation[0]);
+ res[1] = saturate_cast<ET>(estimation[1]);
+ res[2] = saturate_cast<ET>(estimation[2]);
return res;
}
};
dst_(dst), extended_srcs_(srcImgs.size())
{
CV_Assert(srcImgs.size() > 0);
- CV_Assert(srcImgs[0].channels() == sizeof(T));
+ CV_Assert(srcImgs[0].channels() == pixelInfo<T>::channels);
rows_ = srcImgs[0].rows;
cols_ = srcImgs[0].cols;
main_extended_src_ = extended_srcs_[temporal_window_half_size_];
const IT max_estimate_sum_value =
- (IT)temporal_window_size_ * (IT)search_window_size_ * (IT)search_window_size_ * 255;
+ (IT)temporal_window_size_ * (IT)search_window_size_ * (IT)search_window_size_ * (IT)pixelInfo<T>::sampleMax();
fixed_point_mult_ = std::numeric_limits<IT>::max() / max_estimate_sum_value;
// precalc weight for every possible l2 dist between blocks
// additional optimization of precalced weights to replace division(averaging) by binary shift
+ // squared distances are truncated to 16 bits to get a reasonable table size
int template_window_size_sq = template_window_size_ * template_window_size_;
almost_template_window_size_sq_bin_shift = 0;
while (1 << almost_template_window_size_sq_bin_shift < template_window_size_sq)
almost_template_window_size_sq_bin_shift++;
+ almost_template_window_size_sq_bin_shift += 2*pixelInfo<T>::sampleBits() - 16;
int almost_template_window_size_sq = 1 << almost_template_window_size_sq_bin_shift;
double almost_dist2actual_dist_multiplier = (double) almost_template_window_size_sq / template_window_size_sq;
- IT max_dist = 255 * 255 * sizeof(T);
+ IT max_dist =
+ (IT)pixelInfo<T>::sampleMax() * (IT)pixelInfo<T>::sampleMax() * (IT)pixelInfo<T>::channels;
int almost_max_dist = (int) (max_dist / almost_dist2actual_dist_multiplier + 1);
almost_dist2weight.resize(almost_max_dist);