Colorization using Optimization
着色是一种由计算机辅助的向单色图像或电影添加颜色的过程。本文提出了一种简单的着色方法,它既不需要精确的图像分割,也不需要精确的区域跟踪。该方法基于一个简单的前提:在时空中具有相似强度的相邻像素应该具有相似的颜色。
作者用一个二次代价函数形式化了这个前提,并用标准技术有效地解决的优化问题。
只需要用一些颜色的涂鸦来注释图像,该算法可以产生一个完全彩色的图像或图像序列。
本文主要分析下面的代码,写的很清晰易懂,效果很好。
代码仓库:[https://github.com/soumik12345/colorization-using-optimization]
主要原理
一个像素的颜色可以由邻域像素颜色的加权得到
加权系数由灰度的距离得到
这两个公式正好印证了:
具有相似强度的相邻像素应该具有相似的颜色。
实现的时候
代码中实现两个方法,一个调用库函数,一个雅可比迭代求线性方程组
方法一:建立稀疏矩阵, 然后用from scipy.sparse.linalg import spsolve函数求解
u = spsolve(W, b1) # 已知特定检测点的颜色,邻域距离,求所有点的颜色。已知特定检测点的光流和邻域距离(怎么定义?),求所有点的光流
v = spsolve(W, b2)
方法二:建立稀疏矩阵 和 一个线性方程组。可以通过最小二乘方法,也可以通过迭代法,比如代码中使用雅可比迭代法求解该方程
def jacobi(self, weight_matrix, b_u, b_v, epoch: int, interval: int) -> None:
D_u = weight_matrix.diagonal()
D_v = weight_matrix.diagonal()
R_u = weight_matrix - scipy.sparse.diags(D_u)
R_v = weight_matrix - scipy.sparse.diags(D_v)
x_u = np.zeros(weight_matrix.shape[0])
x_v = np.zeros(weight_matrix.shape[0])
print(D_u.shape, R_u.shape, x_u.shape)
print('Optimizing iteratively...')
for epoch in tqdm(range(1, epoch + 1)):
x_u = (b_u - R_u.dot(x_u)) / D_u
x_v = (b_v - R_v.dot(x_v)) / D_v
if epoch % interval == 0:
self.result_history.append(
self.yuv_channels_to_rgb(self.result_y, x_u, x_v))
# Ax = b
# (r+d)x = b
# x = (b-rx)/d 迭代 比较大的矩阵用迭代。比较小的 x=(A'A)^-1 (A'b)
比如输入灰度图和 clue图:
迭代100次后:
200次迭代:
400次迭代: