利用python在excel中画图的实现方法


Posted in Python onMarch 17, 2020

一、前言

以前大学时候,学EXCEL看到N多大神利用excel画图,觉得很不可思议。今个学了一个来月python,膨胀了就想用excel画图。当然,其实用画图这个词不甚严谨,实际上是利用opencv遍历每一个像素的rgb值,再将其转化为16进制,最后调用openpyxl进行填充即可。

1.1、实现效果

效果如下图

利用python在excel中画图的实现方法

1.2、需要用到的库的安装

需要用到库如下:

import cv2   #导入OpenCV库
import xlsxwriter #利用这个调整行高列宽
import openpyxl  #利用这个填充颜色
import numpy as np #下面这两个是数据存储的两种方式,用此种方式处理数据,比列表高效,具体可自行查看文档
import pandas as pd

除了第一个库其他的可以直接用pip在命令提示行进行安装,或者利用编辑器的一些自动安装功能也非常的方便,具体的请参看这篇文章 的第三节: 三、开始安装

第一个库如果你直接用pip3 install opencv-python 进行安装的话,无论你网速多么快,都会非常慢几k/s,如下:

利用python在excel中画图的实现方法

如果能安装好还行,关键有的可能等上几分钟也不行,直接出现几十行的红色字看的头疼。几经百度后才知道是安装源的问题,切换为国内的安装源即可,利用如下命令,

pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python

如下图,我准备截取安装速度和上面的作对比的,结果直接安装好了

利用python在excel中画图的实现方法

二、代码分开讲解

本文我们利用面相对象的编程思维进行。

2.1、对象的定义以及初始化

class ImageToExcel():
 def __init__(self,image_path,excel_path):
  self.imgviewx=cv2.imread(image_path,cv2.IMREAD_COLOR)
  self.excel_path=excel_path

前面两行很好理解就是定义对象的格式以及初始化对象

其中image_path和excel_path这两个变量是你的图像储存路径和后续的excel文件保存位置。

第三行self.imgviewx=cv2.imread(image_path,cv2.IMREAD_COLOR)意思是调用opencv的imread读取图片。其中第一个参数就是对象实例化时候传递进来的图像储存路径。该函数返回的是一个三维数组,分别表示x,y,rgb 就是x,y坐标对应的rgb值,其中x,y单位为1像素。最后将这个三维数组传递给对象的一个属性imgviewx,等待后续对象方法调用。我们将之打印出来如下。

利用python在excel中画图的实现方法

第四行<<self.excel_path=excel_path>>是将对象实例化时候传递进来的excel_path传递给对象的属性excel_path,同样等待后续对象的方法调用。

2.2、对象的方法

1:行高列宽调整,以防止图像变形

#excel行高列宽调整
 def excel_size(self):
  workbook = xlsxwriter.Workbook(self.excel_path)
  worksheet = workbook.add_worksheet('test')
  worksheet.set_column('A:CAA', 1)
  for x in range(2000):worksheet.set_row(x, 8.4)
  workbook.close()

这个其实你可以后续在excel中调整也可以。
第二行第三行基本一看就懂,就是在你刚开始对象实例化时候传入的一个路径中创建一个工作簿并添加一个名为test的工作表。
第三行意思是将A列到CAA列的列宽设置为1(注意:这里面设置为1不知道为什么在工作表中就是0.94,列宽同样小点
第四行意思同样,不过行高不能批量只能通过循环。
最后一样看着像关闭,其实最主要功能是保存,没有这一行,前面的所有设置都不会被保存。

2.3、对象的方法2:10进制转化为16进制

#10进制转化为16进制
 def ten2_16(self,num):
  num1 = hex(num).replace('0x', '')
  return num1 if len(num1) > 1 else '0' + num1

这个方法不用细说,就是利用系统自带的函数hex将10进制转化为16进制。我们都知道hex返回的16进制是以0x开头的,而16进制颜色码中明显没有,所以要用replace去掉。
如果rgb值是16以内的,以16进制显示的话会是1位数,而同样这个在16进制颜色码中也没有,所以最后一行的意思就是一位数的话在开头补0。

2.4、对象的方法3:获取r、g、b值并运用方法1转化为16进制颜色码

#获取像素数据并转化为16进制
 def get_rgb_data(self):
  self.excel_size()
  data_r=pd.DataFrame( np.array(self.imgviewx)[:,:,2] ).applymap(self.ten2_16)
  data_g=pd.DataFrame( np.array(self.imgviewx)[:,:,1] ).applymap(self.ten2_16)
  data_b=pd.DataFrame( np.array(self.imgviewx)[:,:,0] ).applymap(self.ten2_16)
  return (data_r+data_g+data_b).values

其中第二行<<self.excel_size() >>是在本方法本调用时候先调用方法1调整行高列宽。我们后面说,这关系到对象方法之间的参数传递,我们后续说。
三四五行的代码结构一样,我们挑一个说。比如第三行data_r=pd.DataFrame( np.array(self.imgviewx)[:,:,2] ).applymap(self.ten2_16)这个代码我们可以拆开成下面的代码

r=np.array(self.imgviewx)[:,:,2]
tmp=pd.DataFrame( r )
data_r=tmp.applymap(self.ten2_16)

这下就容易懂了
第一行意思是将刚开始对象初始化时候得到的包含目标图片的所有像素点的rgb值的三维列表转化为数组并提取其中的r。
第二行是将第一行得到的数组转化为DataFrame对象并存储在tmp变量中,以便第三行的处理。
第三行是利用DataFrame中的applymap将r值转化为16进制。

最后一行<<return (data_r+data_g+data_b).values>>意思是将转化为16进制的rgb值合并后就得到了16进制的颜色码并转化为数组。

2.5、对象的方法4;颜色填充

def color_fill(self):
  rgb_list=self.get_rgb_data()
  wb = openpyxl.load_workbook(self.excel_path)
  ws = wb['test']
  for x,tmp1 in list(enumerate(rgb_list)):
   print('总共有%s行,已填充%s行,还剩下%s行'%(len(rgb_list),x+1,len(rgb_list)-x-1))
   for y ,tmp2 in list(enumerate(tmp1)):
    ws.cell(x+1,y+1).fill = openpyxl.styles.fills.GradientFill(stop=[str(tmp2),str(tmp2)])
  wb.save(self.excel_path)

第二行<<rgb_list=self.get_rgb_data()>>是不是似曾相识,对,就是在方法2中调用方法1时候用的。
这里就是在本方法也就是方法3中调用方法2。唯一的区别就是有没有返回值。
我们这样在方法3中调用方法2然后方法2中调用方法1。这样在对象外的时候我们就只用对象实例化并调用方法3即可实现功能。
第三行、第四行就是调用openpyxl.load_workbook打开我们在方法1中新建的工作簿中的test工作表
五到七行两个循环嵌套很容易懂就是利用循环遍历每个工作表
第八行的代码可能可以简化 ,这个是我修改网上的一个填充渐变色的代码。
最后一行就是工作表的保存,没什么可说的。

三、完整代码

import cv2   #导入OpenCV库
import xlsxwriter #利用这个调整行高列宽
import openpyxl  #利用这个填充颜色
import numpy as np #下面这两个是数据存储的两种方式,用此种方式处理数据,比列表高效
import pandas as pd

class ImageToExcel():
 #初始化
 def __init__(self,image_path,excel_path):
  self.imgviewx=cv2.imread(image_path,cv2.IMREAD_COLOR)
  self.excel_path=excel_path
 # excel行高列宽调整
 def excel_size(self):
  workbook = xlsxwriter.Workbook(self.excel_path)
  worksheet = workbook.add_worksheet('test')
  worksheet.set_column('A:CAA', 1)
  for x in range(2000): worksheet.set_row(x, 8.4)
  workbook.close()
 #rgb转16进制颜色码
 def ten2_16(self,num):
  tmp = hex(num).replace('0x', '')
  return tmp if len(tmp) > 1 else '0' + tmp
 #获取像素数据并转化为16进制
 def get_rgb_data(self):
  self.excel_size()
  data_r=pd.DataFrame( np.array(self.imgviewx)[:,:,2] ).applymap(self.ten2_16)
  data_g=pd.DataFrame( np.array(self.imgviewx)[:,:,1] ).applymap(self.ten2_16)
  data_b=pd.DataFrame( np.array(self.imgviewx)[:,:,0] ).applymap(self.ten2_16)
  return (data_r+data_g+data_b).values
 #颜色填充
 def color_fill(self):
  rgb_list=self.get_rgb_data()
  wb = openpyxl.load_workbook(self.excel_path)
  ws = wb['test']
  for x,tmp1 in list(enumerate(rgb_list)):
   print('总共有%s行,已填充%s行,还剩下%s行'%(len(rgb_list),x+1,len(rgb_list)-x-1))
   for y ,tmp2 in list(enumerate(tmp1)):
    ws.cell(x+1,y+1).fill = openpyxl.styles.fills.GradientFill(stop=[str(tmp2),str(tmp2)])
  wb.save(self.excel_path)
excel_path='test23.xlsx'
image_path='tttt.png'
image=ImageToExcel(image_path,excel_path)
image.color_fill()

最后四行前两行可以直接写在第三行中,就是对象的实例化中
另外还有一点,image_path中的 tttt.jpg是直接和我的py文件放在一起的,不然运行会报错。

四、结语

好啦,到此所有东西已全部搞定,当然还有很多要注意的,
第一、方法3中红绿蓝的提取中这部分的编号是刚好相反的,提取时候需要注意
如下

利用python在excel中画图的实现方法

当然你也可以尝试改变这个值看最后会得到什么结果。蓝色的太阳 红色的天空 或者是绿色的帽子,哈哈 好吧这个就你们自己发挥了。
第二、除了以上一点需要注意的,还有一个需要注意,就是像素不能太高。我测试了下342*218的话我的i7-6700u打开excel就不是很流畅了。
你可以遍历的时候以2个像素点或者四个像素点为步长,不过这样我没试过,可能颗粒感比较明显吧(自己猜测没试过),或者把原始图片修改下。

到此这篇关于利用python在excel中画图的实现方法的文章就介绍到这了,更多相关python excel画图内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
一个基于flask的web应用诞生 组织结构调整(7)
Apr 11 Python
利用Django内置的认证视图实现用户密码重置功能详解
Nov 24 Python
Python实现的自定义多线程多进程类示例
Mar 23 Python
Python列表解析配合if else的方法
Jun 23 Python
Python爬虫爬取新浪微博内容示例【基于代理IP】
Aug 03 Python
详解Django中CBV(Class Base Views)模型源码分析
Feb 25 Python
torch 中各种图像格式转换的实现方法
Dec 26 Python
Python基础之字符串操作常用函数集合
Feb 09 Python
python实现三种随机请求头方式
Jan 05 Python
发工资啦!教你用Python实现邮箱自动群发工资条
May 10 Python
如何使用Python提取Chrome浏览器保存的密码
Jun 09 Python
浅谈Python从全局与局部变量到装饰器的相关知识
Jun 21 Python
Python reversed函数及使用方法解析
Mar 17 #Python
使用python自动追踪你的快递(物流推送邮箱)
Mar 17 #Python
windows、linux下打包Python3程序详细方法
Mar 17 #Python
Python任务自动化工具tox使用教程
Mar 17 #Python
vue常用指令代码实例总结
Mar 16 #Python
django-利用session机制实现唯一登录的例子
Mar 16 #Python
python安装dlib库报错问题及解决方法
Mar 16 #Python
You might like
php获取客户端电脑屏幕参数的方法
2015/01/09 PHP
PHP中的闭包(匿名函数)浅析
2015/02/07 PHP
解读PHP的Yii框架中请求与响应的处理流程
2016/03/17 PHP
Laravel 自定命令以及生成文件的例子
2019/10/23 PHP
JavaScript的Polymer框架中dom-repeat与VM的相关操作
2015/07/29 Javascript
jQuery实现的自动加载页面功能示例
2016/09/04 Javascript
javascript实现简单的可随机变色网页计算器示例
2016/12/30 Javascript
jQuery实现动态文字搜索功能
2017/01/05 Javascript
基于jQuery实现的打字机效果
2017/01/16 Javascript
JS拉起或下载app的实现代码
2017/02/22 Javascript
vue中v-for循环给标签属性赋值的方法
2018/10/18 Javascript
简单了解TypeScript中如何继承 Error 类
2019/06/21 Javascript
vue使用openlayers实现移动点动画
2020/09/24 Javascript
[03:21]辉夜杯主赛事 12月25日TOP5
2015/12/26 DOTA
使用tensorflow实现AlexNet
2017/11/20 Python
使用python和pygame绘制繁花曲线的方法
2018/02/24 Python
python之DataFrame实现excel合并单元格
2021/02/22 Python
Django组件content-type使用方法详解
2019/07/19 Python
python2 中 unicode 和 str 之间的转换及与python3 str 的区别
2019/07/25 Python
python2和python3实现在图片上加汉字的方法
2019/08/22 Python
python中利用numpy.array()实现俩个数值列表的对应相加方法
2019/08/26 Python
python字典setdefault方法和get方法使用实例
2019/12/25 Python
Python使用进程Process模块管理资源
2020/03/05 Python
基于plt.title无法显示中文的快速解决
2020/05/16 Python
Django前后端分离csrf token获取方式
2020/12/25 Python
HTML5中外部浏览器唤起微信分享
2020/01/02 HTML / CSS
房地产开发计划书
2014/01/10 职场文书
优秀导游先进事迹材料
2014/01/25 职场文书
电厂职工自我鉴定
2014/02/20 职场文书
班子群众路线教育实践个人对照检查材料思想汇报
2014/09/30 职场文书
2015年质检工作总结
2015/05/04 职场文书
茶花女读书笔记
2015/06/29 职场文书
幼儿园语言教学反思
2016/02/23 职场文书
Vue Element-ui表单校验规则实现
2021/07/09 Vue.js
关于redisson缓存序列化几枚大坑说明
2021/08/04 Redis
对讲机知识
2022/04/07 无线电