【MATLAB Image Processing Toolbox 入門教學一】快速入門之「影象匯入匯出」與「檢測影象中的圓」

2020-10-29 18:00:18


寫在前面:2020.10 轉博的第一個月,本科自動化專業,碩士光電科學與工程專業,博士光學工程專業。我目前還認為自己是一個本科生,因為我只拿到了本科的學位證書。碩士期間做的專案和影象處理無關,自學MATLAB Iamge Processing Toolbox是想增加自己學習的範圍,不知道哪天用得上。想要更新這個系列一是為了給自己接下來幾年的學習做個記錄,二是真切希望自己能堅持下來。我深知想要順利博士畢業或者說符合博士的身份,只學習這些是不夠的,希望社群大佬輕噴,另外希望與大家共同進步。

MATLAB Image Processing Toolbox 簡介

MATLAB幫助中心檔案這樣描述:
「Image Processing Toolbox™ 為影象處理、分析、視覺化和演演算法開發提供了一套全面的參考標準演演算法和工作流 App。您可以使用深度學習和傳統影象處理技術執行影象分割、影象增強、去噪、幾何變換和影象配準。工具箱支援處理二維、三維和任意大的影象。
Image Processing Toolbox App 可讓您自動完成常見的影象處理工作流。您可以互動方式分割影象資料、比較影象配準技術,以及對大型資料集進行批次處理。利用視覺化函數和 App,您可以探查影象、三維體和視訊;調整對比度;建立直方圖;以及對關注區域 (ROI) 執行操作。
您可以通過在多核處理器和 GPU 上執行演演算法來提高演演算法的執行速度。許多工具箱函數支援桌面原型和嵌入式視覺系統部署的 C/C++ 程式碼生成。」

總結就是:MATLAB影象處理工具箱可以對您的任意尺寸影象實現任意的操作(廢話)。

MATLAB Image Processing Toolbox 的知識架構

Image processing toolbox包括以下幾個內容:

1 Image processing toolbox快速入門:基礎知識的學習;
2 匯入、匯出和轉換:影象資料的匯入和匯出,影象型別的轉換換;
3 顯示和探查:用於影象的顯示和探查的互動性工具;
4 幾何變換和影象配準:使用強度相關性、特徵匹配或控制點對映來縮放、旋轉、執行其他 N 維變換和對齊影象;
5 影象濾波和增強:對比度調整、形態學濾波、去模糊、基於關注區域的處理;
6 影象分割與分析:區域分析、紋理分析、畫素和影象統計量;
7 深度學習進行影象處理:使用折積神經網路執行影象處理任務,例如去除影象噪聲和基於低解析度影象建立高解析度影象,此時需要用到deep learning toolbox;
8 三維體影象處理:對三維體資料進行濾波、分割和其他影象處理操作;
9 程式碼生成:為工具箱函數生成 C 程式碼和 MEX 函數;
10 GPU運算:在圖形處理單元(GPU)執行影象處理程式碼。

作者目前也不知道各個模組具體的作用,可能等我有幸更新完所有模組的時候才有資格說這些。有基礎的可以根據上面的大概描述選擇自己感興趣的部分繼續學習。

對MATLAB Image Toolbox做完介紹,下面開始進行第一部分Image processing toolbox快速入門的學習。

Image Processing Toolbox快速入門之「影象匯入匯出」與「檢測影象中的圓」

1 基本影象的匯入、處理和匯出

1.1 影象的讀入和顯示

MATLAB中使用imread和imshow來進行讀取圖片和顯示圖片的操作,類似於OpenCV。
從工作區讀圖片:

I=imread('1.jpg')

此時,圖片1.jpg就已經讀入,I為表示圖片的陣列。
由於讀入的是一張彩色圖片,所以數字I是三維陣列
顯示圖片:

imshow(I)

趙雲龍膽面板,賊帥。
之前讀入的圖片就可以顯示出來。

1.2 檢查影象在工作區的顯示方式

可以使用whos指令,檢查imread讀入的影象在工作區的儲存方式,說白了就是檢視陣列I的大小尺寸資料型別等,這些在工作區中也可以檢視。
在MATLAB命令列視窗繼續輸入

whos I

可以得到:在這裡插入圖片描述

1.3 提高影象對比度

使用imhist函數檢視影象的畫素強度分佈,但注意,imhist只能檢視灰度影象的直方圖,所以稱為灰度直方圖。使用rgb2gray將RGB影象轉成灰度影象,繼續輸入:

J=rgb2gray(I);
imhist(J);

即得到趙雲-龍膽的灰度圖J及其灰度直方圖。
灰度圖
灰度直方圖
灰度直方圖反映了影象的對比度強弱,直方圖分佈範圍越寬,表明對比度越強,反之則越弱。

histeq函數用於直方圖均衡化,可增強影象的對比度。
繼續輸入:

K=histeq(J);
figure;imshow(K);
figure;imhist(K);

可以得到直方圖均衡化後的灰度影象及其直方圖。
直方圖均衡化後的趙雲-龍膽
均衡化後的灰度直方圖
可以看出,處理後的灰度影象黑白對比更加明顯,灰度直方圖的分佈範圍更加廣泛。

1.4 將圖片寫入磁碟

使用imwrite將圖片K寫入磁碟:

imwrite(K,'ok.jpg');

即可將圖片寫入MATLAB當前工作資料夾。
如果想要將圖片寫入任意指定的資料夾,就在兩個單引號中間輸入完整的路徑。

我們可以使用imfinfo函數檢視資料夾中圖片的資訊,例如圖片的尺寸大小、格式、顏色型別等。
繼續輸入

imfinfo('ok.jpg');

得到

能看出,返回的圖片資訊型別是陣列型別。

2 檢測和測量影象中的圓形物件

本小節中說明MATLAB檢測影象中圓形物件的imfindcircles函數的使用方法,並通過viscircles函數將檢測到的圓標註出來。

2.1 載入影象和確定搜尋圓的範圍

為了方便範例,本次採用的圖片是MATLAB自帶的「彩色薯片」,首先是imread讀入圖片,並用imshow顯示。

 srcImage=imread('coloredChips.png');
 imshow(srcImage);

在這裡插入圖片描述
這張圖作為圓形物件的識別範例真是完美,既有顏色對比強烈的藍色和紅色薯片,也有和背景顏色近似的黃色,更重要的是,圖中有一些重疊交錯的圓,貼近實際情況中的目標檢測,這也是比較具有挑戰性的地方。

載入圖片之後,接下來確定搜尋圓的半徑範圍,這裡採用的是imdistline函數。接著輸入:

d=imdistline;

在這裡插入圖片描述
可以看出在之前載入的彩色薯片影象上多了一個類似標尺的玩意,我們可以拖動這個標尺,移動標尺兩邊的方框,用於測量影象中圓形的直徑,此處只需要測量一個大概的半徑範圍即可。
在這裡插入圖片描述
在這裡插入圖片描述
隨意測量了兩個,直徑在40-50個畫素,所以半徑範圍為20-25,當然保險起見,也可以設定大一點,這個區間[20,25]要記住,下面的圓形識別時需要用到,但要注意,確定了半徑範圍之後別忘記刪除imhistline工具,也就是上面的物件d。

delete(d);

2.2 初步嘗試圓識別

在圓識別之前,讓我們先熟悉使用的函數:imfindcircles.

[centers,radii]=imfindcircles(A,radiusRange);

A即為輸入的rgb影象,radiusRange就是上一步我們確定的搜尋圓的大概半徑,返回的centers和radii為檢測到的圓心位置和對應的圓半徑。
我們在MATLAB中輸入:

[centers,radii]=imfindcircles(srcImage,[20,25]);

在這裡插入圖片描述

但卻發現,返回的圓心和半徑居然是空陣列。沒關係,這是正常現象,只是沒檢測到圓罷了,至少我們會簡單使用imfindcircles這個函數了,但到底怎麼才能檢測到圓,繼續往下看。

2.3 深入imfindcircles函數

讓我們深究一下imfindcircles這個函數,通過MATLAB幫助檔案,我們發現有這個語法:

[centers,radii,metric]=imfindcircles(A,radiusRange,Name,Value);

引數A和radiusRange已經在上面說過了,後面的Name是傳遞給imfindcircles函數的引數名稱,value是對應的引數值。
具體的Name有:ObjectPolarity/Method/Sensitivity/EdgeThreshold。我們逐個引數分析:
1 ObjectPolarity
此引數用於指定檢測的目標與背景之間的亮度關係。具體的值和含義為:
‘bright’(default):搜尋比背景更亮的圓形物件;
‘dark’:搜尋比背景更暗的圓形物件。

那麼,我們怎麼確定目標比背景更亮還是更暗呢?可以用下面的方法:
使用rgb2gray將彩色薯片轉成灰度圖。

grayImage=rgb2gray(srcImage);
 imshow(grayImage)

在這裡插入圖片描述
可以看出,灰度圖中大部分圓比背景顏色更深,更暗,所以對於這張圖的ObjectPolarity引數,設定為’dark’更合適。

2 Method
此引數用於指定累加器陣列的演演算法,有下面兩個值:
‘PhaseCode’(default):Atherton和Kerbyson的相位編碼方法;
‘TwoStage’:這個演演算法使用的是兩段圓霍夫變換。

3 Sensitivity
此引數設定圓形霍夫變換累加器陣列的檢測敏感度,此引數對於兩個Method引數均有效果。預設值為0.85,可以設定為0-1內的數位。
較高的敏感度可以檢測到弱圓和被遮擋的圓,但也會增加誤檢測的風險。

4 EdgeThreshold
此引數用於確定影象中邊緣畫素的梯度閾值,將閾值設定為較低的值時,imfindcircles會檢測到更多的圓形物件(具有弱邊和強邊)。隨著閾值值的增加,它會檢測到較少具有弱邊的圓。一般預設情況下,imfindcircles使用函數graysthresh自動選擇邊緣漸變閾值。

在返回的參數列裡,我們發現還多了一個引數metric。此引數返回的是檢測到的圓的強度,圓強度是圓中心的相對強度。

MATLAB幫助檔案裡列出使用imfindcircles函數的幾個tips:
①當輸入的最小半徑小於5時,imfindcircles的檢測精度會受到影響。
②使用預設的演演算法(PhaseCode)會比TwoStage在半徑近似時速度更快。
③兩種檢測演演算法都有其優缺點,檢測結果因輸入圖片而異。
④當圓的圓心在圖片外時,imfindcircles函數檢測不到此圓。
⑤在檢測二值圖片時,imfindcircles函數會對其預處理,同樣,檢測rgb圖片時,imfindcircles函數也會將其先轉為灰度影象。

2.4 再次嘗試圓識別

深入瞭解imfindcircles函數中各個引數的作用後,接下來進行真正的圓識別,並通過viscircles函數將檢測到的圓在原影象中顯示出來。

在MATLAB中輸入:

 [centers,radii]=imfindcircles(srcImage,[20,25],'ObjectPolarity','dark','Sensitivity',0.9);
 imshow(srcImage);
 h=viscircles(centers,radii);

在這裡插入圖片描述
我們發現,有部分圓已經被檢測出來了。繼續增大檢測靈敏度:

 [centers,radii]=imfindcircles(srcImage,[20,25],'ObjectPolarity','dark','Sensitivity',0.92);
delete(h);%刪除之前畫的圓
 h=viscircles(centers,radii);

在這裡插入圖片描述
可以看出,這次檢測到了更多的圓。讓我們嘗試使用另外一種檢測方法,其他引數不變:

 [centers,radii]=imfindcircles(srcImage,[20,25],'ObjectPolarity','dark','Sensitivity',0.92,'Method','twostage');
delete(h);
 h=viscircles(centers,radii);

在這裡插入圖片描述
這次,除了比背景亮的黃色圓沒有被檢測出來之外,其他的圓都被檢測出來了。
可以看出,使用TwoStage演演算法在靈敏度0.92時能檢測更多的圓。一般來說,兩種演演算法是互補的,有不同的優點。預設的PhaseCode方法速度更快,抗噪聲,穩定性強,但想要達到與TwoStage演演算法相同的檢測效果,則需要更高的靈敏度,我們採用預設演演算法,在0.95靈敏度下檢測試試看:

 [centers,radii]=imfindcircles(srcImage,[20,25],'ObjectPolarity','dark','Sensitivity',0.95);
delete(h);
 h=viscircles(centers,radii);

在這裡插入圖片描述
效果和TwoStage演演算法在靈敏度0.92下的檢測結果一樣。

2.5 完善圓識別

經過上面幾個步驟的檢測,除了比背景更亮的黃色薯片,其他都被檢測出來了,下面我們來檢測黃色圓,將ObjectPolarity引數設定為bright:

 [centers,radii]=imfindcircles(srcImage,[20,25],'ObjectPolarity','bright','Sensitivity',0.95);
delete(h);
 h=viscircles(centers,radii);

在這裡插入圖片描述
有三個黃色圓被檢測出來,還有一個邊界較為模糊的圓沒有被檢測。我們將靈敏度調到0.95時,這個圓可以被檢測,但除此之外還有橙色和藍色的圓被檢測出來,有興趣的同學可以試一下。
那麼如何做到在不重複檢測的情況下檢測到這個黃色的圓呢?一個我們忽視的引數EdgeThreshold派上了用場。邊界模糊的黃色圓具有更低的邊緣梯度,預設的邊緣梯度值不能將這個圓的邊緣識別出來,所以我們要降低邊緣梯度的值:

 [centers,radii]=imfindcircles(srcImage,[20,25],'ObjectPolarity','bright','Sensitivity',0.92,'EdgeThreshold',0.1);
delete(h);
 h=viscircles(centers,radii);

在這裡插入圖片描述
可以看出,所有的黃色圓都被檢測處出來了(雖然還有個綠色。。。)。

2.6 繪製檢測出來的所有圓

本節將MATLAB識別圓的完整程式碼列出,僅供參考

srcImage=imread('coloredChips.png');
imshow(srcImage);
d=imdistline;
delete(d);
[centersDark,radiiDark]=imfindcircles(srcImage,[20,25],'ObjectPolarity','dark','Method','TwoStage','Sensitivity',0.92);
hDark=viscircles(centersDark,radiiDark,'EdgeColor','G'); %設定畫出的圓的邊界為綠色,其中EdgeColor不同版本不同,博主用的2014,新版本的MATLAB用Color即可。
[centersBright,radiiBright]=imfindcircles(srcImage,[20,25],'ObjectPolarity','bright','Sensitivity',0.92,'EdgeThreshold',0.1);
hBright=viscircles(centersBright,radiiBright,'EdgeColor','B');

在這裡插入圖片描述
大功告成,所有的圓都被檢測出來了。
大家可以嘗試改一下imfindcircles函數中各種引數的值,看看有沒有驚人的結果。

第一次寫文章,難免由排版不好看、錯誤的地方,盡請指正。