welsh颜色迁移算法实现过程-python版

2023-11-13

很久很久以前,笔者曾经研究学习过welsh算法,并用c++实现过,见链接 welsh颜色迁移算法实现过程;后来心血来潮想再看看效果,却发现opencv的版本已经更迭变化太快了,且有学友也想复现一下实验效果,因此决定用再用python实现一次改算法。

welsh的流程如下:

1.将目标图像和样本图像转换到Lab空间;

2.对目标图像和样本图像进行亮度重映射,保证后续的像素匹配正确进行;

3.从参考图片中选择一部分样本点,将这些样本点的像素亮度值L和领域亮度值σ得方差保存起来,作为权值W,W = L/2 + σ/2;

4.对目标图像进行逐像素扫描,对每个像素,计算其权值W,即为亮度值L和领域亮度值σ之和然后除以2,然后在第三步得到的样本点钟找到与其权值最接近的参考点,并将改点的a通道和b通道的值赋给目标图像的像素。

5.将图像从Lab空间转化到RGB空间。
 

ok,我们的想法很简单,对参考图片创建一个模型,选取一定量的参考点,对每个参考点,记录其权值W,我们用代码来实现这个过程:

for _ in range(self.segment):
    height_index = np.random.choice(self.height_array)
    width_index = np.random.choice(self.width_array)

    pixel = Pixel(height_index, width_index)
    pixel_light = self.l_image[pixel.x, pixel.y]
    pixel_a = self.a_image[pixel.x, pixel.y]
    pixel_b = self.b_image[pixel.x, pixel.y]

    pixel_std = self.get_domain_std(pixel)

    weight_list.append(WeightPixel(pixel_light * self.ratio + pixel_std * (1 - self.ratio),
                                   pixel_a,
                                   pixel_b))
weight_list.sort()
return weight_list

segment是我们需要选取的参考点个数,Pixel和WeightPixel是我们自定义的类,看不懂没关系,后续我会上传整个代码,大致意思就是计算参考点附近的权值W,然后保存到一个列表中,WeightPixel是根据权值W进行排序的。为什么要排序?因为排序后我们就能利用二分查找快速定位到W值最接近的点了。

ok,建立了参考模型,我们就可以对输入图片进行分析了,(我讲述的时候省略了转换到Lab空间这一步骤),首先我们进行亮度重映射,代码如下:

    pixel_ratio = (consult_max_pixel - consult_min_pixel) / (max_pixel - min_pixel)

    for i in range(height):
        progress_bar(i / height)
        for j in range(width):
            pixel_light = consult_min_pixel + (gray_image_l_origin[i, j] - min_pixel) * pixel_ratio

            gray_image_l[i, j] = pixel_light

prograss_bar是进度条,这里不需要看,consult_min_pixel和consult_max_pixel是对应的参考图像亮度最小值和最大值,min_pixel和max_pixel是输入图像亮度的最小值和最大值,这里比较好理解,就是讲输入图像的亮度值按比例映射到参考图像的范围内。

后续,我们对输入图像的每个像素值进行讨论,计算每个像素值的权值W,然后查找参考点中权值W最接近的点(这里可以体现出之前排序的作用),将参考点的色彩信息赋值给该像素点的色彩像素,代码如下:

    for row in range(height):
        progress_bar(row / height)
        for col in range(width):
            pixel = Pixel(row, col)
            pixel_light = gray_image_l[pixel.x, pixel.y]

            # 求窗口内像素方差;
            window_left = max(pixel.x - window_size, 0)
            window_right = min(pixel.x + window_size + 1, height)
            window_top = max(pixel.y - window_size, 0)
            window_bottom = min(pixel.y + window_size + 1, width)

            window_slice = gray_image_l[window_left: window_right, window_top: window_bottom]

            pixel_std = np.std(window_slice)

            weight_pixel = WeightPixel(ratio * pixel_light + (1 - ratio) * pixel_std,
                                       0, 0)
            
            # 二分查找,另外,为了避免列表越界,当找到列表两边时需要调整一下;
            search_pixel = bisect.bisect(consult_image.get_weight_list(), weight_pixel)
            search_pixel = 1 if search_pixel == 0 else search_pixel
            search_pixel = len(consult_image.get_weight_list()) - 1 \
                if search_pixel == len(consult_image.get_weight_list()) else search_pixel

            left_pixel = consult_image.get_weight_list()[search_pixel - 1]
            right_pixel = consult_image.get_weight_list()[search_pixel]

            nearest_pixel = left_pixel if left_pixel.weight + right_pixel.weight > 2 * weight_pixel.weight else right_pixel

            gray_image_a[row, col] = nearest_pixel.a
            gray_image_b[row, col] = nearest_pixel.b

ok,代码有点长,功能都写在注释里了,应该比较容易看懂。

最后,转换会RGB图像,保存:

rgb_image = cv2.cvtColor(merge_image, cv2.COLOR_LAB2BGR)
cv2.imwrite("out.jpg", rgb_image)

实验效果如下:

 

整个代码见下面链接,运行方式很简单,python colorize.py即可,可以在代码里改图片的路径,也可以修改一下代码,添加命令行参数等;另,代码需优化的地方还很多,且注释不规范,例如函数取名不优雅、占用内存的height_array数组等,都可以去掉,也可以把求权值的功能写到一个函数中,等等。

csdn资源链接: https://download.csdn.net/download/zsy162534/11128843

百度云链接:链接:https://pan.baidu.com/s/1sMc26QRQ1l6Pljv7HfYXlw 
提取码:n4ap 

最后再写一句,最新的图像着色都是以深度学习为主了,效果也会更好一些,见两个个2016年的深度学习图像着色的效果:

https://tinyclouds.org/colorize/ ; https://github.com/richzhang/colorization

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

welsh颜色迁移算法实现过程-python版 的相关文章

随机推荐