首页 > 其他分享 >使用liner、feather、multiband对已经拼接的数据进行融合(下)

使用liner、feather、multiband对已经拼接的数据进行融合(下)

时间:2022-12-26 23:06:10浏览次数:42  
标签:Vec3f Mat int multiband liner down currentImg feather size

高斯金字塔是向下采样,而laplace金字塔式向上采样(也就是恢复),采用的都是差值的方法。如何能够在金字塔各个层次上面进行图像的融合,结果证明是相当不错的。网络上面流传的一个类解释了这个问题,并且能够拿来用:



​​include

"stdafx.h"​​

​​
include

<
iostream
>
include

<
vector
>
include

<
opencv2
/
core
/
core.hpp
>
include

<
opencv2
/
imgproc
/
imgproc.hpp
>
include

<
opencv2
/
highgui
/
highgui.hpp
>
include

<
opencv2
/
features2d
/
features2d.hpp
>
include

<
opencv2
/
calib3d
/
calib3d.hpp
>
using

namespace
ifdef
define

new
endif
define



/*


1.设计一个mask(一半全1,一半全0),并计算level层的gaussion_mask[i];


2.计算两幅图像每一层的Laplacian[i],并与gaussion_mask[i]相乘,合成一幅result_lapacian[i];


3.对两幅图像不断求prydown,并把最高层保存在gaussion[i],与gaussion_mask[i]相乘,合成一幅result_gaussion;


4,对result_gaussion不断求pryup,每一层都与result_lapacian[i]合成,最后得到原-图像大小的融合图像。


*/




class
LaplacianBlending {
private
:

Mat_
<
Vec3f
>
top;
Mat_
<
Vec3f
>
down;
Mat_
<

float
>
blendMask;



vector
<
Mat_
<
Vec3f
>

>
topLapPyr,downLapPyr,resultLapPyr;
//Laplacian Pyramids

Mat topHighestLevel, downHighestLevel, resultHighestLevel;

vector
<
Mat_
<
Vec3f
>

>
maskGaussianPyramid;
//masks are 3-channels for easier multiplication with RGB




int
levels;




//创建金字塔

void
buildPyramids() {

buildLaplacianPyramid(top,topLapPyr,topHighestLevel);


buildLaplacianPyramid(down,downLapPyr,downHighestLevel);


buildGaussianPyramid();


}


//创建gauss金字塔

void
buildGaussianPyramid() {
//金字塔内容Y为a每一层的掩模
assert(topLapPyr.size()
>
0
);




maskGaussianPyramid.clear();


Mat currentImg;


//blendMask就是掩码
cvtColor(blendMask, currentImg, CV_GRAY2BGR);
//store color img of blend mask into maskGaussianPyramid
maskGaussianPyramid.push_back(currentImg);
//0-level



currentImg
=
blendMask;

for
(
int
l
=
1
; l
<
levels
+
1
; l
++
) {

Mat _down;


if
(topLapPyr.size()
>
l)

pyrDown(currentImg, _down, topLapPyr[l].size());


else

pyrDown(currentImg, _down, topHighestLevel.size());
//lowest level




Mat down;


cvtColor(_down, down, CV_GRAY2BGR);

maskGaussianPyramid.push_back(down);
//add color blend mask into mask Pyramid
currentImg
=
_down;

}


}





//创建laplacian金字塔

void
buildLaplacianPyramid(
const
Mat
&
img, vector
<
Mat_
<
Vec3f
>

>
&
lapPyr, Mat
&
HighestLevel) {

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;
//存储的就是残D差

lapPyr.push_back(lap);

currentImg
=
down;

}


currentImg.copyTo(HighestLevel);


}




Mat_
<
Vec3f
>
reconstructImgFromLapPyramid() {

//将左右laplacian图像拼成的resultLapPyr金字塔中每一层

//从上到下插值放大并相加,即得blend图像结果
Mat currentImg
=
resultHighestLevel;

for
(
int
l
=
levels
-
1
; l
>
=
0
; l
--
) {

Mat up;


pyrUp(currentImg, up, resultLapPyr[l].size());

currentImg
=
up
+
resultLapPyr[l];

}


return
currentImg;

}





void
blendLapPyrs() {

//获得每层金字塔中直接用左右两图Laplacian变换拼成的图像

//一半的一半就是在这个地方计算的。 是基于掩模的方式进行的.
resultHighestLevel
=
topHighestLevel.mul(maskGaussianPyramid.back())
+

downHighestLevel.mul(Scalar(
1
.
0
,
1
.
0
,
1
.
0
)
-
maskGaussianPyramid.back());

for
(
int
l
=
0
; l
<
levels; l
++
) {
Mat A
=
topLapPyr[l].mul(maskGaussianPyramid[l]);
Mat antiMask
=
Scalar(
1
.
0
,
1
.
0
,
1
.
0
)
-
maskGaussianPyramid[l];
Mat B
=
downLapPyr[l].mul(antiMask);
Mat_
<
Vec3f
>
blendedLevel
=
A
+
B;

resultLapPyr.push_back(blendedLevel);


}


}




public
:

LaplacianBlending(
const
Mat_
<
Vec3f
>
&
_top,
const
Mat_
<
Vec3f
>
&
_down,
const
Mat_
<

float
>
&
_blendMask,
int
_levels)
:
//缺省数y据Y,使1用 LaplacianBlending lb(l,r,m,4);

top(_top),down(_down),blendMask(_blendMask),levels(_levels)


{

assert(_top.size()
==
_down.size());
assert(_top.size()
==
_blendMask.size());
buildPyramids();
//创建laplacian金字塔和gauss金字塔
blendLapPyrs();
//将左右金字塔融合成为a一个图片

};




Mat_
<
Vec3f
>
blend() {

return
reconstructImgFromLapPyramid();
//reconstruct Image from Laplacian Pyramid

}


};




Mat_
<
Vec3f
>
LaplacianBlend(
const
Mat_
<
Vec3f
>
&
t,
const
Mat_
<
Vec3f
>
&
d,
const
Mat_
<

float
>
&
m) {
LaplacianBlending lb(t,d,m,
4
);

return
lb.blend();

}







DllExport
double
aValue
=
1
.
5
;
DllExport
int
dlladd()

{


return

5
;

}

DllExport
int
dlladd(
int
a,
int
b)

{


return
a
+
b;

}

DllExport cv
:
:
Mat imagetest()

{

cv
:
:
Mat image1
=
cv
:
:
imread(
"C:\\apple.png"
,
1
);
cv
:
:
Mat image2
=
cv
:
:
imread(
"C:\\orange.png"
,
1
);



Mat_
<
Vec3f
>
t; image1.convertTo(t,CV_32F,
1
.
0
/
255
.
0
);
//Vec3f表示有三个通道,即 [row][column][depth]
Mat_
<
Vec3f
>
d; image2.convertTo(d,CV_32F,
1
.
0
/
255
.
0
);



Mat_
<

float
>
m(t.rows,d.cols,
0
.
0
);
//将m全部赋3值为a0

//m(Range::all(),Range(0,m.cols/2)) = 1.0; //原来初始的掩码是在这里
m(Range(
0
,m.rows
/
2
),Range
:
:
all())
=
1
.
0
;
Mat_
<
Vec3f
>
blend
=
LaplacianBlend(t,d, m);



imshow(
"blended"
,blend);

return
blend;

}
​​



需要注意的是, m(Range(0,m.rows/2),Range::all())=1.0表明了原始图像的掩码,这个掩码就是那个分界的地方。


比如比如:



使用liner、feather、multiband对已经拼接的数据进行融合(下)_Mask

;



使用liner、feather、multiband对已经拼接的数据进行融合(下)_ci_02


永达实际的项目上面,应该是这样。


在使用这种方法进行大规模拼接的时候,主要是两个问题


一个是效果,在上面的那个橘子苹果的例子中,只有前景的颜色有变化,实际上其它几个地方色彩亮度变化不是很大。但是对于实际情况下的拼接来说,亮度有变化,比较难以处理。



使用liner、feather、multiband对已经拼接的数据进行融合(下)_ci_03


二是效率。laplacian需要大量的过程,造成结果内存的需求很大,一时半会很难优化好。multband看来只能够在符合要求的简单拼接中去实现使用。

标签:Vec3f,Mat,int,multiband,liner,down,currentImg,feather,size
From: https://blog.51cto.com/jsxyhelu2017/5971120

相关文章