Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何用 Python 给照片换色

如何用 Python 给照片换色

作者头像
机器视觉CV
发布于 2019-10-20 10:53:51
发布于 2019-10-20 10:53:51
3.4K00
代码可运行
举报
文章被收录于专栏:机器视觉CV机器视觉CV
运行总次数:0
代码可运行

最近遇到了一个需求,就是对图片进行色彩风格转换,让一个物体可以以各种不同的色彩来呈现。

比如一个红色的苹果,我想把它转化成绿色,这可怎么办呢?本来想的解决方案是先识别边界,然后对边界内区域进行色彩替换或者填充,这样整个流程就分成了两步,首先需要进行边界判断,有了边界之后才能对某些区域颜色进行替换填充,填充的区域还是不规则的,填充的颜色也需要根据实际的情况来变化,同时还要兼顾阴影、高光等等的处理,想想真是头大。

然后我就突然想到了之前学 PS 的时候,曾经做过对某一张图片进行色调替换,我还记得当时调的内容是「色相」,通过调节这个值可以实现各种色调的转换。这之后我就心想,能不能用程序来做这件事呢?

于是我就开始了对图像色彩的一些研究,研究完了之后就实现了用 Python 来更换图片色调的功能,将这篇文章顺便记录下来。

先给大家看看效果吧,就比如我从百度上随便搜一张图,比如热气球吧,是这样子:

原图

我把它转成红色、黄色、蓝色、紫色,基本就是这个样子:

红色风格

黄色风格

绿色图片

蓝色图片

这里的图片都是经过 Python 自动转换算法实现的,主要调节的就是色相。其实代码实现是比较简单的,但在实现之前需要了解一些图像色彩知识。了解了这些之后我们再实现才会更加游刃有余。

下面我们就首先来了解一下图像色彩的基本知识,然后用 Python 实现色调转换算法吧。

RGB

首先让我们来了解下颜色的三原色,RGB。

RGB,其实就是三种颜色,分别代表红色(Red)、绿色(Green)、蓝色(Blue),用这三种原色颜色混合可以表示任意的颜色。RGB 是根据颜色发光的原理来设计的,比如这里有红绿蓝三道光,当三束光混合在一起的时候,其呈现的最终的光效颜色就取决于这三种原色光的强弱了。

•比如说红光最强,绿光和蓝光几乎没有,那么最后结果肯定呈现为红光了。•如果蓝光很弱,红光和绿光非常强,那么结果就是红光和绿光的混合光,也就黄光。•如果红绿蓝三种光都非常强,那么就会呈现三种光的混合光,也就是白光。•如果三种光都非常弱,那就几乎没有光,自然就是黑色了。

如果大家了解过 RGB 的一些知识的话,想必也见过这张混合光图:

但是这仅仅是一张平面图,并不能很好地体现三原色的混合关系,大家可以看这张图:

实际上可以对 RGB 色值建立一个三维坐标系,坐标原点就在上图中所看不见的那个正方体顶点,向左延伸为 R 红色轴,向右延伸为 B 蓝色轴,向上延伸为 G 绿色轴。

RGB 在进行色彩表示时使用了 256 阶,也就是从 0-255,可以由一个字节来表示。数值越大,RGB 三个轴,每个轴对应的数值越大,就代表其亮度越高,最亮就对应着 255,最暗就对应着 0。三个轴上的三个数字联合起来可以用来表示一个颜色。

例如:

•(255, 255, 255) 就代表 RGB 都是满的,组成白色。•(255, 255, 0) 就代表 R 红色是满的,G 绿色是满的,B 蓝色是没有的,红色和绿色混合为黄色,所以它就表示黄色。•(0, 0, 0) 就代表 RGB 都是没有的,呈现黑色。

因此,通过这三个数值,我们就可以实现任何颜色的表示了。

HSV

但了解了 RGB 显然不能应对我们的需求,它和色相也没有什么关系,所以这里我们还需要研究另外一个颜色模型,叫做 HSV。

HSV,又叫做 HSB,其实也是三个参数,分别是色调(Hue)、饱和度(Saturation)、明度(Brightness),在 HSV 中 V 代表 Value,也是明度的意思。通过这三个值,我们同样可以表示任意的颜色。

首先我们看看 HSV (HSB) 颜色模型的坐标轴图吧,它可以用这么一个锥形的坐标来表示:

色调,Hue,它是一种角度度量,就是图中 Hue 所示的角度,绕圆锥体一周。它的值是从红色开始逆时针方向计算的,红色是 0,绿色是 120,蓝色为 240,形成一个红绿蓝三原色组成的色带。

饱和度,Saturation,它是图中 Saturation 所示的方向,由最上面圆的圆心向外扩散。它表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为 0,饱和度达到最高。通常取值范围为 0-100,值越大,颜色越饱和。也就是说图中,圆心处饱和度为 0,越靠近边,饱和度越高,最高达到 100。

明度,Brightness,它表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关,对于物体色,此值和物体的透射比或反射比有关。通常取值范围为 0-100,0 对应黑色,100 对应白色。

另外大家如果用到取色板的话,它是这样子的:

你可以看到左边有个大的矩形,右边有个竖直的彩虹带。由于刚才所说的圆锥坐标不好表示,在调色板里面就把圆锥坐标拆成了两部分。

•右边的彩虹带就可以选择色调 Hue,拖动彩虹带的箭头位置就可以调整 Hue 的值。•左边的正方形就和饱和度 Saturation、明度 Brightness 有关,横坐标表示饱和度 Saturation,纵坐标表示 Brightness,从左到右,饱和度 Saturation 变高,从下到上,明度 Brightness 变高。•左下角,由于饱和度 Saturation 和明度 Brightness 都为 0,就呈现黑色。•左上角,由于饱和度 Saturation 为 0,所以相当于没有颜色,颜色最浅,但是它的明度 Brightness 达到了最高,所以它就显示没有颜色的明度最高的色,即白色。•右上角,由于饱和度 Saturation 和明度 Brightness 都为最高,那就显示最纯的 Hue 值。

这也就是 HSB 颜色模型的原理。

同样地,我们可以用 HSB 的三个值来表示任意的颜色,因此 HSB 也成为表示颜色的基本标准之一。

HSB 和 RGB 的转换

HSB 和 RGB 都能表示一个颜色,它们之间也是可以相互转换的,可以一一对应。

他们之间的转换逻辑这里就不再专门对其公式展开详解了,公式总结如下:

RGB to HSB

HSV to RGB

大家如果感兴趣想要研究的话也可以去:https://www.rapidtables.com/convert/color/hsv-to-rgb.html 来了解一下详情,这里还有详细的转换表格以及实时转换实现。

另外对于它们之间的转换算法,很多库都已经封装好了。我们可以直接调用,比如 Python 中的 colorsys 模块,就实现了 rgb_to_hsv 和 hsv_to_rgb 算法,我们也可以直接使用。

色调转换

了解了以上内容之后,我们就可以使用程序来实现色调转换了。相比我们已经知道应该改什么内容了,那就是修改 HSV 中的 H 值,通过不同的 H 值我们就可以将图片转换为不同的色调了。

具体思路是怎样的呢:

•首先获取图像每个像素的的 RGB 色值。•将 RGB 色值转化为 HSV 色值。•调整 HSV 色值中的 H。•将 HSV 色值转回 RGB 色值。•输出图像。

一共就是这么五步,这里的两个转换色值的操作我们就可以借助于 colorsys 模块。另外需要安装一个 pillow 模块:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
pip3 install pillow

安装完毕之后,我们准备任意一张图片,然后实现上面的五个步骤。

最终的代码实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import colorsysfrom PIL import Image
# 输入文件filename = 'input.jpg'# 目标色值target_hue = 0
# 读入图片,转化为 RGB 色值image = Image.open(filename).convert('RGB')
# 将 RGB 色值分离image.load()r, g, b = image.split()result_r, result_g, result_b = [], [], []# 依次对每个像素点进行处理for pixel_r, pixel_g, pixel_b in zip(r.getdata(), g.getdata(), b.getdata()):    # 转为 HSV 色值    h, s, v = colorsys.rgb_to_hsv(pixel_r / 255., pixel_b / 255., pixel_g / 255.)    # 转回 RGB 色系    rgb = colorsys.hsv_to_rgb(target_hue, s, v)    pixel_r, pixel_g, pixel_b = [int(x * 255.) for x in rgb]    # 每个像素点结果保存    result_r.append(pixel_r)    result_g.append(pixel_g)    result_b.append(pixel_b)
r.putdata(result_r)g.putdata(result_g)b.putdata(result_b)
# 合并图片image = Image.merge('RGB', (r, g, b))# 输出图片image.save('output.png')

具体的实现在代码注释里面已经很清楚了。

在这里我们将 target_hue 定义为 0。通过前文我们知道,Hue 为 0 代表红色,120 代表绿色,240 代表蓝色。我们可以自定义 0-355 这 360 个数值,实现不同的色调转换。

如果想输出其他颜色的图片,就把 target_hue 这个值改一下就好了。

看看最后的运行效果,输入是一张原图:

所以最后的输出效果就是如下的结果:

如果将代码中的 target_hue 值进行更改,就会呈现不同的颜色风格了,就像文中开头所示的一样。

比如把飞猪的 Logo 由黄色变为红色,都是可以做到的:

处理透明像素

上面的算法仅仅考虑了 RGB,如果有些图包含了透明像素,上面的程序对于透明像素是无法处理的,最后输出的结果会带有某种颜色的背景。

对于透明像素的处理,我们可以增加一个维度的值,就是 A,即 Alpha 透明度。

所以使用 RGBA 和 HSV 的转换我们就可以实现透明像素的处理了,代码实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import colorsysfrom PIL import Image
# 输入文件filename = 'input.png'# 目标色值target_hue = 0
# 读入图片,转化为 RGB 色值image = Image.open(filename).convert('RGBA')
# 将 RGB 色值分离image.load()r, g, b, a = image.split()result_r, result_g, result_b, result_a = [], [], [], []# 依次对每个像素点进行处理for pixel_r, pixel_g, pixel_b, pixel_a in zip(r.getdata(), g.getdata(), b.getdata(), a.getdata()):    # 转为 HSV 色值    h, s, v = colorsys.rgb_to_hsv(pixel_r / 255., pixel_b / 255., pixel_g / 255.)    # 转回 RGB 色系    rgb = colorsys.hsv_to_rgb(target_hue, s, v)    pixel_r, pixel_g, pixel_b = [int(x * 255.) for x in rgb]    # 每个像素点结果保存    result_r.append(pixel_r)    result_g.append(pixel_g)    result_b.append(pixel_b)    result_a.append(pixel_a)
r.putdata(result_r)g.putdata(result_g)b.putdata(result_b)a.putdata(result_a)
# 合并图片image = Image.merge('RGBA', (r, g, b, a))# 输出图片image.save('output.png')

在这里就是增加了对透明像素的处理,在图像 convert 和 merge 的时候都使用 RGBA 模式,就可以保留原有图片中的透明像素了。

以上便是使用 Python 程序自动调整色调的实现。

其他应用

另外对于图像调色的应用还有很多,比如我们可以不直接指定 Hue 的值,而是将 Hue 的值在原来的基础上增加或减少,则可以实现彩虹变色,如:

原图是这样子:

经过处理之后我们可以得到这样的效果:

这样我们使用程序处理出各种风格的好看的照片了,是不是很有意思呢?具体的实现可以参考:https://stackoverflow.com/questions/27041559/rgb-to-hsv-python-change-hue-continuously。

大家如果觉得有意思,就快来试试吧~

参考链接:

•https://blog.csdn.net/weixin_43280713/article/details/84133915•https://stackoverflow.com/questions/27041559/rgb-to-hsv-python-change-hue-continuously•https://blog.csdn.net/qq_33759946/article/details/90295377

图片来源于互联网公开内容,如有图片侵权,请联系我删除,谢谢。


个人站点:

Github: https://github.com/FLyingLSJ

CSDN : https://blog.csdn.net/LSJ944830401

BLOG: https://flyinglsj.github.io/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-10-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器视觉CV 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
[UWP]使用Writeable​Bitmap创建HSV色轮
HSV都是一种将RGB色彩模型中的点在圆柱坐标系中的表示法,这种表示法试图做到比RGB基于笛卡尔坐标系的几何结构更加直观。HSV即色相、饱和度、明度(英语:Hue, Saturation, Value),又称HSB,其中B即英语:Brightness。
dino.c
2019/01/18
1.1K0
[UWP]使用Writeable​Bitmap创建HSV色轮
【计算机视觉】使用OpenCV处理色彩空间(Python版)
GRAY色彩空间通道指的是灰度图像,灰度图像的通常只有1个,值范围是[0, 255],一共256个灰度级别。其中0表示纯黑色,255表示纯白色。0~255之间的数值表示不同的亮度(即色彩的深浅程度)的深灰色或浅灰色。因此,一副灰度图能展示丰富的细节信息,如图1所示。
蒙娜丽宁
2023/03/08
2.4K0
【计算机视觉】使用OpenCV处理色彩空间(Python版)
颜色空间RGB与HSV(HSL)的转换
一般的3D编程仅仅须要使用RGB颜色空间就好了,但事实上美术人员很多其它的是使用HSV(HSL),由于能够方便的调整饱和度和亮度。
全栈程序员站长
2021/12/17
3.8K0
颜色空间RGB与HSV(HSL)的转换
由RGB到HSV的转换详解
在图像处理中,最常见的就是RGB色彩模型。在RGB模型中,每种颜色出现在红、绿、蓝的原色光谱分量中。该模型基于笛卡尔坐标系。如图1所示,RGB原色值位于3个角上;二次色青色,深红色和黄色位于另外三个角上,黑色位于原点处,白色位于里原点最远的角上。
FPGA开源工作室
2020/02/25
3.3K0
数字视频基础知识
一、光和颜色 1 光和颜色 可见光是波长在380 nm~780 nm 之间的电磁波,我们看到的大多数光不是 一种波长的光,而是由许多不同波长的光组合成的。如果光源由单波长组成,就 称为单色光源。该光源具有能量,也称强度。实际中,只有极少数光源是单色的, 大多数光源是由不同波长组成,每个波长的光具有自身的强度。这称为光源的光 谱分析。 颜色是视觉系统对可见光的感知结果。研究表明,人的视网膜有对红、绿、 蓝颜色敏感程度不同的三种锥体细胞。红、绿和蓝三种锥体细胞对不同频率的光 的感知程度不同,对不同亮度的感知程度也不同。 自然界中的任何一种颜色都可以由R,G,B 这3 种颜色值之和来确定,以这 三种颜色为基色构成一个RGB 颜色空间。
lcyw
2022/06/10
7930
数字视频基础知识
基于OpenCV的彩色空间互转
图像彩色空间互转在图像处理中应用非常广泛,而且很多算法只对灰度图有效;另外,相比RGB,其他颜色空间(比如HSV、HSI)更具可分离性和可操作性,所以很多图像算法需要将图像从RGB转为其他颜色空间,所以图像彩色互转是十分重要和关键的。
Datawhale
2020/06/23
2.7K0
基于C/C++的HSV转RGB程序
HSV是根据颜色的直观特性由 A. R. Smith 在 1978 年创建的一种颜色空间, 也称六角锥体模型。其中的H、S、V分别代表色调(H)、饱和度(S)和明度(V)。 H参数表示色彩信息,即所处的光谱颜色的位置。该参数用一角度量来表示,红、绿、蓝分别相隔120度。互补色分别相差180度。用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,紫色为300°; 纯度S为一比例值,范围从0到1,它表示成所选颜色的纯度和该颜色最大的纯度之间的比率。S=0时,只有灰度。饱和度S表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。 V表示色彩的明亮程度,范围从0到1。有一点要注意:它和光强度之间并没有直接的联系。明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。 HSV对用户来说是一种直观的颜色模型。我们可以从一种纯色彩开始,即指定色彩角H,并让V=S=1 ,然后我们可以通过向其中加入黑色和白色来得到我们需要的颜色。增加黑色可以减小V而S不变,同样增加白色可以减小S而V不变。例如,要得到深蓝色,V=0.4 S=1 H=210度。要得到淡蓝色,V=1 S=0.4 H=210度。 一般说来,人眼最大能区分128种不同的色彩,130种色饱和度,23种明暗度。如果我们用16Bit表示HSV的话,可以用7位存放H,4位存放S,5位存放V,即745或者655就可以满足我们的需要了。 由于HSV是一种比较直观的颜色模型,所以在许多图像编辑工具中应用比较广泛,如Photoshop(在Photoshop中叫HSB)等等,但这也决定了它不适合使用在光照模型中,许多光线混合运算、光强运算等都无法直接使用HSV来实现。
跋扈洋
2022/12/03
1.2K0
基于C/C++的HSV转RGB程序
UI界面配色方法终极指南!一篇长文搞定所有问题
静电说:要培养对颜色的敏感度,你必须要了解色彩的原理。在这个基础上去感悟,久而久之,色彩会在你手中变的游刃有余。下面这篇终极色彩指南非常值得一看~让我们不妨再系统梳理一下你的配色技巧吧!
用户5009027
2022/05/23
3K0
UI界面配色方法终极指南!一篇长文搞定所有问题
【OpenCV】HSV颜色识别-HSV基本颜色分量范围
一般对颜色空间的图像进行有效处理都是在HSV空间进行的,然后对于基本色中对应的HSV分量需要给定一个严格的范围,下面是通过实验计算的模糊范围(准确的范围在网上都没有给出)。
用户2965768
2018/08/30
7.4K0
【OpenCV】HSV颜色识别-HSV基本颜色分量范围
OpenCV 的颜色空间转换
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/119589.html原文链接:https://javaforall.cn
全栈程序员站长
2022/07/09
5940
计算机视觉:2.6~4.5 颜色空间、数据结构与绘图
最常见的色彩空间就是RGB,人眼也是基于RGB的色彩空间去分辨颜色的。 OpenCV默认使用的是BGR。BGR和RGB色彩空间的区别在于图片在色彩通道上的排列顺序不同。
DioxideCN
2022/08/05
1.1K0
计算机视觉:2.6~4.5 颜色空间、数据结构与绘图
颜色空间
HSV(Hue, Saturation, Value)是根据颜色的直观特性由 A. R. Smith 在 1978 年创建的一种颜色空间, 也称六角锥体模型(Hexcone Model)。
为为为什么
2022/08/10
2.2K0
颜色空间
色彩知识
色深用 2 的幂指数来表示,bit 数愈高,色深值便愈高,影像所能表现的色彩也愈多。
Kiba518
2020/07/21
2.1K0
基于 OpenCV 与 Java 两个语言版本实现获取某一图片特定区域的颜色对比度
对比度是指图像中不同区域之间的明暗差异程度,它是图像质量中的重要指标之一。除了颜色对比度之外,常见的对比度包括:
程序员洲洲
2024/06/07
4590
基于 OpenCV 与 Java 两个语言版本实现获取某一图片特定区域的颜色对比度
opencv基础知识和绘图图形
淼学派对
2023/10/14
2590
opencv基础知识和绘图图形
之于图片主色调提取算法
算法的主要目的是从真彩色图像所能表现的大约16M中颜色中选取最代表性或者出现频率最高的256种颜色。
cpuimage
2018/05/10
6.3K5
VC++中使用OpenCV进行颜色检测
在VC++中使用OpenCV进行颜色检测非常简单,首选读取一张彩色图像,并调用函数cvtColor(img, imgHSV, COLOR_BGR2HSV);函数将原图img转换成HSV图像imgHSV,再设置好HSV三个分量的上限和下限值,调用inRange函数inRange(imgHSV, lower, upper, mask);将HSV色彩图像转换成掩码图,掩码图中只有黑白二值图像,从而达到颜色检测的目的。颜色检测通常可以用于物体检测和跟踪中,尤其在不同的图像和物体中根据特定的颜色去筛选出某个物体。
ccf19881030
2024/05/24
6200
VC++中使用OpenCV进行颜色检测
OCR笔记① | 环境配置与简单操作
各位朋友大家好,我是CPP课题组的视觉工程师。这个系列的文章主要介绍计算机视觉尤其是OCR在经济类课题数据采集中的应用以及其实现方法。既是小教程又是学习笔记。
量潮科技
2022/10/31
5550
彩色图像色彩空间原理
自然界的各种色彩、人类所感知的色彩以及各种图像设备和计算机软件所使用的颜色可通过色彩空间(Color Space)来描述。
不脱发的程序猿
2021/08/10
1.1K0
.NET 深度指南:Colors
我不知道你们是什么情况,但我自己在过去多年中都因为.NET 色彩(Colors)类中可用的色彩数量有限而头痛不已,为此我试图用 ColorPickers 获得匹配的色彩并努力去理解各种色彩模型。为了让我的生活轻松一些,我写了几个小方法可以把任何色彩改成黑白的,还有一个方法可以混合色彩。有了这些方法后,我得到了匹配度很高的色彩,有点像 GradientBrush 中的渐变效果。
深度学习与Python
2022/03/23
4930
.NET 深度指南:Colors
相关推荐
[UWP]使用Writeable​Bitmap创建HSV色轮
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验