利用python在excel中畫圖的實現(xiàn)方法
一、前言
以前大學(xué)時候,學(xué)EXCEL看到N多大神利用excel畫圖,覺得很不可思議。今個學(xué)了一個來月python,膨脹了就想用excel畫圖。當然,其實用畫圖這個詞不甚嚴謹,實際上是利用opencv遍歷每一個像素的rgb值,再將其轉(zhuǎn)化為16進制,最后調(diào)用openpyxl進行填充即可。
1.1、實現(xiàn)效果
效果如下圖
1.2、需要用到的庫的安裝
需要用到庫如下:
import cv2 #導(dǎo)入OpenCV庫 import xlsxwriter #利用這個調(diào)整行高列寬 import openpyxl #利用這個填充顏色 import numpy as np #下面這兩個是數(shù)據(jù)存儲的兩種方式,用此種方式處理數(shù)據(jù),比列表高效,具體可自行查看文檔 import pandas as pd
除了第一個庫其他的可以直接用pip在命令提示行進行安裝,或者利用編輯器的一些自動安裝功能也非常的方便,具體的請參看這篇文章 的第三節(jié): 三、開始安裝
第一個庫如果你直接用pip3 install opencv-python 進行安裝的話,無論你網(wǎng)速多么快,都會非常慢幾k/s,如下:
如果能安裝好還行,關(guān)鍵有的可能等上幾分鐘也不行,直接出現(xiàn)幾十行的紅色字看的頭疼。幾經(jīng)百度后才知道是安裝源的問題,切換為國內(nèi)的安裝源即可,利用如下命令,
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
如下圖,我準備截取安裝速度和上面的作對比的,結(jié)果直接安裝好了
二、代碼分開講解
本文我們利用面相對象的編程思維進行。
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
這兩個變量是你的圖像儲存路徑和后續(xù)的excel文件保存位置。
第三行self.imgviewx=cv2.imread(image_path,cv2.IMREAD_COLOR)
意思是調(diào)用opencv的imread讀取圖片。其中第一個參數(shù)就是對象實例化時候傳遞進來的圖像儲存路徑。該函數(shù)返回的是一個三維數(shù)組,分別表示x,y,rgb 就是x,y坐標對應(yīng)的rgb值,其中x,y單位為1像素。最后將這個三維數(shù)組傳遞給對象的一個屬性imgviewx,等待后續(xù)對象方法調(diào)用。我們將之打印出來如下。
第四行<<self.excel_path=excel_path
>>是將對象實例化時候傳遞進來的excel_path傳遞給對象的屬性excel_path,同樣等待后續(xù)對象的方法調(diào)用。
2.2、對象的方法
1:行高列寬調(diào)整,以防止圖像變形
#excel行高列寬調(diào)整 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()
這個其實你可以后續(xù)在excel中調(diào)整也可以。
第二行第三行基本一看就懂,就是在你剛開始對象實例化時候傳入的一個路徑中創(chuàng)建一個工作簿并添加一個名為test的工作表。
第三行意思是將A列到CAA列的列寬設(shè)置為1(注意:這里面設(shè)置為1不知道為什么在工作表中就是0.94,列寬同樣小點)
第四行意思同樣,不過行高不能批量只能通過循環(huán)。
最后一樣看著像關(guān)閉,其實最主要功能是保存,沒有這一行,前面的所有設(shè)置都不會被保存。
2.3、對象的方法2:10進制轉(zhuǎn)化為16進制
#10進制轉(zhuǎn)化為16進制 def ten2_16(self,num): num1 = hex(num).replace('0x', '') return num1 if len(num1) > 1 else '0' + num1
這個方法不用細說,就是利用系統(tǒng)自帶的函數(shù)hex將10進制轉(zhuǎn)化為16進制。我們都知道hex返回的16進制是以0x開頭的,而16進制顏色碼中明顯沒有,所以要用replace去掉。
如果rgb值是16以內(nèi)的,以16進制顯示的話會是1位數(shù),而同樣這個在16進制顏色碼中也沒有,所以最后一行的意思就是一位數(shù)的話在開頭補0。
2.4、對象的方法3:獲取r、g、b值并運用方法1轉(zhuǎn)化為16進制顏色碼
#獲取像素數(shù)據(jù)并轉(zhuǎn)化為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()
>>是在本方法本調(diào)用時候先調(diào)用方法1調(diào)整行高列寬。我們后面說,這關(guān)系到對象方法之間的參數(shù)傳遞,我們后續(xù)說。
三四五行的代碼結(jié)構(gòu)一樣,我們挑一個說。比如第三行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值的三維列表轉(zhuǎn)化為數(shù)組并提取其中的r。
第二行是將第一行得到的數(shù)組轉(zhuǎn)化為DataFrame對象并存儲在tmp變量中,以便第三行的處理。
第三行是利用DataFrame中的applymap將r值轉(zhuǎn)化為16進制。
最后一行<<return (data_r+data_g+data_b).values
>>意思是將轉(zhuǎn)化為16進制的rgb值合并后就得到了16進制的顏色碼并轉(zhuǎn)化為數(shù)組。
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中調(diào)用方法1時候用的。
這里就是在本方法也就是方法3中調(diào)用方法2。唯一的區(qū)別就是有沒有返回值。
我們這樣在方法3中調(diào)用方法2然后方法2中調(diào)用方法1。這樣在對象外的時候我們就只用對象實例化并調(diào)用方法3即可實現(xiàn)功能。
第三行、第四行就是調(diào)用openpyxl.load_workbook打開我們在方法1中新建的工作簿中的test工作表
五到七行兩個循環(huán)嵌套很容易懂就是利用循環(huán)遍歷每個工作表
第八行的代碼可能可以簡化 ,這個是我修改網(wǎng)上的一個填充漸變色的代碼。
最后一行就是工作表的保存,沒什么可說的。
三、完整代碼
import cv2 #導(dǎo)入OpenCV庫 import xlsxwriter #利用這個調(diào)整行高列寬 import openpyxl #利用這個填充顏色 import numpy as np #下面這兩個是數(shù)據(jù)存儲的兩種方式,用此種方式處理數(shù)據(jù),比列表高效 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行高列寬調(diào)整 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轉(zhuǎn)16進制顏色碼 def ten2_16(self,num): tmp = hex(num).replace('0x', '') return tmp if len(tmp) > 1 else '0' + tmp #獲取像素數(shù)據(jù)并轉(zhuǎn)化為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文件放在一起的,不然運行會報錯。
四、結(jié)語
好啦,到此所有東西已全部搞定,當然還有很多要注意的,
第一、方法3中紅綠藍的提取中這部分的編號是剛好相反的,提取時候需要注意
如下
當然你也可以嘗試改變這個值看最后會得到什么結(jié)果。藍色的太陽 紅色的天空 或者是綠色的帽子,哈哈 好吧這個就你們自己發(fā)揮了。
第二、除了以上一點需要注意的,還有一個需要注意,就是像素不能太高。我測試了下342*218的話我的i7-6700u打開excel就不是很流暢了。
你可以遍歷的時候以2個像素點或者四個像素點為步長,不過這樣我沒試過,可能顆粒感比較明顯吧(自己猜測沒試過),或者把原始圖片修改下。
到此這篇關(guān)于利用python在excel中畫圖的實現(xiàn)方法的文章就介紹到這了,更多相關(guān)python excel畫圖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python導(dǎo)入數(shù)值型Excel數(shù)據(jù)并生成矩陣操作
- Python pandas如何向excel添加數(shù)據(jù)
- Python使用Excel將數(shù)據(jù)寫入多個sheet
- 解決python執(zhí)行較大excel文件openpyxl慢問題
- 基于python實現(xiàn)把json數(shù)據(jù)轉(zhuǎn)換成Excel表格
- Python讀取excel文件中帶公式的值的實現(xiàn)
- Python3使用xlrd、xlwt處理Excel方法數(shù)據(jù)
- python2 對excel表格操作完整示例
- Python Excel vlookup函數(shù)實現(xiàn)過程解析
相關(guān)文章
Python中json.dumps()函數(shù)的使用解析
json.dumps將一個Python數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換為JSON,本文介紹了Python中json.dumps()函數(shù)的具體使用方法,以及和dump的區(qū)別,感興趣的可以了解一下2021-05-05Python機器學(xué)習(xí)NLP自然語言處理基本操作家暴歸類
本文是Python機器學(xué)習(xí)NLP自然語言處理系列文章,帶大家開啟一段學(xué)習(xí)自然語言處理 (NLP) 的旅程。本篇文章主要學(xué)習(xí)NLP自然語言處理家暴歸類2021-09-09python修改字典內(nèi)key對應(yīng)值的方法
這篇文章主要介紹了python修改字典內(nèi)key對應(yīng)值的方法,涉及Python中字典賦值的相關(guān)實現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-07-07python基礎(chǔ)學(xué)習(xí)之如何對元組各個元素進行命名詳解
python的元祖和列表類似,不同之處在于元祖的元素不能修改,下面這篇文章主要給大家介紹了關(guān)于python基礎(chǔ)學(xué)習(xí)之如何對元組各個元素進行命名的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下2018-07-07