论文复现:Poisson Image Editing

一、论文介绍

Poisson Image Editing这篇论文使用泊松方程,实现了一种图像融合算法,将一张图像的某个区域无缝地复制到另一张图像中。如下图所示。
在这里插入图片描述
可以看到cloning是经过简单复制得到的图像,从源图像中抠出的区域并不能与目标图像很好地融合。右图是使用本文中提出的算法,经过无缝复制后,从源图像的抠出的区域可以无缝地导入目标图像中。

二、一些先验知识

1.泊松方程

泊松方程是泊松在物理学领域提出的一个偏微分方程,其形式为:
△ f = Ω \bigtriangleup f=\Omega f=Ω
其中 △ \bigtriangleup 表示二阶微分即拉普拉斯算子, Ω \Omega Ω为已知量。
对于泊松方程的求解,论文中提到了给定狄利克雷边界条件的泊松方程解法,即给定函数 f f f在边界处的实际值。

2.Laplace算子

在二维图像中,图像函数 f f f是离散函数,拉普拉斯算子为如下卷积核形式:
[ 0 1 0 1 − 4 1 0 1 0 ] \begin{bmatrix} 0& 1& 0\\ 1& -4& 1\\ 0& 1& 0 \end{bmatrix} 010141010
比如要计算 ( i , j ) (i,j) (i,j)处的像素点的二阶微分:
△ f ( i , j ) = [ 0 1 0 1 − 4 1 0 1 0 ] . [ f ( i − 1 , j − 1 ) f ( i − 1 , j ) f ( i − 1 , j + 1 ) f ( i , j − 1 ) f ( i , j ) f ( i , j + 1 ) f ( i + 1 , j − 1 ) f ( i + 1 , j ) f ( i + 1 , j + 1 ) ] \bigtriangleup f(i,j)=\begin{bmatrix} 0& 1& 0\\ 1& -4& 1\\ 0& 1& 0 \end{bmatrix}.\begin{bmatrix} f(i-1,j-1)& f(i-1,j)& f(i-1,j+1)\\ f(i,j-1)& f(i,j)& f(i,j+1)\\ f(i+1,j-1)& f(i+1,j)& f(i+1,j+1) \end{bmatrix} f(i,j)=010141010.f(i1,j1)f(i,j1)f(i+1,j1)f(i1,j)f(i,j)f(i+1,j)f(i1,j+1)f(i,j+1)f(i+1,j+1)

三、算法原理

算法的目的是将一张图像的某一个区域与另一张图像更好地融合,当两张图像梯度(图像灰度的变化率)越接近,则说明两张图像融合得越好。即最小化如下公式:
m i n ∬ ∣ ▽ f − v ∣ 2 min\iint \left | \bigtriangledown f-v \right | ^{2} minfv2
其中 v v v是源图像的梯度, ▽ f \bigtriangledown f f是目标图像的梯度。
要使得该公式最小,即 △ f = ▽ v \bigtriangleup f=\bigtriangledown v f=v在这里插入图片描述
如上图所示,将源图像中脸部区域复制到目标图像中,经过简单的复制,得到右图所示的cloing图像,这个过程可以抽象为如下图所示的模型。
在这里插入图片描述
图中, g g g是源图像圈出区域的图像函数, v v v是设置的与源图像有关的梯度向量场,
v = ▽ g v=\bigtriangledown g v=g
▽ v = △ f \bigtriangledown v=\bigtriangleup f v=f.
Ω \Omega Ω是从源图像中抠出的部分区域, f f f是该区域像素的像素值; S S S是目标图像中除了 Ω \Omega Ω区域外的部分, f ∗ f* f是该区域像素的像素值。 ∂ Ω \partial \Omega Ω Ω \Omega Ω区域的边界,边界像素值是对应的目标图像该处的像素值:
f ∣ ∂ Ω = f ∣ ∂ Ω ∗ f_{\mid \partial \Omega}=f_{\mid \partial \Omega}^{*} fΩ=fΩ

这样就构造了一个具有狄利克雷边界条件的泊松方程: △ f = △ g \bigtriangleup f=\bigtriangleup g f=g w i t h with with f ∣ ∂ Ω = f ∣ ∂ Ω ∗ f_{\mid \partial \Omega}=f_{\mid \partial \Omega}^{*} fΩ=fΩ

四、一个例子

如下图所示,左图表示 4 ∗ 4 4*4 44的源图像,右图是 4 ∗ 4 4*4 44的目标图像,将左图中矩形框框住的区域复制到右图白色区域中,源图像 g 1 , . . . , g 16 g_{1},...,g_{16} g1,...,g16已知,目标图像中 f 1 , . . . , f 16 f_{1},...,f_{16} f1,...,f16已知,要求的是 x 1 , x 2 , x 3 , x 4 x_{1},x_{2},x_{3},x_{4} x1,x2,x3,x4
在这里插入图片描述
根据以上列出的泊松方程列出如下式子:
− 4 x 1 + x 2 + x 3 + f 2 + f 5 = − 4 g 6 + g 2 + g 5 + g 7 + g 10 -4 x_{1}+x_{2}+x_{3}+f_{2}+f_{5}=-4 g_{6}+g_{2}+g_{5}+g_{7}+g_{10} 4x1+x2+x3+f2+f5=4g6+g2+g5+g7+g10
− 4 x 2 + x 1 + x 4 + f 3 + f 8 = − 4 g 7 + g 3 + g 6 + g 8 + g 11 -4 x_{2}+x_{1}+x_{4}+f_{3}+f_{8}=-4 g_{7}+g_{3}+g_{6}+g_{8}+g_{11} 4x2+x1+x4+f3+f8=4g7+g3+g6+g8+g11
− 4 x 3 + x 1 + x 4 + f 9 + f 14 = − 4 g 10 + g 6 + g 9 + g 11 + g 14 -4 x_{3}+x_{1}+x_{4}+f_{9}+f_{14}=-4 g_{10}+g_{6}+g_{9}+g_{11}+g_{14} 4x3+x1+x4+f9+f14=4g10+g6+g9+g11+g14
− 4 x 4 + x 2 + x 3 + f 12 + f 15 = − 4 g 11 + g 7 + g 10 + g 12 + g 15 -4 x_{4}+x_{2}+x_{3}+f_{12}+f_{15}=-4 g_{11}+g_{7}+g_{10}+g_{12}+g_{15} 4x4+x2+x3+f12+f15=4g11+g7+g10+g12+g15

经过简单移项可写成以下矩阵形式:
[ − 4 1 1 0 1 − 4 0 1 1 0 − 4 1 0 1 1 − 4 ] [ x 1 x 2 x 3 x 4 ] = [ − 4 g 6 + g 2 + g 5 + g 7 + g 10 − f 2 − f 5 − 4 g 7 + g 3 + g 6 + g 8 + g 11 − f 3 − f 8 − 4 g 10 + g 6 + g 9 + g 11 + g 14 − f 9 − f 14 − 4 g 11 + g 7 + g 10 + g 12 + g 15 − f 12 − f 15 ] \left[\begin{array}{cccc} -4 & 1 & 1 & 0 \\ 1 & -4 & 0 & 1 \\ 1 & 0 & -4 & 1 \\ 0 & 1 & 1 & -4 \end{array}\right]\left[\begin{array}{l} x_{1} \\ x_{2} \\ x_{3} \\ x_{4} \end{array}\right]=\left[\begin{array}{c} -4 g_{6}+g_{2}+g_{5}+g_{7}+g_{10}-f_{2}-f_{5} \\ -4 g_{7}+g_{3}+g_{6}+g_{8}+g_{11}-f_{3}-f_{8} \\ -4 g_{10}+g_{6}+g_{9}+g_{11}+g_{14}-f_{9}-f_{14} \\ -4 g_{11}+g_{7}+g_{10}+g_{12}+g_{15}-f_{12}-f_{15} \end{array}\right] 4110140110410114x1x2x3x4=4g6+g2+g5+g7+g10f2f54g7+g3+g6+g8+g11f3f84g10+g6+g9+g11+g14f9f144g11+g7+g10+g12+g15f12f15
4个方程式解4个未知数,可得到唯一解。

五、具体实现

代码核心在于构建线性系统 A x = b Ax=b Ax=b

int o_start_r = 32, o_start_c = 14, d_start_r = 76, d_start_c = 550;
int h = 64, w = 200;

void BuildSystem() {
	SparseMatrix<double> A(h * w, h * w);
	for (int i = 0; i < h; i++) {
		for (int j = 0; j < w; j++) {
			int index = i * w + j;
			A.coeffRef(index, index) = -4;
			if (i != 0)		A.coeffRef(index, (i - 1) * w + j) = 1;
			if (i != h - 1) A.coeffRef(index, (i + 1) * w + j) = 1;
			if (j != 0)		A.coeffRef(index, i * w + j - 1) = 1;
			if (j != w - 1)	A.coeffRef(index, i * w + j + 1) = 1;
		}
	}

	Image o_img("./data/original.jpg");
	Image d_img("./data/destination.png");

	VectorXd R(h * w); VectorXd G(h * w); VectorXd B(h * w);
	R.setZero(); G.setZero(); B.setZero();

	for (int i = 0; i < h; i++) {
		for (int j = 0; j < w; j++) {
			int o_r = o_start_r + i, o_c = o_start_c + j;
			int d_r = d_start_r + i, d_c = d_start_c + j;

			Vec3d div_RGB = o_img.GetDivAt(o_r, o_c);
			if (j == 0)
				div_RGB -= d_img.colors[d_r][d_c - 1];
			if (j == w - 1)
				div_RGB -= d_img.colors[d_r][d_c + 1];
			if (i == 0)
				div_RGB -= d_img.colors[d_r - 1][d_c];
			if (i == h - 1)
				div_RGB -= d_img.colors[d_r + 1][d_c];

			R(i * w + j) = div_RGB[0];
			G(i * w + j) = div_RGB[1];
			B(i * w + j) = div_RGB[2];
		}
	}

	SparseLU<Eigen::SparseMatrix<double>, Eigen::COLAMDOrdering<int> > solver;
	solver.compute(A);
	VectorXd r = solver.solve(R);
	VectorXd g = solver.solve(G);
	VectorXd b = solver.solve(B);

	for (int i = 0; i < h * w; i++) {
		int r_ = d_start_r + i / w;
		int c_ = d_start_c + i % w;
		//保证RGB值在0~255
		double new_r = min(max(r(i), 0.0), 255.0);
		double new_g = min(max(g(i), 0.0), 255.0);
		double new_b = min(max(b(i), 0.0), 255.0);
		d_img.colors[r_][c_] = Vec3d(new_r, new_g, new_b);
	}

	d_img.Save("./data/result.jpg");
	waitKey(0);
}

int main() {
	BuildSystem();
	return 0;
}

六、效果图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

七、总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值