c++ opencv 复现Fiji 配对拼接算法中的加权融合
复现Fiji Is Just ->Plugins->Stitching->Pairewise stitching(默认参数)
未融合
fiji的效果
复现的效果
右下角效果不太理想
参考:插件源码+论文
Globally optimal stitching of tiled 3D microscopic image acquisitions
double computeWeight(const cv::Point& location,const cv::Size& imgeSize, const cv::Size2d & imgAreaBlend)
{double minDistance = 1;int distance =max(1, min(location.x + 1, imgeSize.width - location.x ));if (distance < imgAreaBlend.width)minDistance *= distance / imgAreaBlend.width;distance = max(1, min(location.y + 1, imgeSize.height - location.y));if (distance < imgAreaBlend.height)minDistance *= distance / imgAreaBlend.height;if (minDistance == 1)return minDistance;else if (minDistance <= 0)return 0.0000001;elsereturn (cos((1.0 - minDistance) * CV_PI) + 1)*0.5;
}
void weightBlend(cv::Mat& blendedImg, const cv::Mat& leftImg, const cv::Mat& rightImg, cv::Point offset, double percentScaling)
{cv::Rect blendedImgRect;cv::Rect refLeftRect = cv::Rect(0, 0, leftImg.cols, leftImg.rows);cv::Rect refRightRect = cv::Rect(offset.x, offset.y, rightImg.cols, rightImg.rows);blendedImgRect = refLeftRect | refRightRect;blendedImg= Mat(blendedImgRect.size(), leftImg.type(),cv::Scalar::all(0));Point locationLeft, locationRight;Size leftImgSize = leftImg.size();Size rightImgSize = rightImg.size();double percentScalingHalf = percentScaling * 0.5f;cv::Size2d leftImgAreaBlend(round(percentScalingHalf * leftImgSize.width), round(percentScalingHalf * leftImgSize.height));cv::Size2d rightImgAreaBlend(round(percentScalingHalf * rightImgSize.width), round(percentScalingHalf * rightImgSize.height));double weight, weightSum, valueSum;bool outBoundLeft, outBoundRight;cv::Mat noblendedImg = blendedImg.clone();leftImg.copyTo(noblendedImg(refLeftRect - blendedImgRect.tl()));rightImg.copyTo(noblendedImg(refRightRect - blendedImgRect.tl()));for(int r=0;r< blendedImg.rows;++r){for (int c = 0; c < blendedImg.cols; ++c){locationLeft.x = c + blendedImgRect.x - refLeftRect.x;locationLeft.y = r + blendedImgRect.y - refLeftRect.y;outBoundLeft = locationLeft.x < 0 || locationLeft.x >= leftImg.cols ||locationLeft.y < 0 || locationLeft.y >= leftImg.rows;locationRight.x = c + blendedImgRect.x - refRightRect.x;locationRight.y = r + blendedImgRect.y - refRightRect.y;outBoundRight = locationRight.x < 0 || locationRight.x >= rightImg.cols ||locationRight.y < 0 || locationRight.y >= rightImg.rows;if (outBoundLeft&& outBoundRight){continue;}weightSum = 0;valueSum = 0;if (!outBoundLeft){weight = max(0.00001, computeWeight(locationLeft, leftImgSize, leftImgAreaBlend));weightSum += weight;valueSum += leftImg.at<uchar>(locationLeft) * weight;}if (!outBoundRight){weight = max(0.00001, computeWeight(locationRight, rightImgSize, rightImgAreaBlend));weightSum += weight;valueSum += rightImg.at<uchar>(locationRight) * weight;}blendedImg.at<uchar>(r, c) = cv::saturate_cast<uchar>(valueSum / weightSum);}}
}