1. 程式人生 > >OpenCV3基礎——幾種基本的影象處理

OpenCV3基礎——幾種基本的影象處理

雖然單單要做車牌號識別的話不需要特別多種類的影象處理,但是我們不能只是為了這麼一個目標去學習,所以這次就講一些OpenCV裡基本的影象處理,大家以後可以根據需求使用不同的影象處理。

一、影象顯示

這一步在上次的部落格裡面已經出現過了,但是保證這次部落格的完整性,所以就再來一遍。

【開啟Visual Studio】→【新建專案】→【Win32控制檯應用專案(修改名稱後點確定)】→【下一步】→【空專案(勾起來以後點選確認)】【解決方案資源管理器】→【原始檔】→【新建項】→【新增】→【(修改名稱後點擊確定)】

(後面的程式都是以這個操作開頭的,而我為了方便所以就在一個原始檔裡進行修改了)

我這次的路徑是D:\University\New\Test2\Test2

#include<opencv2\opencv.hpp>
using namespace cv; //包含cv名稱空間

void main(){
	Mat img = imread("1.jpg"); //載入圖片
	imshow("【原始圖】", img); //顯示影象
	waitKey(0); //等待任意按鍵按下
}

此處的1.jpg是放在了上面那個路徑裡面,出現的效果圖:


當然,其實也可以顯示不在該資料夾裡的圖片,只需要將“1.jpg”改成你想要顯示的圖片所在的路徑即可,例如我在D盤存了個2.jpg,我想要顯示它,就只需將程式碼改成Mat img=imread("D://2.jpg");就可以了。

為了和上次的有些區別,我們來稍微講一下程式碼中的一些語句的含義。

1、OpenCV的名稱空間

      OpenCV中的C++類和函式都是定義在名稱空間cv之內的,有兩種方法可以訪問:第一種,是在程式碼開頭的適當位置加上using namespace cv;這句程式碼,規定程式位於此名稱空間之內;另外一種,是在使用OpenCV的每一個類和函式時,都加入cv::名稱空間。不用講都知道,第二種方法十分的繁瑣,所以,推薦大家在程式碼開頭的適當位置,加上using namespace cv;這句。

2、Mat類簡析

       Mat類是用於儲存影象以及其他矩陣資料的資料結構,預設情況下其尺寸為0。我們也可以指定其初始尺寸,比如定義一個Mat類物件,就要寫cv::Mat pic(320,640,cv::Scalar(100));,Mat類是OpenCV裡十分重要,內容有很多,我們這裡需要用到的關於Mat的其實就是簡單的這樣一句程式碼:Mat img=imread("1.jpg");,所以我就不在多講了。

3、影象的載入:imread()函式

       imread()函式是用於讀取檔案中的圖片到OpenCV中。可以在OpenCV官方文件中查到它的原形,如下:

       Mat imread(const string& filename, intflags=1);

       第一個引數,const string&型別的filename,填我們需要載入的圖片路徑名,在Windows作業系統下,OpenCV的imread函式支援如下型別的影象載入。


       第二個引數,int型別的flags,為載入標識,他指定一個載入影象的顏色型別【這個內容有些生澀難理解,故不多贅述】。

4、imshow()函式

      imshow()函式用於在指定的視窗中顯示一幅影象,函式原型如下。

      void imshow(const string& winname, InputArray mat);

      第一個引數,const string&型別的winname,填需要顯示的視窗標識名稱。

      第二個引數,InputArray型別的mat,填需要顯示的影象。【很多時候,遇到函式原型中的InputArray/OutputArray型別,我們把它簡單地當做Mat型別即可。因為它的定義有些難理解,而且原始碼略顯冗長,所以不過多贅述】

二、影象腐蝕和膨脹

      腐蝕,即用影象中的暗色部分“腐蝕”掉影象中的高亮部分。程式碼如下:

#include<opencv2\highgui\highgui.hpp> //OpenCV highgui模組標頭檔案
#include<opencv2\imgproc\imgproc.hpp> //OpenCV 影象處理標頭檔案
using namespace cv; //包含cv名稱空間

int main(){
	//載入圖片
	Mat img = imread("1.jpg");
	//顯示原圖
	imshow("【原圖】腐蝕操作", img);
	//進行腐蝕操作
	Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
	Mat dstimg;
	erode(img, dstimg, element);
	//顯示效果圖
	imshow("【效果圖】腐蝕操作", dstimg);
	waitKey(0);
	return 0;
}

程式首先依然是載入和顯示一幅影象,然後定義一個Mat型別的變數來獲得getStructuringElement函式的返回值,而getStructuringElement函式的返回值為指定形狀和尺寸的結構元素(核心矩陣)。引數準備完畢,接著便可以呼叫erode函式進行影象腐蝕操作,然後呼叫imshow函式進行顯示。

下面對getStructuringElement函式進行簡單的講述:

第一個引數,核心的形狀(一般有下面三種:矩形:MORPH_RECT;交叉形:MORPH_CROSS;橢圓形:MORPH_ELLIPSE)

第二個引數,核心的大小(上面的程式碼,表示的就是15*15的正方形核心)

效果圖如下(原圖都和一中的原圖一樣,故不再顯示):


膨脹,和腐蝕相反,從影象直觀來看,就是將影象光亮部分放大,黑暗部分縮小。程式碼如下:

#include<opencv2\highgui\highgui.hpp> //OpenCV highgui模組標頭檔案
#include<opencv2\imgproc\imgproc.hpp> //OpenCV 影象處理標頭檔案
using namespace cv; //包含cv名稱空間

int main(){
	//載入圖片
	Mat img = imread("1.jpg");
	//顯示原圖
	imshow("【原圖】膨脹操作", img);
	//進行膨脹操作
	Mat element = getStructuringElement(MORPH_RECT, Size(15, 15));
	Mat dstimg;
	dilate(img, dstimg, element);
	//顯示效果圖
	imshow("【效果圖】膨脹操作", dstimg);
	waitKey(0);
	return 0;
}

和腐蝕的程式碼的區別就只在於呼叫的函式不同,膨脹呼叫的是dilate函式。

效果圖如下:


三、影象模糊

模糊,對影象進行均值濾波處理,然後就把影象模糊了……程式碼如下:

#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
using namespace cv;

int main(){
	//載入原圖
	Mat img = imread("1.jpg");
	//顯示原圖
	imshow("【原圖】均值濾波", img);
	//進行均值濾波操作
	Mat dstimg;
	blur(img, dstimg, Size(7, 7));
	//顯示效果圖
	imshow("【效果圖】均值濾波", dstimg);
	waitKey(0);
	return 0;
}

blur函式的第三個引數表示的是核心的大小,程式碼中的意思是畫素長寬均為7的一個核心。

效果圖如下:


四、canny邊緣檢測

這個操作會在我們最終要實現的汽車車牌識別中會出現。

載入影象,並將其轉成灰度圖,再用blur函式進行影象模糊以降噪,然後用canny函式進行邊緣檢測,最後進行顯示。程式碼如下:

#include<opencv2\highgui\highgui.hpp>
#include<opencv2\imgproc\imgproc.hpp>
using namespace cv;

int main(){
	//載入原圖
	Mat srcImage = imread("1.jpg");
	//顯示原圖
	imshow("【原圖】Canny邊緣檢測", srcImage);
	Mat dstImage, edge, grayImage;
	//【1】創建於src同類型和大小的矩陣dst
	dstImage.create(srcImage.size(), srcImage.type());
	//【2】將原影象轉換成灰度影象
	cvtColor(srcImage, grayImage, COLOR_BGR2GRAY);
	//【3】先使用3*3核心來降噪
	blur(grayImage, edge, Size(3, 3));
	//【4】執行Canny運算元
	Canny(edge, edge, 3, 9, 3);
	//顯示效果圖
	imshow("【效果圖】Canny邊緣檢測", edge);
	waitKey(0);
	return 0;
}

簡單講一下Canny函式各引數的意義:

第一個引數:輸入,是灰度圖,就算是彩色圖也會處理成灰度圖(但是如果不先轉成灰度影象並降噪的話會出現很多原本不存在的線條,大家可以自己嘗試一下)

      第二個引數:輸出的圖的位置,輸出的圖是二值圖。

      第三四個引數:是兩個閾值,上限和下限,如果一個畫素的梯度大於上限,則被認為是邊緣畫素,如果低於下限則被拋棄,如果介於兩者之間,只有當其與高於上限閾值的畫素連線時才會被接受。

      第五個引數:表示模板的大小,如果是3,則表示3*3矩陣的大小。

效果圖如下:

原本還想弄個小小的人臉識別的彩蛋的,但是弄完這篇我就已經快癱了,所以就留到下次吧。