使用Python和OpenCV在图像之间执行超快速的颜色转换
Posted 程序媛一枚~
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Python和OpenCV在图像之间执行超快速的颜色转换相关的知识,希望对你有一定的参考价值。
这篇博客将介绍如何使用Python和OpenCV在图像之间执行超快速的颜色转换。
与Reinhard基于直方图的颜色传递方法不同,该方法严格依赖Lab*颜色空间中像素强度的平均值和标准偏差,因此非常高效,能够快速处理非常大的图像。
1. 效果图
如下图所示,将左图水母蓝转移到中间珊瑚红上,得到转换空间后的图想蓝红珊瑚图
效果图2如下,将原图珊瑚红的色彩转移到中间水母蓝图像上,得到右侧的有点紫白兰的水母图
2. 原理
2.1 颜色转移算法
有俩种方法可以实现颜色转换:
-
基于直方图的方法,该方法旨在平衡三种“类型”的垃圾箱:相等、过量和不足。
该方法效果好,但以牺牲速度为代价。使用此算法需要对源图像中的每个像素执行查找,这将随着图像大小的增长而变得非常昂贵。 -
颜色转移算法——它只使用L * a * b 图像通道的平均值和标准偏差。没有复杂的代码,没有计算直方图,只是简单的统计数字。这种方法可以轻松地处理巨大的图像。
通过分别利用Lab颜色空间和每个L、a和b通道的平均值和标准偏差,可以在两幅图像之间传递颜色。
2.2 步骤
- 输入源图像和目标图像。源图像包含希望目标图像模拟的颜色空间。左侧的日落图像是我的源,中间的图像是我的目标,右侧的图像是应用于目标的源的颜色空间。
- 将源图像和目标图像转换为Lab颜色空间。**Lab颜色空间模拟感知一致性,其中颜色值的微小变化也应产生颜色重要性的相对相等变化。与标准RGB颜色空间相比,Lab*颜色空间在模拟人类如何解读颜色方面做得更好,它在颜色传递方面非常有效。**
- 拆分源和目标的通道。
- 计算源图像和目标图像的每个Lab*通道的平均值和标准偏差。
- 从目标通道中减去目标图像的Lab*通道的平均值。
- 通过目标的标准偏差除以源的标准偏差,再乘以目标通道,对目标通道进行缩放。
- 为源添加Lab*通道的方式。
- 剪裁范围[0,255]之外的任何值(注意:此步骤不是原始文件的一部分。我添加它是因为OpenCV处理颜色空间转换的方式。如果要在不同的语言/库中实现此算法,则必须自己执行颜色空间转换,或者了解库如何进行转换)。
- 将频道重新合并在一起。
- 从Lab*空间转换回RGB颜色空间。
2.3 算法改进
虽然Reinhard等人的算法速度极快,但有一个特别的缺点——它依赖于全局颜色统计,因此具有类似像素强度值的大区域会显著影响平均值(从而影响整体颜色转移)。
优化可以考虑两种方案:
-
在较小的感兴趣区域(ROI)中计算源图像的平均值和标准偏差,ROI是希望模拟的颜色,而不是使用整个图像。采用这种方法将使平均值和标准偏差更好地表示期望使用的颜色空间。
-
对两幅图像应用k均值聚类。可以在Lab*颜色空间中对每个图像的像素强度进行聚类,然后使用欧几里德距离确定两个图像之间最相似的质心。然后,只计算这些区域内的统计数据。同样这将使平均值和标准差产生更“局部”的影响,并有助于缓解全局统计数据的过度代表性问题。 缺点是这种方法速度要慢得多。
3. 源码
# USAGE
# python example.py --source images/sm.jpg --target images/sh.jpg
import argparse
import cv2
# 导入必要的类
from color_transfer import color_transfer
def show_image(title, image, width=300):
# 缩放照片为固定宽度像素,默认300像素
r = width / float(image.shape[1])
dim = (width, int(image.shape[0] * r))
resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
# 展示缩放的照片
cv2.imshow(title, resized)
def str2bool(v):
if v.lower() in ('yes', 'true', 't', 'y', '1'):
return True
elif v.lower() in ('no', 'false', 'f', 'n', '0'):
return False
else:
raise argparse.ArgumentTypeError('Boolean value expected.')
# 构建命令行参数及解析
ap = argparse.ArgumentParser()
ap.add_argument("-s", "--source", required=True,
help="Path to the source image")
ap.add_argument("-t", "--target", required=True,
help="Path to the target image")
ap.add_argument("-o", "--output", help="Path to the output image (optional)")
args = vars(ap.parse_args())
# 加载照片
source = cv2.imread(args["source"])
target = cv2.imread(args["target"])
# 转换原图的颜色到目标图像
transfer = color_transfer(source, target)
# 检查是否保存输出图像
if args["output"] is not None:
cv2.imwrite(args["output"], transfer)
# 展示照片直至按键
show_image("Source", source)
show_image("Target", target)
show_image("Transfer", transfer)
cv2.waitKey(0)
参考
以上是关于使用Python和OpenCV在图像之间执行超快速的颜色转换的主要内容,如果未能解决你的问题,请参考以下文章
使用OpenCV在图像和视频流中执行基于深度学习的超级分辨率
使用 Redis 在 C++ 和 python 之间共享 Opencv 图像
Android App开发超实用实例 | OpenCV在Android手机实现在图像上添加文本