Laplacian pyramid blender

#include "opencv2/opencv.hpp"
 
using namespace cv;
 
class LaplacianBlending {
private:
    Mat_<Vec3f> left;
    Mat_<Vec3f> right;
    Mat_<float> blendMask;
     
    vector<Mat_<Vec3f> > leftLapPyr,rightLapPyr,resultLapPyr;
    Mat leftSmallestLevel, rightSmallestLevel, resultSmallestLevel;
    vector<Mat_<Vec3f> > maskGaussianPyramid; //masks are 3-channels for easier multiplication with RGB
     
    int levels;
     
     
    void buildPyramids() {
        buildLaplacianPyramid(left,leftLapPyr,leftSmallestLevel);
        buildLaplacianPyramid(right,rightLapPyr,rightSmallestLevel);
        buildGaussianPyramid();
    }
     
    void buildGaussianPyramid() {
        assert(leftLapPyr.size()>0);
         
        maskGaussianPyramid.clear();
        Mat currentImg;
        cvtColor(blendMask, currentImg, CV_GRAY2BGR);
        maskGaussianPyramid.push_back(currentImg); //highest level
         
        currentImg = blendMask;
        for (int l=1; l<levels+1; l++) {
            Mat _down; 
            if (leftLapPyr.size() > l) {
                pyrDown(currentImg, _down, leftLapPyr[l].size());
            } else {
                pyrDown(currentImg, _down, leftSmallestLevel.size()); //smallest level
            }
 
            Mat down; 
            cvtColor(_down, down, CV_GRAY2BGR);
            maskGaussianPyramid.push_back(down);
            currentImg = _down;
        }
    }
     
    void buildLaplacianPyramid(const Mat& img, vector<Mat_<Vec3f> >& lapPyr, Mat& smallestLevel) {
        lapPyr.clear();
        Mat currentImg = img;
        for (int l=0; l<levels; l++) {
            Mat down,up;
            pyrDown(currentImg, down);
            pyrUp(down, up, currentImg.size());
            Mat lap = currentImg - up;
            lapPyr.push_back(lap);
            currentImg = down;
        }
        currentImg.copyTo(smallestLevel);
    }
     
    Mat_<Vec3f> reconstructImgFromLapPyramid() {
        Mat currentImg = resultSmallestLevel;
        for (int l=levels-1; l>=0; l--) {
            Mat up;
                         
            pyrUp(currentImg, up, resultLapPyr[l].size());
            currentImg = up + resultLapPyr[l];
        }
        return currentImg;
    }
     
    void blendLapPyrs() {
        resultSmallestLevel = leftSmallestLevel.mul(maskGaussianPyramid.back()) + 
                                    rightSmallestLevel.mul(Scalar(1.0,1.0,1.0) - maskGaussianPyramid.back());
        for (int l=0; l<levels; l++) {
            Mat A = leftLapPyr[l].mul(maskGaussianPyramid[l]);
            Mat antiMask = Scalar(1.0,1.0,1.0) - maskGaussianPyramid[l];
            Mat B = rightLapPyr[l].mul(antiMask);
            Mat_<Vec3f> blendedLevel = A + B;
             
            resultLapPyr.push_back(blendedLevel);
        }
    }
 
public:
    LaplacianBlending(const Mat_<Vec3f>& _left, const Mat_<Vec3f>& _right, const Mat_<float>& _blendMask, int _levels):
    left(_left),right(_right),blendMask(_blendMask),levels(_levels) 
    {
        assert(_left.size() == _right.size());
        assert(_left.size() == _blendMask.size());
        buildPyramids();
        blendLapPyrs();
    };
     
    Mat_<Vec3f> blend() {
        return reconstructImgFromLapPyramid();
    }   
};
 
Mat_<Vec3f> LaplacianBlend(const Mat_<Vec3f>& l, const Mat_<Vec3f>& r, const Mat_<float>& m) {
    LaplacianBlending lb(l,r,m,4);
    return lb.blend();
}
 
int main(int argc, char** argv) {
   Mat l8u = imread("left.png");
   Mat r8u = imread("right.png");
   Mat_<Vec3f> l; l8u.convertTo(l,CV_32F,1.0/255.0);
   Mat_<Vec3f> r; r8u.convertTo(r,CV_32F,1.0/255.0);
 
   Mat_<float> m(l.rows,l.cols,0.0);
   m(Range::all(),Range(0,m.cols/2)) = 1.0;
 
   Mat_<Vec3f> blend = LaplacianBlend(l, r, m);
   imshow("blended",blend);
   waitKey(0);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值