static void computeOffset(cv::Mat img1, cv::Mat img2, int d, cv::Point& _off) { cv::Point offset; cv::Size size1 = img1.size(), size2 = img2.size(); if ((size1.width > 2 && size1.height > 2) && (size2.width > 2 && size2.height > 2) && (d < 16)) { cv::Mat tmp1, tmp2; cv::resize(img1, tmp1, cv::Size(), 0.5f, 0.5f); cv::resize(img2, tmp2, cv::Size(), 0.5f, 0.5f); computeOffset(tmp1, tmp2, d+1, offset); offset.x *= 2, offset.y *= 2; } else { offset.x = 0, offset.y = 0; } cv::Point result; cv::Mat tb1, tb2, eb1, eb2; computeBitmaps(img1, tb1, eb1); computeBitmaps(img2, tb2, eb2); cv::Rect bound1(cv::Point(0,0), size1); cv::Rect bound2(cv::Point(0,0), size2); int min_err = (bound1 & bound2).area(); for (int dx = -1; dx <= 1; ++dx) { for (int dy = -1; dy <= 1; ++dy) { cv::Point displace = offset + cv::Point(dx,dy); cv::Rect frame = bound1 & (bound2 + displace); cv::Rect shift = bound2 & (bound1 - displace); // ROIs cv::Mat framed_tb1(tb1, frame); cv::Mat framed_eb1(eb1, frame); cv::Mat shifted_tb2(tb2, shift); cv::Mat shifted_eb2(eb2, shift); // cv::Mat tmp1, tmp2; cv::bitwise_xor(framed_tb1, shifted_tb2, tmp1); cv::bitwise_and(tmp1, framed_eb1, tmp2); cv::bitwise_and(shifted_eb2, tmp2, tmp1); // int err = (int)cv::sum(tmp1)[0]; if (dx == 0 && dy == 0) err -= 1; if (err < min_err) { result = displace; min_err = err; } } } _off = result; }
Point calculateShift(InputArray _img0, InputArray _img1) { Mat img0 = _img0.getMat(); Mat img1 = _img1.getMat(); CV_Assert(img0.channels() == 1 && img0.type() == img1.type()); CV_Assert(img0.size() == img0.size()); int maxlevel = static_cast<int>(log((double)max(img0.rows, img0.cols)) / log(2.0)) - 1; maxlevel = min(maxlevel, max_bits - 1); std::vector<Mat> pyr0; std::vector<Mat> pyr1; buildPyr(img0, pyr0, maxlevel); buildPyr(img1, pyr1, maxlevel); Point shift(0, 0); for(int level = maxlevel; level >= 0; level--) { shift *= 2; Mat tb1, tb2, eb1, eb2; computeBitmaps(pyr0[level], tb1, eb1); computeBitmaps(pyr1[level], tb2, eb2); int min_err = (int)pyr0[level].total(); Point new_shift(shift); for(int i = -1; i <= 1; i++) { for(int j = -1; j <= 1; j++) { Point test_shift = shift + Point(i, j); Mat shifted_tb2, shifted_eb2, diff; shiftMat(tb2, shifted_tb2, test_shift); shiftMat(eb2, shifted_eb2, test_shift); bitwise_xor(tb1, shifted_tb2, diff); bitwise_and(diff, eb1, diff); bitwise_and(diff, shifted_eb2, diff); int err = countNonZero(diff); if(err < min_err) { new_shift = test_shift; min_err = err; } } } shift = new_shift; } return shift; }