利用python在excel中畫圖的實(shí)現(xiàn)方法
一、前言
以前大學(xué)時(shí)候,學(xué)EXCEL看到N多大神利用excel畫圖,覺(jué)得很不可思議。今個(gè)學(xué)了一個(gè)來(lái)月python,膨脹了就想用excel畫圖。當(dāng)然,其實(shí)用畫圖這個(gè)詞不甚嚴(yán)謹(jǐn),實(shí)際上是利用opencv遍歷每一個(gè)像素的rgb值,再將其轉(zhuǎn)化為16進(jìn)制,最后調(diào)用openpyxl進(jìn)行填充即可。
1.1、實(shí)現(xiàn)效果
效果如下圖
1.2、需要用到的庫(kù)的安裝
需要用到庫(kù)如下:
import cv2 #導(dǎo)入OpenCV庫(kù)import xlsxwriter #利用這個(gè)調(diào)整行高列寬import openpyxl #利用這個(gè)填充顏色import numpy as np #下面這兩個(gè)是數(shù)據(jù)存儲(chǔ)的兩種方式,用此種方式處理數(shù)據(jù),比列表高效,具體可自行查看文檔import pandas as pd
除了第一個(gè)庫(kù)其他的可以直接用pip在命令提示行進(jìn)行安裝,或者利用編輯器的一些自動(dòng)安裝功能也非常的方便,具體的請(qǐng)參看這篇文章 的第三節(jié): 三、開始安裝
第一個(gè)庫(kù)如果你直接用pip3 install opencv-python 進(jìn)行安裝的話,無(wú)論你網(wǎng)速多么快,都會(huì)非常慢幾k/s,如下:
如果能安裝好還行,關(guān)鍵有的可能等上幾分鐘也不行,直接出現(xiàn)幾十行的紅色字看的頭疼。幾經(jīng)百度后才知道是安裝源的問(wèn)題,切換為國(guó)內(nèi)的安裝源即可,利用如下命令,
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
如下圖,我準(zhǔn)備截取安裝速度和上面的作對(duì)比的,結(jié)果直接安裝好了
二、代碼分開講解
本文我們利用面相對(duì)象的編程思維進(jìn)行。
2.1、對(duì)象的定義以及初始化
class ImageToExcel(): def __init__(self,image_path,excel_path): self.imgviewx=cv2.imread(image_path,cv2.IMREAD_COLOR) self.excel_path=excel_path
前面兩行很好理解就是定義對(duì)象的格式以及初始化對(duì)象
其中image_path和excel_path這兩個(gè)變量是你的圖像儲(chǔ)存路徑和后續(xù)的excel文件保存位置。
第三行self.imgviewx=cv2.imread(image_path,cv2.IMREAD_COLOR)意思是調(diào)用opencv的imread讀取圖片。其中第一個(gè)參數(shù)就是對(duì)象實(shí)例化時(shí)候傳遞進(jìn)來(lái)的圖像儲(chǔ)存路徑。該函數(shù)返回的是一個(gè)三維數(shù)組,分別表示x,y,rgb 就是x,y坐標(biāo)對(duì)應(yīng)的rgb值,其中x,y單位為1像素。最后將這個(gè)三維數(shù)組傳遞給對(duì)象的一個(gè)屬性imgviewx,等待后續(xù)對(duì)象方法調(diào)用。我們將之打印出來(lái)如下。
第四行<<self.excel_path=excel_path>>是將對(duì)象實(shí)例化時(shí)候傳遞進(jìn)來(lái)的excel_path傳遞給對(duì)象的屬性excel_path,同樣等待后續(xù)對(duì)象的方法調(diào)用。
2.2、對(duì)象的方法
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()
這個(gè)其實(shí)你可以后續(xù)在excel中調(diào)整也可以。第二行第三行基本一看就懂,就是在你剛開始對(duì)象實(shí)例化時(shí)候傳入的一個(gè)路徑中創(chuàng)建一個(gè)工作簿并添加一個(gè)名為test的工作表。第三行意思是將A列到CAA列的列寬設(shè)置為1(注意:這里面設(shè)置為1不知道為什么在工作表中就是0.94,列寬同樣小點(diǎn))第四行意思同樣,不過(guò)行高不能批量只能通過(guò)循環(huán)。最后一樣看著像關(guān)閉,其實(shí)最主要功能是保存,沒(méi)有這一行,前面的所有設(shè)置都不會(huì)被保存。
2.3、對(duì)象的方法2:10進(jìn)制轉(zhuǎn)化為16進(jìn)制
#10進(jìn)制轉(zhuǎn)化為16進(jìn)制 def ten2_16(self,num): num1 = hex(num).replace(’0x’, ’’) return num1 if len(num1) > 1 else ’0’ + num1
這個(gè)方法不用細(xì)說(shuō),就是利用系統(tǒng)自帶的函數(shù)hex將10進(jìn)制轉(zhuǎn)化為16進(jìn)制。我們都知道hex返回的16進(jìn)制是以0x開頭的,而16進(jìn)制顏色碼中明顯沒(méi)有,所以要用replace去掉。如果rgb值是16以內(nèi)的,以16進(jìn)制顯示的話會(huì)是1位數(shù),而同樣這個(gè)在16進(jìn)制顏色碼中也沒(méi)有,所以最后一行的意思就是一位數(shù)的話在開頭補(bǔ)0。
2.4、對(duì)象的方法3:獲取r、g、b值并運(yùn)用方法1轉(zhuǎn)化為16進(jìn)制顏色碼
#獲取像素?cái)?shù)據(jù)并轉(zhuǎn)化為16進(jìn)制 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)用時(shí)候先調(diào)用方法1調(diào)整行高列寬。我們后面說(shuō),這關(guān)系到對(duì)象方法之間的參數(shù)傳遞,我們后續(xù)說(shuō)。三四五行的代碼結(jié)構(gòu)一樣,我們挑一個(gè)說(shuō)。比如第三行data_r=pd.DataFrame( np.array(self.imgviewx)[:,:,2] ).applymap(self.ten2_16)這個(gè)代碼我們可以拆開成下面的代碼
r=np.array(self.imgviewx)[:,:,2]tmp=pd.DataFrame( r )data_r=tmp.applymap(self.ten2_16)
這下就容易懂了第一行意思是將剛開始對(duì)象初始化時(shí)候得到的包含目標(biāo)圖片的所有像素點(diǎn)的rgb值的三維列表轉(zhuǎn)化為數(shù)組并提取其中的r。第二行是將第一行得到的數(shù)組轉(zhuǎn)化為DataFrame對(duì)象并存儲(chǔ)在tmp變量中,以便第三行的處理。第三行是利用DataFrame中的applymap將r值轉(zhuǎn)化為16進(jìn)制。
最后一行<<return (data_r+data_g+data_b).values>>意思是將轉(zhuǎn)化為16進(jìn)制的rgb值合并后就得到了16進(jìn)制的顏色碼并轉(zhuǎn)化為數(shù)組。
2.5、對(duì)象的方法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()>>是不是似曾相識(shí),對(duì),就是在方法2中調(diào)用方法1時(shí)候用的。這里就是在本方法也就是方法3中調(diào)用方法2。唯一的區(qū)別就是有沒(méi)有返回值。我們這樣在方法3中調(diào)用方法2然后方法2中調(diào)用方法1。這樣在對(duì)象外的時(shí)候我們就只用對(duì)象實(shí)例化并調(diào)用方法3即可實(shí)現(xiàn)功能。第三行、第四行就是調(diào)用openpyxl.load_workbook打開我們?cè)诜椒?中新建的工作簿中的test工作表五到七行兩個(gè)循環(huán)嵌套很容易懂就是利用循環(huán)遍歷每個(gè)工作表第八行的代碼可能可以簡(jiǎn)化 ,這個(gè)是我修改網(wǎng)上的一個(gè)填充漸變色的代碼。最后一行就是工作表的保存,沒(méi)什么可說(shuō)的。
三、完整代碼
import cv2 #導(dǎo)入OpenCV庫(kù)import xlsxwriter #利用這個(gè)調(diào)整行高列寬import openpyxl #利用這個(gè)填充顏色import numpy as np #下面這兩個(gè)是數(shù)據(jù)存儲(chǔ)的兩種方式,用此種方式處理數(shù)據(jù),比列表高效import pandas as pdclass 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進(jìn)制顏色碼 def ten2_16(self,num): tmp = hex(num).replace(’0x’, ’’) return tmp if len(tmp) > 1 else ’0’ + tmp #獲取像素?cái)?shù)據(jù)并轉(zhuǎn)化為16進(jìn)制 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()
最后四行前兩行可以直接寫在第三行中,就是對(duì)象的實(shí)例化中另外還有一點(diǎn),image_path中的 tttt.jpg是直接和我的py文件放在一起的,不然運(yùn)行會(huì)報(bào)錯(cuò)。
四、結(jié)語(yǔ)
好啦,到此所有東西已全部搞定,當(dāng)然還有很多要注意的,第一、方法3中紅綠藍(lán)的提取中這部分的編號(hào)是剛好相反的,提取時(shí)候需要注意如下
當(dāng)然你也可以嘗試改變這個(gè)值看最后會(huì)得到什么結(jié)果。藍(lán)色的太陽(yáng) 紅色的天空 或者是綠色的帽子,哈哈 好吧這個(gè)就你們自己發(fā)揮了。第二、除了以上一點(diǎn)需要注意的,還有一個(gè)需要注意,就是像素不能太高。我測(cè)試了下342*218的話我的i7-6700u打開excel就不是很流暢了。你可以遍歷的時(shí)候以2個(gè)像素點(diǎn)或者四個(gè)像素點(diǎn)為步長(zhǎng),不過(guò)這樣我沒(méi)試過(guò),可能顆粒感比較明顯吧(自己猜測(cè)沒(méi)試過(guò)),或者把原始圖片修改下。
到此這篇關(guān)于利用python在excel中畫圖的實(shí)現(xiàn)方法的文章就介紹到這了,更多相關(guān)python excel畫圖內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. UDDI FAQs2. ajax實(shí)現(xiàn)頁(yè)面的局部加載3. Jsp中request的3個(gè)基礎(chǔ)實(shí)踐4. 詳解JSP 內(nèi)置對(duì)象request常見(jiàn)用法5. asp.net core項(xiàng)目授權(quán)流程詳解6. SpringBoot后端接口的實(shí)現(xiàn)(看這一篇就夠了)7. 阿里前端開發(fā)中的規(guī)范要求8. Spring Cloud 優(yōu)雅下線以及灰度發(fā)布實(shí)現(xiàn)9. asp讀取xml文件和記數(shù)10. ASP和PHP文件操作速度的對(duì)比
