Numpy进阶(一) — 替换图片中的指定颜色!

简介: 提出需求做图像处理时,有时会遇到换色问题,就例如下面图片(网上找的小姐姐图片,侵删)的背景图并不喜欢,我想换成蓝色的要怎么做呢

提出需求


做图像处理时,有时会遇到换色问题,就例如下面图片(网上找的小姐姐图片,侵删)的背景图并不喜欢,我想换成蓝色的要怎么做呢微信图片_20220520112846.jpg这时候肯定会有小伙伴会想到PS,PS 工具当然是首选,但是如果有大量图片需要更换的时候 PS 显然并不是一个好方案,这时候可以借助 Python 来实现


原理讲解


在换色之前,需要了解一下图片成像编码知识,平常我们常用到的图片编码都为 RGB  格式,是由R、G、B 三通道所组的微信图片_20220520112848.jpg

每个通道的取值范围在 0-255 之间,而这三通道值的任意组合可以组成色板上的任意颜色,当R、G、B[0,0,0] 时是黑色,[255,255,255]  是是白色,一幅图像的呈像原理就是由不同像素值按一定的顺序排列也就是说  更换图像颜色的本质就是改变指定色素值即可这里多说一嘴,平常我们会遇到一些透明图片,透明的图片相对正常 RGB 图片多加了一个通道,多出来的通道取值范围也是在0-255之间用,于控制图像的透明程度 ;数值越大,越不透明;这种模式在 PIL 库中叫做 RGBA 格式


代码实操


下面进入代码部分,这里首先利用图像库要读取一幅图片(这里我用的是 PIL),把图像格式转化为数组类型,方便后面更改像素值

from PIL import Image

import numpy as np


img = Image.open('E:/23.png')

arr = np.asarray(img)


#打印数组的形状

print('数组的维度尺寸为:')

print(arr.shape)


print('\n')


print('打印像素值')

for i in arr:

   for j in i:        

       print(j)

从结果中,我们可以了解到图片的背景像素为 [255 255 255] ,我们知道背景像素值之后接下来就是把我们想要替换的像素值把它替换掉即可

微信图片_20220520112849.jpgSnipaste_2020-03-21_23-20-30.jpg替换过程中,先用最传统有效的递归方法,用两个 for 循环 对像素值做个判断,像素值如果是[255 255 255] 就进行更换,否则不做修改,这里用 [0 0 255] 蓝色作为更换背景,


start_time = time.time()

#对原数组进行copy,源于原数组不可更改;

arr1 =arr.copy()


for i in arr1:

   for j in i:

       if (j[0] ==255and j[1]==255and j[2]==255):

           #满足条件进行像素值更换

           j[0] = 0

           j[1] = 0

           j[2] = 255


print('迭代法更换用时{}s'.format(time.time()-start_time))

plt.imsave('E:/1235.png',arr1)

利用 for 循环进行逐像素修改也可以,但是因为是一个一个像素地修改因此会出现一个问题就是耗时 ,图像分辨率越大,这个劣势越明显,因为是数组修改因此我们可以利用 Numpy 来进行操作;借助 Numpy 先把三通道分离,然后相加得到一个新的数组,把需要更改的 R、G、B三通道值也相加起来得到一个特征值,利用 Numpy  数组的布尔值与特征值之间的条件筛选 对数组中的值进行更新(通道相加和等于特征值就替换,否则Pass ),完整代码如下:

#需要更换的像素值

scr_img = [255,255,255]


#新的像素值

new_img = [0,0,255]


start_time = time.time()

#三通道分离

r_img,g_img,b_img = arr[:,:,0].copy(),arr[:,:,1].copy(),arr[:,:,2].copy()


#三通道值相加形式变成单通道,组合在一起,进行编码

img = r_img +  g_img + b_img

value_const = scr_img[0] + scr_img[1] + scr_img[2]


#符合条件进行更改像素值

r_img[img == value_const] = new_img[0]

g_img[img == value_const] = new_img[1]

b_img[img == value_const] = new_img[2]


#numpy三通道合并

arr1 = np.dstack([r_img,g_img,b_img])


print('通道法用时时间:{}'.format(time.time()-start_time))


plt.imsave('E:/2315.png',arr1)

最后我们可以看一下结果,因为找的图片中,小姐姐头像周围像素并不全是 [255 255 255](纯白),所以替换出来的图片会出现瑕疵,但总体效果还是比较不错的微信图片_20220520112851.jpg

之所以引出第二种方法,是得益于 Numpy 数组操作的高性能运算,这里列出了两种方法在运行时所耗时间,Numpy 通道法不足 0.08s,而迭代法长达 1.3s ,相对来说还是通道法性能更好一点微信图片_20220520112853.jpg微信图片_20220520112855.jpg

相关文章
|
存储 数据可视化 数据挖掘
【数据分析入门】Numpy进阶
【数据分析入门】Numpy进阶
|
4月前
|
数据处理 Python
数据科学进阶之路:Pandas与NumPy高级操作详解与实战演练
【7月更文挑战第13天】探索数据科学:Pandas与NumPy提升效率的高级技巧** - Pandas的`query`, `loc`和`groupby`用于复杂筛选和分组聚合,例如筛选2023年销售额超1000的记录并按类别计总销售额。 - NumPy的广播和向量化运算加速大规模数据处理,如快速计算两个大数组的元素级乘积。 - Pandas DataFrame基于NumPy,二者协同加速数据处理,如将DataFrame列转换为NumPy数组进行标准化再回写,避免链式赋值。 掌握这些高级操作,实现数据科学项目的效率飞跃。
59 0
|
6月前
|
数据处理 C语言 索引
使用NumPy进行科学计算:基础与进阶
【4月更文挑战第9天】NumPy是数据处理和科学计算的核心工具,提供高性能的多维数组对象和数学函数库。本文深入讲解NumPy的基础和进阶技巧,包括ndarray的向量化操作、广播机制、ufunc、高级索引以及线性代数操作。通过示例展示如何利用NumPy进行高效计算,强调性能优化,帮助读者提升科学计算能力。
55 6
|
机器学习/深度学习 存储 数据挖掘
【100天精通Python】Day53:Python 数据分析_NumPy数据操作和分析进阶
【100天精通Python】Day53:Python 数据分析_NumPy数据操作和分析进阶
88 0
|
算法 计算机视觉 索引
【菜菜的CV进阶之路-基础库的使用-Numpy】按指定条件筛选numpy ndarray数据并进行操作
【菜菜的CV进阶之路-基础库的使用-Numpy】按指定条件筛选numpy ndarray数据并进行操作
194 0
|
计算机视觉 Python
Numpy 进阶(二) — 对图像进行旋转、水平、垂直镜像操作!
原理讲解 用 Python 对图片做旋转、镜像操作时,小伙伴们可能首先想到的是 PIL 、Opencv 等图像处理程序包,只需要一行代码就可以实现目标转换。 这样做的确能够实预期目标,但图像是怎么实现旋转的,这个过程对我们来说就像一个黑盒子,很陌生,为了了解图像变换机制,这篇文章借助 Numpy 数组来实现图像翻转等操作
Numpy 进阶(二) — 对图像进行旋转、水平、垂直镜像操作!
|
Python
NumPy快餐教程(2) - 多维数组进阶
上一讲我们介绍了ndarray的形状变化和生成方法,这一节我们继续讨论多维数组的使用方法。
7177 0
|
机器学习/深度学习 Python
Numpy处理图片方法
Numpy处理图片方法
844 0
|
JSON 数据格式 计算机视觉
用 opencv和numpy进行图片和字符串互转,并保存至 json
用 opencv和numpy进行图片和字符串互转,并保存至 json 转至 https://zhuanlan.zhihu.com/p/27349847 受 用 base64 进行图片和字符串互转,并保存至 json 作者启发,试了试使用opencv来读取图片,然后用numpy转为list,再转为json格式。
1742 0
|
2月前
|
机器学习/深度学习 数据处理 Python
从NumPy到Pandas:轻松转换Python数值库与数据处理利器
从NumPy到Pandas:轻松转换Python数值库与数据处理利器
75 0