python 实现图像快速替换某种颜色


Posted in Python onJune 04, 2020

最近的对图像数据进行处理的时候需要将图像中的某个颜色替换为另一个颜色,但是网络上找到的方法都是通过对图像的遍历进行替换,实在是太费时了!刚开始使用时觉得CPU很快了,一张图片应该用不了多久,但是实际使用中耗时确实难以接受的!于是自己写了一个替换程序加快速度,比遍历快很多,但我觉得不是最快的,应该有通过矩阵索引更快的处理方式,只是我自己暂时并不知道该如何实现,如果以后能够实现会进行更新,暂时先写下自己暂时觉得可用的代码。

一、通过遍历替换

将图像中某个颜色替换为另一个颜色一般的做法是遍历整个图像,逐一替换,如下:

def replace_color_tran(img, src_clr, dst_clr):
	''' 通过遍历颜色替换程序
	@param	img:	图像矩阵
	@param	src_clr:	需要替换的颜色(r,g,b)
	@param	dst_clr:	目标颜色		(r,g,b)
	@return				替换后的图像矩阵
	'''
	img_arr = np.asarray(img, dtype=np.double)
	
	dst_arr = img_arr.copy()
	for i in range(img_arr.shape[1]):	
		for j in range(img_arr.shape[0]):
			if (img_arr[j][i] == src_clr)[0] == True:
				dst_arr[j][i] = dst_clr
		
	return np.asarray(dst_arr, dtype=np.uint8)

二、通过矩阵操作加快替换

但是这样做,处理速度是很慢的即便是现在CPU很快的情况下。我自己通过numpy矩阵操作将速度提升了一点,具体做法如下:

将图像的三个通道拆分开来为R,G,B三个通道

将三个通道的数据值进行简单的编码,合并为单通道矩阵;

将需要替换的颜色进行同2的编码,利用改编码在2中得到的矩阵中得到对应颜色的索引;

利用3中得到的索引将R,G,B三个通道中的对应颜色值替换为目标值;

将得到的三个通道合并为一个图像数据。

具体实现如下:

def replace_color(img, src_clr, dst_clr):
	''' 通过矩阵操作颜色替换程序
	@param	img:	图像矩阵
	@param	src_clr:	需要替换的颜色(r,g,b)
	@param	dst_clr:	目标颜色		(r,g,b)
	@return				替换后的图像矩阵
	'''
  img_arr = np.asarray(img, dtype=np.double)
  
  r_img = img_arr[:,:,0].copy()
  g_img = img_arr[:,:,1].copy()
  b_img = img_arr[:,:,2].copy()

  img = r_img * 256 * 256 + g_img * 256 + b_img
  src_color = src_clr[0] * 256 * 256 + src_clr[1] * 256 + src_clr[2] #编码
  
  r_img[img == src_color] = dst_clr[0]
  g_img[img == src_color] = dst_clr[1]
  b_img[img == src_color] = dst_clr[2]
  
  dst_img = np.array([r_img, g_img, b_img], dtype=np.uint8)
  dst_img = dst_img.transpose(1,2,0)
  
  return dst_img

三、结果对比

先看下具体的实现结果,全部测试程序文末给出,(上面的图片是原图,下面是替换后的图片)。

python 实现图像快速替换某种颜色

python 实现图像快速替换某种颜色

python 实现图像快速替换某种颜色

四、程序解释

通过如下方式编码的原因是r,g,b三原色的数值本身是顺序相关的,为了保证最后索引的一致与准确性,采用将不同数值错位开。这里的magic number采用256是因为三原色的数值的范围是[0,255],这样相乘可以保证数据在二进制上的完全相互交错而保证该编码是绝对正确的,当然也可以采用其他形式的编码或者数值选择其他数值,我这样选择是为了保险起见而已。

img = r_img * 256 * 256 + g_img * 256 + b_img src_color = src_clr[0] * 256 * 256 + src_clr[1] * 256 + src_clr[2] #编码

五、完整的测试程序

完整的程序:

from PIL import Image
import os
import numpy as np
import time

def replace_color(img, src_clr, dst_clr):
	''' 通过矩阵操作颜色替换程序
	@param	img:	图像矩阵
	@param	src_clr:	需要替换的颜色(r,g,b)
	@param	dst_clr:	目标颜色		(r,g,b)
	@return				替换后的图像矩阵
	'''
  img_arr = np.asarray(img, dtype=np.double)
  
  #分离通道
  r_img = img_arr[:,:,0].copy()
  g_img = img_arr[:,:,1].copy()
  b_img = img_arr[:,:,2].copy()

	#编码
  img = r_img * 256 * 256 + g_img * 256 + b_img
  src_color = src_clr[0] * 256 * 256 + src_clr[1] * 256 + src_clr[2]
  
  #索引并替换颜色
  r_img[img == src_color] = dst_clr[0]
  g_img[img == src_color] = dst_clr[1]
  b_img[img == src_color] = dst_clr[2]
  
  #合并通道
  dst_img = np.array([r_img, g_img, b_img], dtype=np.uint8)
  #将数据转换为图像数据(h,w,c)
  dst_img = dst_img.transpose(1,2,0)
  
  return dst_img

def replace_color_tran(img, src_clr, dst_clr):
	''' 通过遍历颜色替换程序
	@param	img:	图像矩阵
	@param	src_clr:	需要替换的颜色(r,g,b)
	@param	dst_clr:	目标颜色		(r,g,b)
	@return				替换后的图像矩阵
	'''
	img_arr = np.asarray(img, dtype=np.double)
	
	dst_arr = img_arr.copy()
	for i in range(img_arr.shape[1]):	
		for j in range(img_arr.shape[0]):
			if (img_arr[j][i] == src_clr)[0] == True:
				dst_arr[j][i] = dst_clr
		
	return np.asarray(dst_arr, dtype=np.uint8)

img = '1.jpg'
img = Image.open(img).convert('RGB')
res_img = img.copy()
count = 20
matrix_time = 0
trans_time = 0

for i in range(count):
	print(i)
	start = time.time()
	dst_img = replace_color(img, (8,10,51), (255,0,0))
	end = time.time()
	matrix_time += (end - start)
	
	start = time.time()
	dst_img = replace_color_tran(img, (8,10,51), (255,0,0))
	end = time.time()
	trans_time += (end - start)
	
	res_img = dst_img
	
res_img = Image.fromarray(res_img)
res_img.save('2.jpg')

print('矩阵操作花费时间:', matrix_time / count )
print('遍历操作花费时间:', trans_time / count )

以上这篇python 实现图像快速替换某种颜色就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
基于scrapy实现的简单蜘蛛采集程序
Apr 17 Python
Python多进程同步简单实现代码
Apr 27 Python
python正则实现提取电话功能
Feb 24 Python
详谈套接字中SO_REUSEPORT和SO_REUSEADDR的区别
Apr 28 Python
PyQt打开保存对话框的方法和使用详解
Feb 27 Python
Python使用修饰器进行异常日志记录操作示例
Mar 19 Python
Python字符串的常见操作实例小结
Apr 08 Python
python画图——实现在图上标注上具体数值的方法
Jul 08 Python
python 字典的打印实现
Sep 26 Python
python爬虫爬取幽默笑话网站
Oct 24 Python
python 成功引入包但无法正常调用的解决
Mar 09 Python
Python matplotlib图例放在外侧保存时显示不完整问题解决
Jul 28 Python
python下对hsv颜色空间进行量化操作
Jun 04 #Python
Python-opencv实现红绿两色识别操作
Jun 04 #Python
Python基于pandas绘制散点图矩阵代码实例
Jun 04 #Python
Python使用plt.boxplot() 参数绘制箱线图
Jun 04 #Python
浅谈opencv自动光学检测、目标分割和检测(连通区域和findContours)
Jun 04 #Python
Python中操作各种多媒体,视频、音频到图片的代码详解
Jun 04 #Python
Python简单实现词云图代码及步骤解析
Jun 04 #Python
You might like
php sprintf()函数让你的sql操作更安全
2008/07/23 PHP
PHP执行zip与rar解压缩方法实现代码
2010/12/05 PHP
php设计模式 Bridge (桥接模式)
2011/06/26 PHP
Zend Framework中的简单工厂模式 图文
2012/07/10 PHP
PHP CURL CURLOPT参数说明(curl_setopt)
2013/09/30 PHP
PHP连接MYSQL数据库实例代码
2016/01/20 PHP
Yii2创建表单(ActiveForm)方法详解
2016/07/23 PHP
关于jquery的多个选择器的使用示例
2013/10/18 Javascript
获取当前点击按钮的id用this.id实现
2014/03/17 Javascript
JavaScript中this的9种应用场景及三种复合应用场景
2015/09/12 Javascript
ES6新特征数字、数组、字符串
2016/10/01 Javascript
Vue.js实战之组件之间的数据传递
2017/04/01 Javascript
Node.js 获取微信JS-SDK CONFIG的方法示例
2019/05/21 Javascript
JS 封装父页面子页面交互接口的实例代码
2019/06/25 Javascript
微信小程序8种数据通信的方式小结
2020/02/03 Javascript
vue 虚拟DOM的原理
2020/10/03 Javascript
Python实现读取目录所有文件的文件名并保存到txt文件代码
2014/11/22 Python
举例讲解Python中的死锁、可重入锁和互斥锁
2015/11/05 Python
Python 实现数据库更新脚本的生成方法
2017/07/09 Python
python3.5 cv2 获取视频特定帧生成jpg图片
2019/08/28 Python
Python paramiko模块使用解析(实现ssh)
2019/08/30 Python
Python实现Word文档转换Markdown的示例
2020/12/22 Python
浅谈CSS3动画的回调处理
2016/07/21 HTML / CSS
美国林业供应商:Forestry Suppliers
2019/05/01 全球购物
中科方德软件测试面试题
2016/04/21 面试题
师说教学反思
2014/02/07 职场文书
酒店端午节活动方案
2014/08/26 职场文书
基层党员学习党的群众路线教育实践活动心得体会
2014/11/04 职场文书
2014年园林绿化工作总结
2014/12/11 职场文书
2014高三学生考试作弊检讨书
2014/12/14 职场文书
二年级语文下册复习计划
2015/01/19 职场文书
详解Mysql 函数调用优化
2021/04/07 MySQL
SQL Server中使用判断语句(IF ELSE/CASE WHEN )案例
2021/07/07 SQL Server
python实现手机推送 代码也就10行左右
2022/04/12 Python
python的html标准库
2022/04/29 Python
输入框跟随文字内容适配宽实现示例
2022/08/14 Javascript