1. 程式人生 > >通過opencv進行影象讀取與簡單分割

通過opencv進行影象讀取與簡單分割

BY_ZZX

設計內容:

相機作為機器人感測器的一種,可以獲取現實世界中的豐富資訊,通過影象處理與計算機視覺演算法,可以為機器人的移動提供指導。通過開源計算機視覺工具庫(openCV)獲取相機的影象,並利用該工具庫實現影象處理中的影象分割等簡單演算法。設計內容如下:

1)呼叫openCV提供的API實現相機的讀取餘操作。

2)對於給定的矩形停車位場景,在對讀取到的影象上利用顏色差別進行簡單的閾值分割。

3)提取分割後的影象輪廓,並根據影象輪廓確定停車位邊緣的四個角點。

設計過程:

1.在ubuntu下編譯和配置openCV開源庫

這一步可以參考別人的方法,CSDN有很多,我參考的是下面這個老哥的:

其中自然有很多的不解和疑惑,大概理解是一開始裝的cmake是一個編譯工具,OpenCV的編譯是為了它的函式整合在系統之中。通過下面這三行程式碼可以實現讀取電腦攝像頭並且以視訊的形式展現出來。

cmake .
make
./opencv_example

但是這個示例程式卻存在一個bug:無法用滑鼠×掉,×掉後立馬自己又運行了起來。經過研讀它的程式碼,發現是waitKey(n)函式的問題。waitKey函式刪除就沒法顯示視訊,如果關掉視窗,waitKey(n)函式沒有讀取鍵盤輸入,程式會繼續執行,這是一個衝突,所以通過滑鼠×不了這個程式的執行。

2.學習openCV視覺庫的資料結構表示,如影象的儲存表示與基本操作。

openCV 自帶的示例程式裡主要用到了幾個重要的庫、類和函式:

<opencv2\highgui.hpp>:

包含了媒體輸入輸出,視訊捕捉,影象視訊編解碼和圖形介面等

imread():讀取影象檔案

imshow():在制定視窗顯示檔案

nameWindow():建立一個視窗

imwrite():輸出影象檔案

createTrackbar():建立一個滑條,跟某一個數值相連。

VideoCapture類:

VideoCapture ::××××××(/int device id/const string& filename)可以直接開啟視訊(檔案和攝像頭)。open也可以實現這樣的功能

isOpened()是用來確認是否讀取成功

release()是用來釋放被讀取的視訊

grab()是用來抓取下一幀影象,成功則返回1,因此可以用來判斷下一幀影象是否抓取成功

retreve()是用來返回剛剛抓取的視訊幀

read()是呼叫grab(),retreve()

double get()是用來獲取視訊的引數的

bool set()是用來設定視訊的引數的

還有另外一種獲取視訊幀的方法:是結合了Mat類,例項中運用了Mat image和capture >> image;這兩個操作來實現。

新增水印的函式:putText():傳入要新增水印的影象, 要加的字元, 字型, 粗細 ,  顏色,新增位置等引數

waitKey(n):n為等待的時間,這個函式返回值為按鍵的ASCII碼值,同事這個函式也是顯示圖形介面的介面,如果沒有這個函式,讀取到的攝像頭圖形就沒法展現在顯示器上。如果設定waitKey(0),則表示程式會無限制的等待使用者的按鍵事件 。

openCV讀取和顯示圖片:

error:在網上找了一份程式碼,複習貼上然後make出現了兩個錯誤:

stray ‘\240’ in program
stray ‘\302’ in program

在網上查了一下,240是非法ASCII字元,302是全形字元的問題。只能自己重新寫一遍了,遇到了一些不懂的地方,查了一下:

imread(img.jpg,×××):其中後面一個引數是區分以原始圖、灰度圖、RGB圖格式讀取圖片的三個方式,<0代表原始圖,=0代表灰度圖,>0代表RGB圖(1,2,4)

cout<<endl:是輸出結束符

namedWindow("name",***):後面一個引數是視窗大小相關的,1為自動調節視窗大小使之適應圖片,2是滑鼠可以調節視窗大小。注意這裡是nameWindow而不是nameWindow。

destoryWindow("Window_name"):銷燬視窗

重新寫了一遍後,還是有很多error,發現註釋的寫法有問題,註釋必須緊跟在程式碼後面且之間不能有空格。空行也有問題,程式碼區不能自己加空行進去。甚至行距也會有問題報錯。

終於弄好了,編譯通過,能顯示圖片出來。jpg圖片由於是24位的,所以在imread中第二個引數傳入2時,因為2代表anydepth,如果不是16或32點陣圖,則會以8點陣圖像讀入,變成灰色;傳入引數4時,因為4代表是anycolor,故仍然是彩色的;1代表color,所以也是彩色的。

能完成對圖片的讀取操作了,但是在ubuntu下卻不能直接從word裡面拷貝出裡面的圖片出來,於是安裝了pinta:

sudo apt-get install -f
sudo apt-get install pinta

第一行程式碼是修復依賴包的,f:fix-broken,如果直接輸入第二行程式碼,則會報錯沒有安裝依賴包,並且在我的電腦上無法對磁碟進行寫入。然後開啟word,放大,按PrntScr鍵截圖,用pinta裁剪,儲存。

openCV對影象進行閾值分割和提取輪廓

對其中的一些函式進行了研讀:

cvtColor():

C++: void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 );


. InputArray src: 原影象
. OutputArray dst: 變換後儲存影象
. int code: 轉換格式的標識
. int dstCn = 0: 目標影象通道數,如果取值為0,則由src和code決定

利用cvtColor可以把彩色圖轉換為灰度圖,當然也可以在讀取的時候就直接以灰度格式讀入,直接以灰度讀入會不會更快些呢?

error:

stray ‘\357’ in program

查了一下,357是代表在UTF8編碼的文件中插入了中文的標點符號,檢查了一下果然有個逗號寫成了中文的。

threshold:

threshold的中文意思是門檻(n),臨界的(adj)。這個函式的作用就是將灰度影象的灰度設定為0或255,使得影象凸顯出黑白的效果,凸顯出影象輪廓同時使資料量大大減少。函式定義:

double cv::threshold(InputArray Src,
                     OutputArray dst,
                     double thresh,
                     double Maxval,
                     int type,
                    )

第一個引數是輸入影象,

第二個引數是輸出影象,

第三個引數是閾值(thresh),

第四個引數是dst的最大值,

bug:我用一個char型變數存放閾值,結果不論怎麼樣設定閾值,影象都全白。折騰了半天,終於認識到自己的錯誤,太久沒有調程式了,連char型變數的範圍都忘了是-128~127。改成unsigned或者int就好。

getStructuringElement:

這個函式用於生成形態處理的核,定義如下:

getStructuringElement( int shape,//核的形狀:0,十矩形;1,十字交叉形;3,橢圓形
                       Size ksize,//核的大小     
                       Point anchor=Point(-1,-1)//核中心位置,預設位於影象中心處
                     )

這個核其實就是一個矩陣:

3*3的矩形矩陣
[1,1,1
 1,1,1
 1,1,1]
3*3的十字叉形矩陣
[0,1,0
 1,1,1
 0,1,0]
3*3的橢圓形矩陣
[0,1,0
 1,1,1
 1,1,1
 1,1,1
 0,1,0]

這個函式的返回值就是相應的形態學矩陣,需要用一個矩陣來儲存,然後用於形態學處理。

morphologyEx():

這個函式是形態學變化函式,功能十分強大:

morphologyEx(InputArrary src, 
             OutputArray dst, 
             int op,
             InputArray kernel,
             Point anchor=Point(-1,-1),
             intiterations= 1,
             int borderType= BORDER_CONSTANT,
             const Scalar&borderValue=morphologyDefaultBorderValue()
             )

第三個引數,結構元素,表示形態學運算的型別:1.開運算:MORPH_OPEN;2.閉運算:MPRPH_CLOSE;3.形態梯度:MORPH_GRADIENT;4.“頂帽”:MORPH_TOPHAT(原影象與開影象之差);5.“黑帽”:MORPH_BLACKHAT(閉影象與原影象之差)

第四個引數anchor:結構元素的原點

第五個引數iterations:迭代的次數

我經過處理之後的照片如下圖: