發表文章

目前顯示的是 1月, 2022的文章

用Python實作 Perspective Transformation 透視變換

圖片
主要演算法 通常我們在自然背景拍攝一張照片時,或多或少都會有一些 透視變形 存在,而透視變形是由拍攝和觀看圖像的相對距離決定的,導致遠近特徵的相對比例有變化,產生了彎曲或變形,當然在本例子,我是刻意拍了一張比例歪斜的圖,想要驗證依照公式轉換會得到什麼效果。 依照解決方法,這樣的變形我們可以下列的聯立方程式來表示: ​x = ax’ + by’ + cx’y’ + d y = ex’ + fy’  + gx’y’ + h ​其中x、y為你原始影像的座標系,x’、y’為校正後的座標系, a、b、c、d、e、f、g、h為常數,表示變形關係。 程式片段 定義 高斯消去 2. 先定義4個點,找出矩陣 3. 照公式進行矩陣轉換,解出方程式,輸出結果就得到圖片了。 4. 另外我也參考網路範例,仿造OpenCV寫了一個轉置方法,後續比較一下兩種做法的差異。   測試資料與結果 原圖是張刻意拍歪斜的照片,我標出四個白點,可以看到原始轉換區塊變形到接近菱形了。 2. 轉換後得到的結果如下,或許是因為變形幅度高,沒達到完整的轉換。 3. 參考網路實作 Perspective Transformation 做出來的效果,因為先做3D後轉2D,校正效果很好,只是程式寫得不好,有失真。 4. 使用Open CV做的效果 討論 原本課堂講解的校正來源是一個平行四邊形,校正效果相當好,但在本次作用我使用一個不規則的多邊形來做轉換,雖然轉換結果不比原本的好,但還算可以得出資訊。 參考Perspective Transformation實做出來的程式做轉換,對於不規則多邊形轉換的效果很好,只是有失真,若用OpenCV轉出來的話就趨近完美了。 此類的校正可以應用在機器人自駕時的資訊辨認,或是在OCR應用上先把讀入的圖片做校正,在讀取資訊,可以減少判斷失誤。 在Deepfake影片偵測的研究中,許多論文的原理是把影像的Frame讀入後分析他是不是假造影像;如果在深度學習時,我先把人臉或是指定的擷取特徵做校正,可以把每個Frame的特徵變成一樣的構圖,就有機會分辨出他是不是造假的Frame:因為Frame造假是基於原本扭曲變形的畫面做變更,在校正後應該可以看出他和一般正常角度Frame的不同之處。

使用Python實作Image Enhancement

圖片
趁著學期告一段落,工作也在過年前的休息時間,趕快把之前的作業整理出來;這篇文章依然會是先前的 影像處理課程所編寫的作業 ,在這裡不會用到深度學習或機器學習,而是使用傳統的影像處理概念來做,目的是為了瞭解原理。 本篇文章主要是探討如何通過二階微分,將影像邊緣強化。 主要演算法 原圖雖然用的是彩色影像,但我在程式中有轉為灰階,所以實際增強是針對灰階影像增強。 把原影像先乘 Laplacioan運算子做二階微分 ,可以得到影像的邊緣。 接著和原始影像相加,邊緣會被加強,但是因為原圖的雜訊也被放大,所以這裡的圖是有雜訊的加強,得到圖A。 接著原始影像用 Sobel對X和Y做一階微分,可以得到影像邊緣圖B ,接著對圖B做去雜訊。 再來把圖B的像素做標準化,每個像素會被做成0~1的數值,此時在平坦區(比較亮的地方)數值會較大,趨近1,邊緣(比較暗的地方)則趨近0。 我們把標準化的矩陣和圖A相乘,可以知道原圖依照比例被放大了,原先暗的像素方又變得更黑了,非邊緣的地方則會因為乘趨近1的值,故不太有大變化,結果我們會得到圖C,圖C就是加強後的結果。 程式片段 1. 先把圖片轉成灰階影像。     2. 定義Laplace運算子遮罩 3. 定義Sobel運算子遮罩,0是dY,1是dX 4. 定義Slide Window Filter降噪 5. 對原本影像乘Laplace運算子,二階微分得到邊緣,接著和原圖相加。 6. 把微分後結果和原圖相加,得到一張銳化的圖。 7. 接著對原圖做Sobel運算子,一階微分先做dX再做dY,然後用OR合成,也可以得到一張圖的邊緣。 8. 接著用 Slide Window filter 把雜訊降低。 9. 最後我們把這結果做標準化,取得一個0~1的矩陣,然後把矩陣和步驟3的圖相乘,圖的暗部被放暗,亮度則不太改變,因為暗部被變暗了,會感覺到邊緣變得銳利。 測試資料與結果 原圖,將他模糊後轉成灰階。 2. 做Laplace運算後得到邊緣。 3. 和原圖相加,但感覺到雜訊也放大了 4. 對原圖X、Y做Sobel微分後,做合成,得到一個較為銳利的邊緣。 5. 使用Slide Window Filter把雜訊去掉。 6. 接著把模糊後結果乘上前面的圖,得到邊緣增強的結果。 討論 把Sobel微分後的結果做標準化後,再乘上和二階微分後的圖,...

使用Pytorch實作卷積網路(CNN)做多分類圖片識別

圖片
這篇文章是我在修習 影像處理 時做的作業之一,主要是想訓練一個Model來識別輸入的圖片是在室外環境,還是室內環境,為了完成這個目標,我使用 Pytorch 實作了 卷積神經網絡(Convolutional Neural Network)簡稱CNN ,搭配網路上的資料集進行訓練,最後將我隨意亂拍的照片輸入做辨識,發現效果還不錯。 以下節錄我當時整理出來的作業內容,大略解釋了演算法的概念,訓練過程,和最後檢討,因為是作業,故有很多是比較學生角度來解釋整個事件。 主要演算法 室內、室外乍看是二分類,可以用線性回歸(Linear regression)的方式來做,但是考量室內室外只是眾多場景一種,故我用多分類(Multi label classification)的方式開發程式,並用CrossEntropy計算Loss。 會採用多分類(是因為我單純認為用二分法來識別兩個場景不是很好的方法,最後預測結果會落在0~1之間,若用0.49中位數來分辨0和1,感覺有點奇怪。 本次使用Pytorch實做一個簡單的CNN網路架構,CNN最主要會由Convolutional和Maxpool兩種層所組成,激勵函數是Relu,然後最後要用線性層(Fully Connected)輸出預測結果。 初次訓練只用了2層CNN搭配1層的線性層,但訓練的Loss率沒有想像好(低),故再次修改用4層CNN搭配3層的線性層,一方面想看看線姓層的降維幅度是否也會改善Loss率。 在訓練、驗證和測試資料夾中,我都定義了Indoor和Outdoor資料夾,同時也是以此當作標籤功能。 最後輸出時,我們去觀察哪個Label的得分最高,就可以知道他是屬於哪個類型的,假定我規劃0是室內,1是室外,當我發現0的得分是0.9991,1的得分是0.1234,那則代表這張圖是室外。 訓練過程中,一開始Model會去預測一個分數,但我們會依照正確的分類給他真正的分數,接著算出Loss後,經過backward去更新權重,Model就會知道屬於這張圖真正的分數應該是多少,因此一開始Loss極高是正常的,但會隨著訓練逐漸降低,但是Loss如果隨著訓練持續亂跳亂跳的,那有可能代表圖片的Label太雜亂,Model會精神錯亂,這時候你就必須回頭去檢視你的資料集正不正確。 程式片段 定義網路,4層CNN搭配3層的線性層   本次我是使...

你今天NFT了嗎?

圖片
你今天NFT了嗎?最近台灣科技新聞中,先是區塊鏈,再來是元宇宙,最近最火的莫過於於NFT了,不管是文創業者,譬如霹靂布袋戲推出的 魔吞十二宮NFT ,或是張泰山的球員卡NFT,在在都掀起一波熱潮。 NFT全名Non -Fungible Token,翻成中文就是「非同質化代幣」,跟比特幣「非同質化代幣」不太相同,NFT強調的是獨一無二,只會有一份,所以在每個NFT上都會有一個編碼,用來做為識別。 舉個淺顯易懂的例子好了! 就比特幣「非同質化代幣」來說,今天你出門參加聚餐,身上帶了一張千元鈔票,跟朋友碰面時,不巧朋友想買東西卻忘記帶錢,就跟你借一千元,等遇到提款機時,才領了一千元給還你,此時對你來說,你皮夾裡依然有一張千元鈔票,這也是貨幣的本質,來來去去的,我們講究的是他等同的價值,你身上有一千塊,不管你的一千塊是一張鈔票,還是2張五百元鈔票,還是10張一百元鈔票。 但就NFT來說,如果硬要用剛剛鈔票的例子來講,當朋友領了一千元還你,這張一千元已經不是當初的一千元了,因為鈔票上的編號並不相同;這樣講可能太玄,簡單來說,NFT可以看作是一個所有權,譬如房屋、車輛或是土地的所有權,你必須把這權狀握在手上,你才能證明這房屋或土地是你的。 若是你的權狀弄丟了,那你就倒大楣了。 而透過區塊鏈的加密技術,當你擁有一個NFT,關於這個NFT的所有權則會被寫入到區塊中,你會有一把金鑰(Token)來解開所有權的紀錄資訊,證明這個NFT是你的;再科普一點,當你擁有一塊土地,理所當然你就會有一張土地權狀,這張土地權狀會由當時的政府機關頒發,如果你夠謹慎,你會把他鎖在保險箱中,只是在區塊鏈構成的數位世界中,你所擁有的權狀是由平台頒發,而權狀資訊則是被加密後所在網路上的不知名地方。 之所以說不知名,也是區塊鏈的特性之一,匿名。   Photo by Pixabay on Pexels.com 一句話快速了解NFT,NFT就是透過區塊鏈做出來的數位版權技術。 也就所以你會發現,一開始踏入NFT的作品,多偏向數位資料,譬如影片、照片,至少以現在大部分新聞報導的是如此,事實上只要可以數位化的內容都可以被做成NFT,例如程式碼, WWW的發明者就把他當時的原始碼做成NFT銷售 ,而T witter的開發者也把他的第一則推文作為NFT銷售。 在現今市場的大熱潮中, NFT的製作和銷售達到蠻有趣的...

在Colab Notebooks上定義並訓練Yolov4 Model (以水果辨識為例)

圖片
Yolo ( You only look once )可以說是最知名的即時辨識模型了,不僅效果好,速度也快, 當初的論文可以參考這裡, 現在一路也出到V4了,你可以在訓練資料上定義不同的圖片和標籤,以此訓練模型,就可以輕鬆達到辨識新目標的效果。 當然我這樣講是有點浮誇,你必須注意一下你的電腦能不能如願把訓練跑完。 在這次的訓練中,我嘗試在Colab Notebooks上安裝,並訓練Yolov4,主要是為了省去GPU這個環節,因為平時我的工作筆電是一台Mac,想要跑完訓練是真的需要一點時間的;另外為了完成訓練,首先我必須找到一份資料集,再來我必須製作自己的 YOLO  Format標記 檔案,提供給Yolov4進行訓練。 資料集的部分,我使用的是Kaggle上的Fruits fresh and rotten for classification資料集,這其中包含了新鮮蘋果、香蕉、橘子和腐敗的蘋果、香蕉和橘子等六種類型的圖片, 如何在Colab Notebooks上下載Kaggle資料集的話可以參考我這篇文章。 至於如何把Kaggle資料集轉成Yolo format的部分, 可以參考這篇文章,在這裡我捨棄了用LabelImg,也捨棄了Yolo Marker, 為什麼呢? 純粹是因為我懶, 純粹是因為我想盡量把工作自動化,雖然可能割捨掉一些正確性。 在準備好資料集和Yolo Format的標記檔案後,我們可以開始接著作模型下載和訓練的工作,首先我們要先從AlexeyAB下載darknet,這是一個使用C語言實作Yolo的共用函式庫,但是可以提供Python調用;當初是從Yolo的原始作者那fork出來的分支,因為原作者已經不維護原始程式碼了,所以網路上大多用這個版本在訓練和實戰。 首先,我們下載darknet。 當darknet下載完成後會在Colab上建立一個目錄,這裡要注意,後面訓練、打包時,都會在這個目錄底下進行。 當Make時,或模型訓練時,會需要持續寫入權重(weights),所以我們需要先把目錄權限改一下,開放寫入。 在Make打包之前,我們需要改一下組態檔案,這將影響我們後續打包完的模型如何運作,在這裡我們用sed來修改組態, sed  是「stream editor 」的縮寫,顧名思義是進行串流(stream) 的編輯。無論是在編寫shell 的或處理ST...

利用Open CV自動找出Image的bounding box並轉成Yolo Label

圖片
這陣子我試圖在Yolo V4上訓練一個識別模型,在我原始構想中的功能,是為了讓這個模型可以擁有判斷水果新鮮度、腐敗程度的能力,想當然,如果要達到一定精準度,那勢必是要給他一些訓練資料(Training Data),而訓練資料的多寡也會影響模型判斷的正確性,於是乎,我就在網路上找了些資料集(Dataset),幸運的是最後我在Kaggle上找到這個近乎理想的資料集,裏面包含了腐敗的蘋果、香蕉、柑橘,同樣也有新鮮的蘋果、香蕉、柑橘,其實這資料集的原始功能是用來做一個分類器,只是被我暫借來用在 Yolo V4 上罷了。   也就因為有這些前因後果,這時候我就遇到訓練模型最耗工的時候了:資料預處理;在這個 資料集 中,有腐敗的蘋果、香蕉、柑橘,同樣也有新鮮的蘋果、香蕉、柑橘,我將各個型態的水果歸為一類,因為雖然資料集只有6類(Classes),但是資料集中涵蓋多個變化時段、多個角度、多個面向的水果,故所有圖片總結起來不多不少也是上萬張有。   在Yolo訓練時所需要的Label裡,需要標記圖片中的重點,框出一個正方形,告訴Yolo該去關注哪個區域,並讓Model知道這個區域是屬於哪類型的資料,譬如說我們可以在一張框出人臉來,然後告訴Model這個區域的樣子就是人類。   也就是說,當我想要讓Model知道我這些資料集是腐爛、新鮮的香蕉,我應該先把這些水果的特徵標記起來,然後告訴Model這是腐爛、新鮮的水果,也就是一個多分類的議題,雖然我們知道人工標記是最準確的作法,但當我們知道圖便有上萬張時還採人工用軟體(LabelImg、Yolo marker)來標記,就顯得比較不切實際了。   於是我選擇用 Open CV 在圖片上框正方形,也就是找出bounding box,要完成這個任務,需完成幾個步驟。 首先我們輸入一張圖片。 把cv2. cvtColor把圖片由RGB轉成HSV,主要是為了能方便表現出特定顏色,HSV即色相、飽和度、明度(Hue, Saturation, Value),色相(H)是色彩的基本屬性,就是平常所說的顏色名稱,如紅色、黃色等,飽和度(S)是指色彩的純度,越高色彩越純,低則逐漸變灰,取0-100%的數值,明度(V),亮度(L),取0-100%、越高越亮。 將圖片二值化,指的不是變成灰階圖片,因為灰階圖片的像素有0~2...