【计算机图形学】Colorization Using Optimization给灰度图进行着色上色

Colorization Using Optimization

概述:算法利用优化的方法对灰度图进行着色,用户只需简单操作就行,无需对ROI区域进行精确分割。
在这里插入图片描述

1. 预备知识

YUV格式

与我们熟知的RGB通道类似,YUV也是一种颜色编码方法,主要用于电视系统以及模拟视频领域,它将描述灰度值的亮度信息(Y)和描述色彩饱和度的色彩信息(UV)分离,没有UV信息一样可以显示完整的图像,只不过是黑白图像。

两者转化公式如下。

[ Y U V ] = [ 0.299 0.587 0.114 − 0.169 − 0.331 0.5 0.5 − 0.419 − 0.081 ] [ R G B ] + [ 0 128 128 ] \left[\begin{array}{l} Y \\ U \\ V \end{array}\right] = \left[\begin{array}{ccc} 0.299 & 0.587 & 0.114 \\ -0.169 & -0.331 & 0.5 \\ 0.5 & -0.419 & -0.081 \end{array}\right]\left[\begin{array}{l} R \\ G \\ B \end{array}\right]+\left[\begin{array}{c} 0 \\ 128 \\ 128 \end{array}\right] YUV = 0.2990.1690.50.5870.3310.4190.1140.50.081 RGB + 0128128

[ R G B ] = [ 1 − 0.00093 1.401687 1 − 0.3437 − 0.71417 1 1.77216 0.00099 ] [ Y U − 128 V − 128 ] \left[\begin{array}{l} R \\ G \\ B \end{array}\right]=\left[\begin{array}{ccc} 1 & -0.00093 & 1.401687 \\ 1 & -0.3437 & -0.71417 \\ 1 & 1.77216 & 0.00099 \end{array}\right]\left[\begin{array}{c} Y \\ U-128 \\ V-128 \end{array}\right] RGB = 1110.000930.34371.772161.4016870.714170.00099 YU128V128

2. 算法原理

算法利用优化的方法对灰度图进行着色。具体而言,在YUV颜色空间中,首先人为对灰度图进行简单着色,然后利用优化的方法求解其他未着色的像素点的颜色值,最后对这个像素点进行填充。

算法假设在3*3邻域的点中,灰度Y差距小的点,它们的色彩差距也会小。因此我们可以将这个问题转化成一个最小化 J ( U ) J(U) J(U) J ( V ) J(V) J(V)的优化问题。

J ( U ) = ∑ r ( U ( r ) − ∑ s ∈ N ( r ) w r s U ( s ) ) 2 J(U)=\sum_{\mathbf{r}}\left(U(\mathbf{r})-\sum_{\mathbf{s} \in N(\mathbf{r})} w_{\mathbf{r s}} U(\mathbf{s})\right)^{2} J(U)=r U(r)sN(r)wrsU(s) 2

J ( V ) = ∑ r ( V ( r ) − ∑ s ∈ N ( r ) w r s V ( s ) ) 2 J(V)=\sum_{\mathbf{r}}\left(V(\mathbf{r})-\sum_{\mathbf{s} \in N(\mathbf{r})} w_{\mathbf{r s}} V(\mathbf{s})\right)^{2} J(V)=r V(r)sN(r)wrsV(s) 2

这里,r是3*3的像素点邻域的中心点,s是r的相邻点(8个方向), w r s w_{r s} wrs是像素点r和s根据Y通道计算的相似度, w r s w_{r s} wrs计算公式如下,

w r s ∝ e − ( Y ( r ) − Y ( s ) ) 2 2 σ r 2 w_{r s} \propto e^{-\frac{(Y(r)-Y(s))^{2}}{2 \sigma_{r}^{2}}} wrse2σr2(Y(r)Y(s))2

并且权重加和等于1,即 ∑ s ∈ N ( r ) W r s = 1 \sum_{\mathrm{s} \in \mathrm{N}(\mathrm{r})} \mathrm{W}_{\mathbf{r s}} = 1 sN(r)Wrs=1

优化问题的最小值在 J ′ ( U ) = 0 , J ′ ( V ) = 0 J^{\prime}(U)=0,J^{\prime}(V)=0 J(U)=0,J(V)=0时取到,也就是解下面的方程:

W r , s = { 1 , r = s − w r s , r ≠ s , s ∈ N ( r ) 0 ,  otherwise  W_{r, s}=\left\{\begin{array}{cc} 1 ,& r=s \\ -w_{r s}, & r \neq s, s \in N(r)\\ 0, & \text { otherwise } \end{array}\right. Wr,s= 1,wrs,0,r=sr=s,sN(r) otherwise 

W U = b 1 W U=b_{1} WU=b1

W V = b 2 W V=b_{2} WV=b2

这里的 b 1 , b 2 b1,b2 b1,b2指的是简单着色草图中上色像素点的 U , V U,V U,V值。
因为W矩阵只在两个点相邻的情况下才可能取非零的值,每个点的相邻点很少,所以它是一个稀疏的矩阵,可以用类似求解poisson image editing的方法来求解现在的方程来得到图片每个像素点的U,V值。最后将YUV通道的值转回RGB就可以得到一张彩色图。

文献[2]中有非常生动具体的例子解释如何求解未着色部分的U或者V的值。

3. 算法实现

3.1 开发环境

电脑:Ubuntu18.04,cpu:1.8GHz ×8,内存 :8G
环境:Python,主要用scipy.sparse库的csc函数来构建稀疏矩阵,用linalg.spsolve库来求解线性方程。

3.2 实现过程

算法输入是一张灰度图,以及一张对其进行简单上色的草图sketch。
算法输出这张图片的彩色图。
第一步,先对在RGB颜色空间的输入图片转换成YUV颜色空间。
第二步,找到简单上色后的区域,并记录其坐标。
第三步,记录整张图片的每个像素的横纵坐标索引,并通过第二步找到的坐标,计算其上色的坐标及其邻域的权重。因为权重矩阵 W W W非常大并且稀疏,所以用Compressed Sparse Row matrix(CSR)进行存储 W W W
第四步,找到sketch图上色区域并把U,V通道的值赋给向量 b b b
第五步,用scipy.sparse.linalg.spsolve求解线性方程组 W X = b WX=b WX=b,得到图片所有像素点的U,V通道的值,结合灰度图的Y通道的值组成YUV格式的图片,最后将其转化为RGB格式图片。

class ColorizationUsingOptimization():
    def __init__(self, ori_img, skt_img):
        self.ori_img = cv2.imread(ori_img).astype(np.float32) / 255
        self.skt_img = cv2.imread(skt_img).astype(np.float32) / 255
        # rgb2yuv
        self.ori_yuv = cv2.cvtColor(self.ori_img, cv2.COLOR_BGR2YUV)
        self.skt_yuv = cv2.cvtColor(self.skt_img, cv2.COLOR_BGR2YUV)
        # get image size
        self.width = self.ori_img.shape[0]
        self.height = self.ori_img.shape[1]
        self.img_size = self.width * self.height
        # separate y u v
        self.y_ori = self.ori_yuv[:, :, 0]
        self.u_skt = self.skt_yuv[:, :, 1].reshape(self.img_size)
        self.v_skt = self.skt_yuv[:, :, 2].reshape(self.img_size)
        # get sketched pixels position
        self.get_skt_pos()
        # build weight matrix and b
        self.build_weight_b()
        # solve WX = b1 and colorization
        self.color()

    def get_skt_pos(self):
        assert self.ori_img.shape == self.skt_img.shape, "not the same image size"
        self.skt_pos = np.zeros((self.ori_img.shape[0], self.ori_img.shape[1]))
        for i in range(self.skt_pos.shape[0]):
            for j in range(self.skt_pos.shape[1]):
                if (self.ori_img[i][j][0] != self.skt_img[i][j][0]):
                    self.skt_pos[i][j] = 1

    def build_weight_b(self):
        weight_data = []
        row_inds = []
        col_inds = []
        # construct weight matrix
        for w in range(self.width):
            for h in range(self.height):
                if self.skt_pos[w][h] == 0:
                    neighbor_value = []
                    for i in range(w - 1, h + 2):
                        for j in range(h - 1, h + 2):
                            if (0 <= i and i < self.width - 1 and 0 <= j and j < self.height - 1):
                                if (w != i) | (h != j):
                                    neighbor_value.append(self.y_ori[w, h])
                                    row_inds.append(w * self.height + h)
                                    col_inds.append(i * self.height + j)
                    sigma = np.var(np.append(neighbor_value, self.y_ori[w, h]))
                    if sigma < 1e-6:
                        sigma = 1e-6
                    w_rs = np.exp(- np.power(neighbor_value - self.y_ori[w][h], 2) / sigma)
                    w_rs = - w_rs / np.sum(w_rs)
                    for item in w_rs:
                        weight_data.append(item)
                weight_data.append(1)
                row_inds.append(w * self.height + h)
                col_inds.append(w * self.height + h)
        self.W = scipy.sparse.csc_matrix((weight_data, (row_inds, col_inds)), shape=(self.img_size, self.img_size))
        # construct b
        self.b_u = np.zeros(self.img_size)
        self.b_v = np.zeros(self.img_size)
        # skt_pos_vec is the indix of nonzero element
        skt_pos_vec = np.nonzero(self.skt_pos.reshape(self.img_size))
        self.b_u[skt_pos_vec] = self.u_skt[skt_pos_vec]
        self.b_v[skt_pos_vec] = self.v_skt[skt_pos_vec]

    def color(self):
        u_res = scipy.sparse.linalg.spsolve(self.W, self.b_u).reshape((self.width, self.height))
        v_res = scipy.sparse.linalg.spsolve(self.W, self.b_v).reshape((self.width, self.height))

        yuv_res = np.dstack((self.y_ori.astype(np.float32), u_res.astype(np.float32), v_res.astype(np.float32)))
        rgb_res = cv2.cvtColor(yuv_res, cv2.COLOR_YUV2RGB)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0rOLyRqC-1661740668372)(vx_images/411431715944895.png =615x)]

  1. 学会用类和方法实现。在上次的任务中,需要定义三个函数然后重复写输入输出,这样比较麻烦。但用类和方法实现的话,对方法输出的变量加上self,就可以在下个方法中直接使用,更加简洁。
  2. sketch很重要。图片最好用bmp格式,而且图片质量与上色的位置和色彩强度很有关系。
  3. 用csc或者lil配合spsolve求解线性方程,速度比较快。

4. 心得体会

  • sketch很重要。图片最好用bmp格式,而且图片质量与上色的位置和色彩强度很有关系。
  • 用csc或者lil配合spsolve求解线性方程,速度比较快。

5. 参考文献

[1] Colorization using optimization

[2] 读源码学算法之Colorization
[3] 机器学习:Colorization using Optimization
[4] Colorization_using_Optimization code
[5] Colorization
[6] Colorization_using_Optimization code2
[7] ColorizationUsingOptimization

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 色彩优化是一种利用优化算法对黑白进行自动上色的技术。该技术可以通过对像中的像素进行分析和处理,自动为其添加适当的颜色,从而使黑白像变得更加生动、真实。这种技术在计算机视觉、像处理等领域有着广泛的应用。 ### 回答2: 色彩恢复是一种通过优化算法将黑白像转换为彩色像的技术。它是计算机视觉领域的重要研究方向之一。传统的像处理方法主要依赖人工干预来实现,而基于优化的色彩恢复利用机器习和计算机视觉的技术进行自动化处理。 基于优化的色彩恢复技术一般分为两个主要步骤:色彩传递和色彩生成。首先,通过色彩传递,算法通过分析已有彩色像和黑白像的对应关系来传递色彩信息。这可以通过匹配像素或者更复杂的方法实现。接下来,利用优化算法进行色彩生成,以确保生成的彩色像与原始彩色像尽可能相似。这些优化算法可以使用最小二乘法、最大似然估计或其他适用的数模型来定义目标函数,并通过在参数空间中搜索来最小化目标函数。 色彩恢复的优化算法存在一些挑战。首先,黑白像提供的信息有限,因此算法需要对进行适当的推测和填充。其次,颜色的感知是主观的,因此算法需要在保留像细节的同时提供可接受的结果。此外,算法的效率也是一个重要的考虑因素,因为处理大型像需要较长的时间。 虽然色彩恢复领域仍然存在一些挑战,但优化技术已经取得了一定的进展。它已经成功应用于许多应用领域,如照片修复、电影和动画的彩色化等。随着深度习等技术的快速发展,我们可以期待色彩恢复技术在未来会有更广泛的应用。 ### 回答3: 色彩优化是一种通过优化算法为黑白或灰度像增加色彩的技术。它的目标是将颜色添加到像中,以使其看起来更真实、更有生气。色彩优化通常分为两个主要步骤:预处理和优化。 在预处理阶段,首先需要将黑白或灰度像转换为带有彩色像的特征空间。这可以通过使用计算机视觉和机器习算法来实现。其中一种常见的方法是使用卷积神经网络(CNN)对进行训练,从而习出像的特征并将其连接到真实的彩色像。 在优化阶段,算法通过最小化颜色误差函数来为像添加色彩。颜色误差函数衡量了生成的彩色像与真实彩色像之间的差异。通过调整像中的像素值来减小误差函数,优化算法将像从黑白或灰度转变为彩色。一种常见的优化方法是使用梯度下降算法,以逐步改变像素值,直到误差最小化为止。 色彩优化可以应用于各种领域,例如历史照片复原、电影和视频修复、艺术创作等。通过为这些像增加色彩,我们可以还原历史照片的原貌,使电影和视频更加逼真,以及为艺术家提供更多的创作想象空间。 然而,色彩优化也有一些挑战和限制。一方面,算法需要拥有足够的训练数据和可靠的特征提取模型,以便为像正确地赋予色彩。另一方面,对于某些像,特别是低质量的像,色彩优化可能会产生不自然或不准确的结果。因此,我们需要不断改进算法和提升训练模型,以提高色彩优化的效果。 综上所述,色彩优化是一种通过优化算法为黑白或灰度像添加色彩的技术。它通过预处理和优化来实现,可以广泛应用于不同领域,并有着不同程度的挑战和限制。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

「已注销」

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值