詳解OpenCV圖像的概念和基本操作
前言:
opencv最主要的的功能是用於圖像處理,所以圖像的概念貫穿瞭整個opencv,與其相關的核心類就是Mat。
像素:
圖片尺寸以像素為單位時,每一厘米等於28像素,如1515厘米長度的圖片,等於420420像素的長度。一個像素所能表達的不同顏色數取決於比特每像素(BPP)。
灰度圖像:8bpp=2的8次方=256色,
高彩色:16bpp=2的16次方=65536色,
真彩色:24bpps=2的24次方=16777216色。
圖像分辨率:
圖像分辨率是圖像總像素的多少,由於圖像通常用矩陣表示,所以分辨率常用,mn表示,註意: n 表示行數(代表一列包含的像素),m表示列數代表一行包含的像素。
640X480表示圖像的長和寬分別為640和480,總像素為640X480=307200(相機中所說的30萬分辨率),
800X600表示圖像的長和寬分別為800和600,總像素為800X600=480000(相機中所說的50萬分辨率)。
圖像和矩陣
圖像是由像素組成的,而像素實際上就是帶有坐標位置和顏色信息的點。我們把圖片想象成由若幹行,若幹列的點組成的, 現實中有RGB顏色系統,我們可以把圖中任意一點(位置在第m行,第n列)的點A表示為
A[m,n] = [blue,green,red]
參數解讀
m |A點在圖像中的第m行
n |A點在圖像中的第n列
blue |表示藍色,三原色(RGB)的第一個數值
green|表示綠色,三原色(RGB)的第二個數值
red |表示紅色,三原色(RGB)的第一個數值
每個點對應的亮度可以理解為rgb的值,無符號8位數3維,則一個像素點為3維數組,分別對應RGB的值,在OpenCV中數據類型為:cV_8u3C。
假設Mx N,lij表示第j行j列,對應上圖就是M= 300,N= 200。
假設Mx N,lij表示第j行j列,對應上圖就是M= 300,N= 200。
註意:在Opencv中三維數組存儲RGB值,存儲顏色通道的順序不是RGB,而是BGR,如下圖:
Mat排列方式如下:
像素值的讀寫
很多時候,我們需要讀取某個像素值,或者設置某個像素值;在更多的時候,我們需要對整個圖像裡的所有像素進行遍歷。OpenCV提供瞭多種方法來實現圖像的遍歷。
方法一:at 函數
cv::Mat grayim(600, 800, CV_8UC1); // 遍歷所有像素,並設置像素值 for( int i = 0; i < grayim.rows; ++i) { for( int j = 0; j < grayim.cols; ++j ) { grayim.at<uchar>(i,j) = (i+j)%255; } } imshow("grayim",grayim); cv::Mat colorim(600, 800, CV_8UC3); // 遍歷所有像素,並設置像素值 for( int i = 0; i < colorim.rows; ++i) { for( int j = 0; j < colorim.cols; ++j ) { cv::Vec3b pixel; // 註意:opencv通道順序,BGR,非RGB pixel[0] = i%255; // Blue pixel[1] = j%255; // Green pixel[2] = 0; // Red colorim.at<Vec3b>(i,j) = pixel; } } imshow("colorim",colorim); waitKey();
方法一:使用數據指針
cv::Mat grayim(600, 800, CV_8UC1); cv::Mat colorim(600, 800, CV_8UC3); //遍歷所有像素,並設置像素值 for( int i = 0; i < grayim.rows; ++i) { //獲取第 i 行首像素指針 uchar * p = grayim.ptr<uchar>(i); //對第 i 行的每個像素(byte)操作 for( int j = 0; j < grayim.cols; ++j ) p[j] = (i+j)%255; } //遍歷所有像素,並設置像素值 for( int i = 0; i < colorim.rows; ++i) { //獲取第 i 行首像素指針 cv::Vec3b * p = colorim.ptr<cv::Vec3b>(i); for( int j = 0; j < colorim.cols; ++j ) { p[j][0] = i%255; //Blue p[j][1] = j%255; //Green p[j][2] = 0; //Red } } imshow("grayim",grayim); imshow("colorim",colorim);
實驗效果
圖像局部操作
選擇單行/單列
示例:A矩陣的第i行,將這一行的所有元素都乘以2,然後賦值給第j行
A.row(j)= A.row(i)*2;
選擇多行/多列
Range是OpencV中新增的類,該類有兩個關鍵變量star和end。Range對象可以用來表示矩陣的多個連續的行或者多個連續的列。其表示的范圍為從start到end,包含start。
// 創建一個單位陣 Mat A = Mat::eye(10, 10, CV_32S); // 提取第 1 到 3 列(不包括 3) Mat B = A(Range::all(), Range(1, 3)); // 提取B的第 5 至 9 行(不包括 9) // 其實等價於C = A(Range(5, 9), Range(1, 3)) Mat C = B(Range(5, 9), Range::all());
選擇指定區域
圖像中提取感興趣區域(Region of interest)有兩種方法:
方法—:使用構造函數
//創建寬度為 320,高度為 240 的 3 通道圖像 Mat img(Size(320, 240), CV_8UC3); //roi 是表示 img 中 Rect(10, 10, 100, 100)區域的對象 Mat roi(img, Rect(10, 10, 100, 100));
方法二:使用括號運算符
Mat roi2 = img(Rect(10, 10, 100, 100)); //當然也可以使用Range對象來定義感興趣區域,如下: // 用括號運算符 Mat roi3 = img(Range(10, 100), Range(10, 100)); // 用構造函數 Mat roi4(img, Range(10, 100), Range(10, 100));
取對角線元素
矩陣的對角線元素可以使用cv::Mat就的diag()函數獲取:
Mat Mat::diag(int d) const
1.當d=0時,表示取主對角線; 當參數d>0是,表示取主對角線下方的次對線,
2. 當d=1時,表示取主對角線下方,且緊貼主多角線的元素;
3. 當參數d<0時,示取主對角線上方的次對角線。如同row()和col)函數,diag()函數也不進行內存復制操作,其復雜度也是0(1)。
到此這篇關於OpenCV圖像的概念和基本操作的文章就介紹到這瞭,更多相關OpenCV圖像基本操作內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- C++ opencv圖像處理實現灰度變換示例
- C++ Opencv自寫函數實現膨脹腐蝕處理技巧
- OpenCV-Python實現懷舊濾鏡與連環畫濾鏡
- OpenCV實戰之AI照片背景替換
- openCV實現圖像分割