前言:
課堂小專(zhuān),不到半學(xué)期的時(shí)間要做個(gè)修圖軟體。
老師評(píng)分比較高,所以得肝一點(diǎn)o( ̄┰ ̄*)ゞ
不過(guò)倒是學(xué)到很多js操作。
操作畫(huà)面
關(guān)於詳細(xì)功能介紹,請(qǐng)看這篇功能介紹。 關(guān)於本文主要內(nèi)容與程式碼,請(qǐng)看這篇 製作過(guò)程。
Python UI介面選擇
一開(kāi)始課堂上是教預(yù)設(shè)的Qt軟體,但我覺(jué)得Qt醜醜的,所以忍不住去嘗試其他框架。
Tkinter
跟以前做window form很像,用程式碼掛載與編排UI物件。
Qt Designer
在Anaconda預(yù)設(shè)功能, Anaconda資料夾下找到designer.exe啟動(dòng)。
排版檔案會(huì)取為.ui附檔名,操作邏輯與Tk類(lèi)似。
範(fàn)例: 讀取圖片、變暗處理。
內(nèi)部使用Bottle Server框架,可以用網(wǎng)頁(yè)技術(shù)寫(xiě)介面,但不像flask能直接host在線上。
Flask / Django
使用Python編寫(xiě)的輕量級(jí)Web應(yīng)用框架。
範(fàn)例: flask基本頁(yè)面,但其網(wǎng)頁(yè)模板概念跟Django雷同。
範(fàn)例: Django網(wǎng)頁(yè)
創(chuàng)個(gè)views.py檔案,裡面定義Hello頁(yè)面內(nèi)容
在urls.py定義Hello頁(yè)面的網(wǎng)址
綜合比較下來(lái),我選擇開(kāi)發(fā)桌面應(yīng)用程式的eel,若小專(zhuān)題在展示的時(shí)候因?yàn)榫W(wǎng)路問(wèn)題lag那可就掉渣了。( ̄┰ ̄*)
框架名稱(chēng) |
優(yōu)點(diǎn) |
缺點(diǎn) |
Tkinter |
像是用Python程式碼撰寫(xiě)介面的Qt Designer。 |
邏輯與QtDesigner類(lèi)似,同樣無(wú)法解決程式碼攏長(zhǎng)、難做排版等問(wèn)題。 |
Flask/Django |
較完整且可部屬網(wǎng)頁(yè)的web應(yīng)用框架。 |
Python與前端邏輯溝通較複雜,需使用ajax等呼叫方式。 |
eel |
旨在於結(jié)合前端技術(shù)開(kāi)發(fā)桌面應(yīng)用程式,前後端邏輯串接容易。 |
我試著包在docker環(huán)境下部屬但失敗多次,雖然文獻(xiàn)不多但似乎eel不支援網(wǎng)站部屬。 |
EEL基本使用
我是觀看他的影片:
python 呼叫js方法
python 方法上加@eel.expose 讓js端可以呼叫。
func.js檔案:
Async方法使用
按下按鈕後,js端等待python處理結(jié)果後出現(xiàn)alert。
JS-EEL圖檔傳輸
跨語(yǔ)言開(kāi)發(fā)首先遇到的問(wèn)題便是如何傳遞圖片資訊? 由於處理後的圖片需轉(zhuǎn)換成前端html可顯示的based64編碼,其跟openCV imread讀取進(jìn)來(lái)的圖片格式之間的關(guān)係又是如何? 為此我必須先了解從HTML的input 標(biāo)籤輸入的圖片至python端之間的格式與轉(zhuǎn)換。我整理出如下圖這個(gè)流程:
(1.) 由input標(biāo)籤開(kāi)啟的圖片為大型二進(jìn)位檔物件(Binary Large Object ,blob),代表了一個(gè)相當(dāng)於檔案(原始資料)的不可變物件。
(2.) 需實(shí)作js的FileReader物件,將blob轉(zhuǎn)碼成based64字串。
(3.) 透過(guò)eel框架傳送字串至Python端。
(4.) 使用based64處理套件將字串解析成byte陣列。
(5.) 透過(guò)numpy將byte陣列轉(zhuǎn)成uint8陣列。
(6.) 透過(guò)cv2套件將uint陣列解碼成圖片,此時(shí)得到的檔案形同於imread進(jìn)來(lái)的圖片。
(7.) 使用圖片資料進(jìn)行影像處理操作。
(8.) 將處理完的圖片回傳至前端作顯示時(shí),逆著遵循前述的轉(zhuǎn)碼步驟,先將圖片轉(zhuǎn)成byte陣列,再以based64編碼成字串透過(guò)eel框架溝通回前端,由js接收並設(shè)定img標(biāo)籤的src。
JS讀取圖片
使用jQuery偵測(cè)input標(biāo)籤Change事件,搭配fileReader轉(zhuǎn)成base64字串。
Python接收?qǐng)D片
將base64字串透過(guò)轉(zhuǎn)碼,轉(zhuǎn)程opencv可使用的格式。
搭配OpenCV
範(fàn)例: 將圖片轉(zhuǎn)灰階
Python傳回圖片
直方圖
直方圖常常用在檢視圖片顏色趨勢(shì)、集中位置等等。
一開(kāi)始使用Chart.js插件:
js端
Python端
注意np array無(wú)法直接傳輸,所以要轉(zhuǎn)成一般array。
瀏覽器無(wú)法像Python的numpy與的plot套件快速做統(tǒng)計(jì)與圖表,加上本身也不支援多線程(Multi-threading),因此當(dāng)圖片解析度大,需要統(tǒng)計(jì)的數(shù)變多,前端直方圖生成便會(huì)延遲,除了採(cǎi)用異步執(zhí)行避免程序卡死外,我還試過(guò)多個(gè)輕量圖表套件如Chart.js、dygraphs、EChart.js,尋找對(duì)資料最友善的解決方案,雖然目前前端直方圖生成仍有延遲存在,是日後需想辦法解決的問(wèn)題(目前已是在Python生成直方圖數(shù)據(jù),再傳輸至前端表現(xiàn),理論上只需處理255*3個(gè)顏色資料,我認(rèn)為會(huì)卡的點(diǎn)在於繪製與自動(dòng)尋找最小至最大值區(qū)間)。
等化功能
等化是將像素顏色拉得平均一點(diǎn)。
操作Hot Key
註冊(cè)document事件,並藉由array紀(jì)錄各步驟的base64字串。
JS寫(xiě)出圖片
拖拉圖片
JS事件
在修改圖片時(shí)觸發(fā)事件,如此便能最後續(xù)處理,例如圖片縮圖僅需在圖片有更動(dòng)時(shí)才須更新。
顏色通道
圖片RGB拆成可以分別開(kāi)關(guān)的通道,在P圖的時(shí)候常會(huì)從通道中選一張二值化效果最好的通道做遮罩,不過(guò)目前本軟體的通道只能顯示、不能編輯(;′??Д??`) (時(shí)間不夠..)。
在地化
加上為了降低開(kāi)發(fā)環(huán)境複雜度,本軟體前端使用較原生的JQuery輔助,沒(méi)有用如React.js等完整的web生態(tài)系統(tǒng),能使用的工具較為受限,最後使用行之有名的i18n在地化解決方案應(yīng)付小需求翻譯。
後紀(jì):
與全班做法不同,在學(xué)習(xí)的路上總是有些孤獨(dú)、無(wú)助。所幸社群的力量,每當(dāng)我遇到困難時(shí)總是能在StackOverflow等平臺(tái)找到方法。也感謝eel團(tuán)隊(duì)釋出這個(gè)便捷的框架,我也想盡力將所學(xué)知識(shí)、概念紀(jì)錄並分享下來(lái)回饋社群。
這個(gè)專(zhuān)案少說(shuō)也陪伴我快半個(gè)學(xué)期,每天埋頭在打程式、修BUG,最後也算是來(lái)到個(gè)Ending,就像小孩子畢業(yè)一般,想盡力寫(xiě)好文件、交代擴(kuò)充方法等等送它最後一程,儘管我總是會(huì)有點(diǎn)自卑的覺(jué)得「某某功能太基本不值得介紹」所以少寫(xiě)在文件裡,也希望各位能多看看這學(xué)期的努力結(jié)晶。
附錄:
主要功能與對(duì)應(yīng)選單做成表格整理如下:
功能名稱(chēng) |
套用結(jié)果 |
選單 |
調(diào)整大小 |
|
|
旋轉(zhuǎn) |
|
*旋轉(zhuǎn)操作可即時(shí)預(yù)覽,按下套用後自動(dòng)補(bǔ)齊邊界。 |
等化 |
|
*等化後自動(dòng)更新直方圖結(jié)果 |
顏色調(diào)整 |
|
*貼心提供色彩對(duì)照表方便調(diào)整 |
色彩分割 |
|
*範(fàn)例:抓取藍(lán)色頭髮。 |
曝光校正 |
|
|
對(duì)比校正 |
|
|
高斯模糊 |
|
|
去除雜訊 |
|
|
美肌 |
|
|
銳化 |
|
|
邊緣抽取 |
|
*有做彩色/灰階圖兩種處理,若只要白線需先使用「灰階」功能。 |
邊緣保留 |
|
|
鉛筆風(fēng)格 |
|
特色 |
|
毛邊模糊 |
|
魚(yú)眼 |
|
波紋模糊 |
|
|
放射像素模糊 |
|
|
漣漪效果 |
|
|
扭轉(zhuǎn)效果 |
|
|
運(yùn)動(dòng)模糊 |
|
|
放射模糊 |
|
|
標(biāo)示人臉 |
|
|