opencv进阶基于opencv的图像着色(代码片段)

david123_xw david123_xw     2023-01-13     525

关键词:


有时技术会增强艺术,有时它会破坏艺术。

为黑白电影着色是一个可以追溯到 1902 年的非常古老的想法。几十年来,许多电影创作者反对为黑白电影着色的想法,并认为这是对他们艺术的破坏。今天,它被认为是对艺术形式的一种改进。

如果算法不使用任何用户输入,那不是很酷吗?

1.定义着色问题

让我们首先根据 CIE Lab 色彩空间来定义着色问题。与 RGB 颜色空间一样,它是一个 3 通道颜色空间,但与 RGB 颜色空间不同的是,颜色信息仅在 a(绿-红分量)和 b(蓝-黄分量)通道中进行编码。 L(亮度)通道仅编码强度信息。

我们想要着色的灰度图像可以看作是图像在Lab颜色空间中的L通道,我们的目标是找到a和b分量。这样得到的Lab图像可以使用标准颜色空间变换转换为RGB颜色空间。例如,在OpenCV中,这可以使用带有COLOR_BGR2Lab选项的cvtColor来实现。

为了简化计算,Lab 颜色空间的 ab 空间被量化为 313 个 bin,如下图所示。而不是为每个像素找到 a 和 b 值,因为这种量化,我们只需要找到一个介于 0 和 312之间的 bin 编号。另一种思考问题的方式是我们已经有了取值从 0 到 255 的 L 通道,我们需要找到取值在 0 到 312 之间的 ab 通道。所以颜色预测任务现在是变成了多分类问题,其中每个灰色像素有 313 个类别可供选择。

2.用于着色的 CNN 架构

Zhang 等人提出的架构是具有多个卷积块的 VGG 式网络。每个块都有两个或三个卷积层,后跟一个修正线性单元 (ReLU),并终止于一个批量归一化层(BN)。与 VGG 网络不同,它没有池化或全连接层。

输入图像被重新缩放为 224×224。让我们用 X X X表示这个重新缩放的灰度输入图像。

当它通过上图所示的神经网络时,它会被神经网络转化为 Z ^ \\hat Z Z^。在数学上,网络的这种转换可以写成 Z ^ = G ( X ) \\hat Z = G(X) Z^=G(X)

Z ^ \\hat Z Z^的维度是 H ∗ W ∗ Q H*W*Q HWQ,其中 H ( = 56 ) H(=56) H(=56) W ( = 56 ) W(=56) W(=56)是最后一个卷积层输出的高度和宽度。对于每个 H ∗ W H*W HW像素, Z ^ \\hat Z Z^包含一个 Q ( = 313 ) Q(=313) Q(=313)值向量,其中每个值表示像素属于该类的概率。我们的目标是为每个概率分布 Z ^ h , w \\hat Z_h,w Z^h,w找到一对 ab 通道值。

3.从 Z ^ \\hat Z Z^恢复彩色图像

上图所示的 CNN 为我们提供了来自调整大小的输入图像 X X X的分布集合 Z ^ \\hat Z Z^。让我们看看如何从 Z ^ \\hat Z Z^ 中的每个分布中恢复单个 ab 值对。

您可能会认为我们可以简单地取分布的平均值并选择与最近的量化 bin 中心相对应的 ab 对。不幸的是,这种分布不是高斯分布,分布的均值仅对应于不自然的不饱和颜色。要理解这一点,请想一想天空的颜色——它有时是蓝色的,有时是橙黄色的。天空颜色的分布是双峰的。在为天空着色时,蓝色或黄色都会产生合理的颜色。但是蓝色和黄色的平均值是一种无趣的灰色。

那么为什么不使用分布模式来获得蓝色或黄色的天空呢?当然,作者尝试过,虽然它提供了鲜艳的色彩,但有时会破坏空间一致性。他们的解决方案是在均值和模式估计之间进行插值,以获得称为退火均值的量。使用称为温度 (T) 的参数来控制插值程度。 T=0.38 的最终值用作两个极端之间的权衡。


使 用 温 度 ( T ) 的 退 火 均 值 用 于 在 分 布 的 均 值 和 众 数 之 间 进 行 插 值 。 使用温度 (T) 的退火均值用于在分布的均值和众数之间进行插值。 使(T)退

对应于 Z ^ \\hat Z Z^分布的退火均值的 ab 对表示为 Y ^ h , w \\hat Y_h,w Y^h,w,可以写成原始分布 Z ^ h , w \\hat Z_h,w Z^h,w的变换 Y ^ = H ( Z ^ ) \\hat Y=H(\\hat Z) Y^=H(Z^)

请注意,当图像通过 CNN 时,其大小减小到 56×56。因此,预测的 ab 图像 Y ^ \\hat Y Y^也具有 56×56 的维度。为了获得彩色图像,将其上采样到原始图像大小,然后添加到亮度通道 L,以生成最终的彩色图像。

4.具有颜色重新平衡的多项式损失函数

所有神经网络都是通过定义损失函数来训练的。训练过程的目标是最小化训练集的损失。在着色问题中,训练数据由数千张彩色图像及其灰度版本组成。

CNN 的输出是 Z ^ \\hat Z Z^,输入图像是 X X X。我们需要将训练集中的所有彩色图像转换为其对应的值。在数学上,我们只是想反转映射 H H H Z = H − 1 ( Y ) Z=H^-1(Y) Z=H1(Y)

对于输出图像 Y Y Y的每个像素 Y h , w Y_h,w Yh,w,我们可以简单地找到最近的 ab bin 并将 Z h , w Z_h,w Zh,w表示为一个独热向量,其中我们将 1 分配给最近的 ab bin,将 0 分配给所有其他 312 个 bin。但为了获得更好的结果,我们考虑了5个最近邻,并使用高斯分布来计算分布 Z h , w Z_h,w Zh,w,这取决于与真实值的距离。

如果您之前使用过 CNN,您可能会想使用标准交叉熵损失来比较真实值 Z Z Z和预测值 Z ^ \\hat Z Z^
L ( Z ^ , Z ) = − 1 H W ∑ h , w ∑ q Z h , w , q l o g ( Z ^ h , w , q ) L(\\hat Z, Z) = -\\frac1HW\\sum_h,w\\sum_qZ_h,w,qlog(\\hat Z_h,w,q) L(Z^,Z)=HW1h,wqZh,w,qlog(Z^h,w,q)
不幸的是,上述损失函数会产生非常暗淡的颜色。这是因为 ImageNet 中的颜色分布在灰线周围很重。

5.彩色化的结果

作者分享了两个版本的经过训练的 Caffe 模型 - 有和没有颜色重新平衡。我们尝试了两个版本,并在下图中分享了结果。中间一列显示没有重新平衡颜色的版本,最后一列显示重新平衡的版本。

正如我们所见,色彩重新平衡使许多图像非常生动活泼。它们中的大多数都是似是而非的颜色。另一方面,有时它也会为某些图像添加一些不需要的饱和色块。

请记住,当我们尝试将灰度图像转换为彩色图像时,可能有多种合理的解决方案。因此,评估良好着色的方法不是它与基本事实的匹配程度,而是它在人眼中看起来的可信度和愉悦度。

5.1 动物

该模型在动物图像上表现非常好,尤其是猫和狗。这是因为 ImageNet 包含非常大的这些动物集合。

5.2户外场景

该模型在表现蓝天和绿色植被的户外场景方面也做得非常好。另请注意,给定一棵树的轮廓,该模型预测橙色天空表明它已捕捉到日落的概念。



5.3草图

最后,即使是草图,模型也会产生合理的着色。


6.在 OpenCV 中实现着色

作者在此位置的 GitHub 中提供了预训练模型和网络详细信息。下面,我们将回顾 Python 和 C++ 代码,使用这些预训练模型对给定的灰度图像进行着色。我们的代码基于 OpenCV 示例代码。我们使用了 OpenCV 4.5.1 版。我们还提供代码来为给定的灰度视频着色。

链接:https://pan.baidu.com/s/14_my8daL2SxgFVymQy-0Dg 
提取码:1v8m

(1)Python
图像着色代码:

# colorizeImage.py
# Usage 
# python colorizeImage.py --input greyscaleImage.png

import numpy as np
import cv2 as cv
import argparse
import os.path

parser = argparse.ArgumentParser(description='Colorize GreyScale Image')
parser.add_argument('--input', help='Path to image.', default="greyscaleImage.png")
args = parser.parse_args()

if args.input==None:
    print('Please give the input greyscale image name.')
    print('Usage example: python3 colorizeImage.py --input greyscaleImage.png')
    exit()

if os.path.isfile(args.input)==0:
    print('Input file does not exist')
    exit()

# 读取输入图像
frame = cv.imread(args.input)

# 指定 2 个模型文件的路径
protoFile = "./models/colorization_deploy_v2.prototxt"
weightsFile = "./models/colorization_release_v2.caffemodel"
# weightsFile = "./models/colorization_release_v2_norebal.caffemodel"

# 加载聚类中心
pts_in_hull = np.load('./pts_in_hull.npy')

# 将网络读入内存
net = cv.dnn.readNetFromCaffe(protoFile, weightsFile)

# 将聚类中心填充为 1x1 卷积核
pts_in_hull = pts_in_hull.transpose().reshape(2, 313, 1, 1)
net.getLayer(net.getLayerId('class8_ab')).blobs = [pts_in_hull.astype(np.float32)]
net.getLayer(net.getLayerId('conv8_313_rh')).blobs = [np.full([1, 313], 2.606, np.float32)]

#来自 opencv 示例
W_in = 224
H_in = 224

img_rgb = (frame[:,:,[2, 1, 0]] * 1.0 / 255).astype(np.float32)
img_lab = cv.cvtColor(img_rgb, cv.COLOR_RGB2Lab)
img_l = img_lab[:,:,0] # 拉出L通道

# 将亮度通道调整为网络输入大小
img_l_rs = cv.resize(img_l, (W_in, H_in)) #
img_l_rs -= 50 # 减去50中心化

net.setInput(cv.dnn.blobFromImage(img_l_rs))
ab_dec = net.forward()[0,:,:,:].transpose((1,2,0)) # 这是我们的结果

(H_orig,W_orig) = img_rgb.shape[:2] # 原始图像大小
ab_dec_us = cv.resize(ab_dec, (W_orig, H_orig))
img_lab_out = np.concatenate((img_l[:,:,np.newaxis],ab_dec_us),axis=2) # 与原始图像 L 连接
img_bgr_out = np.clip(cv.cvtColor(img_lab_out, cv.COLOR_Lab2BGR), 0, 1)

outputFile = args.input[:-4]+'_colorized.png'
cv.imwrite(outputFile, (img_bgr_out*255).astype(np.uint8))
print('Colorized image saved as '+outputFile)
print('Done !!!')

视频着色代码

# colorizeVideo.py
# Usage
# python colorizeVideo.py --input greyscaleVideo.mp4

import numpy as np
import cv2 as cv
import argparse
import os.path

parser = argparse.ArgumentParser(description='Colorize GreyScale Video')
parser.add_argument('--input', help='Path to video file.', default="greyscaleVideo.mp4")
args = parser.parse_args()

if args.input == None:
    print('Please give the input greyscale video file.')
    print('Usage example: python colorizeVideo.py --input greyscaleVideo.mp4')
    exit()

if os.path.isfile(args.input) == 0:
    opencv进阶--图像变换(代码片段)

...连接常在需要对两幅图像内容进行对比的时候用到的。在OpenCV中针对图像左右连接和上下连接提供了两种不同的函数,vconcat()函数用于实现图像或矩阵数据的上下连接,h 查看详情

opencv进阶图像操作(代码片段)

距离基础操作篇也差不多一周了,其中有许多文章用到了一些常用的但还没来得及介绍的图像操作函数,于是这一篇进阶篇就应运而生了。本篇会首先通俗地讲解各种图像处理的基本原理以帮助了解,然后运用代码帮... 查看详情

opencv进阶图像操作(代码片段)

距离基础操作篇也差不多一周了,其中有许多文章用到了一些常用的但还没来得及介绍的图像操作函数,于是这一篇进阶篇就应运而生了。本篇会首先通俗地讲解各种图像处理的基本原理以帮助了解,然后运用代码帮... 查看详情

基于opencv的图像融合(代码片段)

 版本由于每个版本的代码偏差都比较大,这里是基于opencv3.4.5版本的开发https://github.com/opencv/opencv/releases/tag/3.4.5https://github.com/opencv/opencv_contrib/releases/tag/3.4.5编译命令:cmake-DOPENCV_ENABLE_NONFREE=ON-DBUILD_E 查看详情

opencv-图像着色(采用dnn模块导入深度学习模型)(代码片段)

作者:Steven版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处实现原理    图像着色最早是应用在图像修复方面,将一些过去的黑白旧照根据预设色盘上色,得到色彩... 查看详情

opencv进阶--图像颜色空间(代码片段)

一、颜色模型与转换1.1RGB颜色模型    RGB颜色空间模型:     该模型的命名方式是采用三种颜色的英文首字母,分别是红色,绿色,和蓝色。在RGB模型中所有的颜色都是这三种颜色通过不同比例的混合模型... 查看详情

opencv实战——基于grabcut算法的图像分割(代码片段)

OpenCV实战——基于GrabCut算法的图像分割1.GrabCut算法2.图像分割实战3.完整代码相关链接1.GrabCut算法在OpenCV策略设计模式一节中,我们已经了解了颜色信息如何用于将图像分割成与场景特定元素相对应的区域。每类对象通常具... 查看详情

opencv进阶-基于coco数据集训练好的模型,修改类别显示代码,实现自定义检测物体

coco 查看详情

opencv进阶-基于coco数据集训练好的模型,修改类别显示代码,实现自定义检测物体

coco 查看详情

opencv基础到进阶

本文为系列文章的第2篇,主要讲解对图像的像素的操作方法。2.1存取像素值为了存取矩阵元素,需要指定元素所在的行和列,程序会返回相应的元素。单通道图像返回单个数值,多通道图像,返回的则是一组向量(Vector)。我们通... 查看详情

python机器视觉--opencv进阶(核心)--图像二值化(代码片段)

1.图像二值化1.1图像全局二值化二值化:将图像的每个像素变成两种值,比如0,255.threshold(src,thresh,maxval,type[,dst])src最好是灰度图thresh:阈值maxval:最大值,最大值不一定是255type:操作类型.常见操作类型如下:简单解释:1.若图片数值大... 查看详情

opencv基础(11)基于opencv的边缘检测(代码片段)

...邻近的像素中寻找这些变化。来吧,让我们探讨一下OpenCV中可用的两种重要边缘检 查看详情

java图像处理基于opencv与jvm-----矩阵处理图像(代码片段)

...读取图片,然后输出矩阵对象本身的一些信息importorg.opencv.core.CvType;importorg.opencv.core.Mat;importorg.opencv.core.Core; 查看详情

opencv进阶-打印帧数和运行时间的函数(代码片段)

1.每张图像的运行时间和帧率的计算公式总时间/总帧数=每一帧图像播放时停留的时间。总帧数/总时间=帧率2.getTickFrequency()getTickFrequency():返回CPU一秒中所走的时钟周期数。即一秒钟的重复次数。getTickFrequency()/1000:即一... 查看详情

学习opencv4基于opencv的手写数字识别(代码片段)

本内容分享于课程《OpenCV入门精讲(C++/Python双语教学)》,地址:OpenCV入门精讲(C++/Python双语教学)如果想提升C++的编程水平,可以参考课程:C++进阶学习OpenCV课程中还有... 查看详情

图像检索:基于opencv实现小型的图像数据库检索(代码片段)

本文对前面的几篇文章进行个总结,实现一个小型的图像检索应用。一个小型的图像检索应用可以分为两部分:train,构建图像集的特征数据库。retrieval,检索,给定图像,从图像库中返回最类似的图像构建图像数据库的过程如... 查看详情

java图像处理基于opencv与jvm-----加载保存图像

加载图片openCv有一个名imread的简单函数,用于从文件中读取图像imread函数位于Imgcodecs类的同名包中。加载图片代码importorg.opencv.core.CvType;importorg.opencv.core.Mat;importorg.opencv.core.Core;importorg.opencv.imgcodecs.Imgcodecs;import 查看详情

Python/OpenCV - 基于机器学习的 OCR(图像到文本)

】Python/OpenCV-基于机器学习的OCR(图像到文本)【英文标题】:Python/OpenCV-MachineLearning-basedOCR(ImagetoText)【发布时间】:2017-03-2611:58:36【问题描述】:我正在尝试通过Python2.7接口使用OpenCV来实现基于机器学习的OCR应用程序来解析图... 查看详情