تصویر را به کانال های مجاز تقسیم کنید کانال SوV به صورت نرمال می تونید تفاضل را برای آنها حساب کنید ولی برای کانال Hue از تفاضل دورانی استفاده کنید.
template <typename T>
T abssDiffCircularValue(T val1, T val2, T upper_range) {
auto dif1 = val1 - val2;
if (dif1 < 0)
dif1 = upper_range + dif1;
auto dif2 = val2 - val1;
if (dif2 < 0)
dif2 = upper_range + dif2;
return std::min(dif1, dif2);
}
template<typename T>
void absdiffCircularProc(cv::InputArray _src1, cv::InputArray _src2, cv::InputOutputArray _dst, T upper_range ) {
assert(_src1.type() == _src2.type());
cv::Mat src1 = _src1.getMat();
cv::Mat src2 = _src2.getMat();
_dst.create(src1.size(), src1.type());
cv::Mat dst = _dst.getMat();
for (int i = 0; i < dst.rows; i++) {
auto row_src1 = src1.ptr<T>(i);
auto row_src2 = src2.ptr<T>(i);
auto row_dst = dst.ptr<T>(i);
for (int j = 0; j < dst.cols; j++)
row_dst[i] = abssDiffCircularValue(row_src1[j], row_src2[j], upper_range);
}
}
void absdiffCircular(cv::InputArray _src1, cv::InputArray _src2, cv::InputOutputArray _dst, float upper_range /*= 180*/)
{
assert(_src1.type() == _src2.type());
if (_src1.type() == CV_8UC1)
absdiffCircularProc<uchar>(_src1, _src2, _dst, (uchar)upper_range);
else if (_src1.type() == CV_32FC1)
absdiffCircularProc<float>(_src1, _src2, _dst, (float)upper_range);
}
void compareInHSV(cv::InputArray _src1, cv::InputArray _src2, cv::InputOutputArray _dst, cv::InputArray _mask /*= cv::noArray()*/,
EcvCompareType compare_type, const cv::Scalar& weight )
{
cv::Mat src1_hsv, src2_hsv;
cv::cvtColor(_src1, src1_hsv, CV_BGR2HSV);
cv::cvtColor(_src2, src2_hsv, CV_BGR2HSV);
std::vector<cv::Mat> hsv1_images, hsv2_images;
cv::split(src1_hsv, hsv1_images);
cv::split(src2_hsv, hsv2_images);
std::vector<cv::Mat> diff_images(3);
for (int i = 0; i < 3; i++) {
if (i)
cv::absdiff(hsv1_images[i], hsv2_images[i], diff_images[i]);
else absdiffCircular(hsv1_images[i], hsv2_images[i], diff_images[i]);
}
for (int i = 0; i < 3; i++)
diff_images[i] = diff_images[i] * weight.val[i];
cv::Mat diff_img;
cv::merge(diff_images, diff_img);
compare(diff_img, _dst, _mask, compare_type);
}