版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
OpenCV的基本數(shù)據(jù)類(lèi)型
OpenCV提供了多種基本數(shù)據(jù)類(lèi)型。雖然這些數(shù)據(jù)類(lèi)型在C語(yǔ)言中不是基本類(lèi)型,但結(jié)構(gòu)都
很簡(jiǎn)單,可將它們作為原子類(lèi)型??梢栽凇啊?OpenCV/cxcore/include”目錄下的extypes.h文
件中查看其詳細(xì)定義。
在這些數(shù)據(jù)類(lèi)型中最簡(jiǎn)單的就是CvPointoCvPoint是一個(gè)包含integer類(lèi)型成員x和y的簡(jiǎn)
單結(jié)構(gòu)體。CvPoint有兩個(gè)變體類(lèi)型:CvPoint2D32f和CvPoint3D32f。前者同樣有兩個(gè)成員
x,y,但它們是浮點(diǎn)類(lèi)型;而后者卻多了一個(gè)浮點(diǎn)類(lèi)型的成員z。
CvSize類(lèi)型與CvPoint非常相似,但它的數(shù)據(jù)成員是integer類(lèi)型的widthfllheighto如果希
望使用浮點(diǎn)類(lèi)型,則選用CvSize的變體類(lèi)型CvSize2D32fo
CvRect類(lèi)型派生于CvPoint和CvSize,它包含4個(gè)數(shù)據(jù)成員:x,y,width和height。(正如
你所想的那樣,該類(lèi)型是一個(gè)復(fù)合類(lèi)型)。
下一個(gè)(但不是最后一個(gè))是包含4個(gè)整型成員的CvScalar類(lèi)型,當(dāng)內(nèi)存不是問(wèn)題時(shí):CvScal
ar經(jīng)常用來(lái)代替1.2或者3個(gè)實(shí)數(shù)成員(在這個(gè)情況下,不需要的分量被忽略)。CvScalar
有一個(gè)單獨(dú)的成員val,它是一個(gè)指向4個(gè)雙精度浮點(diǎn)數(shù)數(shù)組的指針。
所有這些數(shù)據(jù)類(lèi)型具有以其名稱(chēng)來(lái)定義的構(gòu)造函數(shù),例如cvSize。。(構(gòu)造函數(shù)通常具有與結(jié)
構(gòu)類(lèi)型一樣的名稱(chēng),只是首字母不大寫(xiě))。記住,這是C而不是C++,所以這些構(gòu)造函數(shù)只
是內(nèi)聯(lián)函數(shù),它們首先提取參數(shù)列表,然后返回被賦予相關(guān)值的結(jié)
構(gòu)?!?1】
各數(shù)據(jù)類(lèi)型的內(nèi)聯(lián)構(gòu)造函數(shù)被列在表3-1中:cvPointXXX(),cvSize(),cvRect()和cvScalar。。
這些結(jié)構(gòu)都十分有用,因?yàn)樗鼈儾粌H使代碼更容易編寫(xiě),而且也更易于閱讀。假設(shè)要在(5,
10)和(20,30)之間畫(huà)一個(gè)白色矩形,只需簡(jiǎn)單調(diào)用:
cvRectangle(
mylmg,
cvPoint(5,10),
cvPoint(20,30),
cvScalar(255,255,255)
);
表3-1:points,size,rectangles和calar三元組的結(jié)構(gòu)
結(jié)構(gòu)成員意義
CvPointintx,y圖像中的點(diǎn)
CvP0int2D32ffloatx,y二維空間中的點(diǎn)
CvP0int3D32ffloatx,y,z三維空間中的點(diǎn)
CvSizeintwidth,height圖像的尺寸
CvRectintx,y,width,height圖像的部分區(qū)域
OvScalardoubleval[4]RGBA值
cvScalar是一個(gè)特殊的例子:它有3個(gè)構(gòu)造函數(shù)。第一個(gè)是cvScalaK),它需要一個(gè)、兩個(gè)、
三個(gè)或者四個(gè)參數(shù)并將這些參數(shù)傳遞給數(shù)組val[]中的相應(yīng)元素。第二個(gè)構(gòu)造函數(shù)是cvReal
Scalar(),它需要?個(gè)參數(shù),它被傳遞給給val[0],而val[]數(shù)組別的值被賦為0。最后一個(gè)有
所變化的是cvScalarAll。,它需要一個(gè)參數(shù)并且val口中的4個(gè)元素都會(huì)設(shè)置為這個(gè)參數(shù)。
矩陣和圖像類(lèi)型
圖3-1為我們展示了三種圖像的類(lèi)或結(jié)構(gòu)層次結(jié)構(gòu)。使用OpenCV時(shí),會(huì)頻繁遇到Ipllmage
數(shù)據(jù)類(lèi)型,第2章已經(jīng)出現(xiàn)多次。Ipllmage是我們用來(lái)為通常所說(shuō)的“圖像”進(jìn)行編碼的基本
結(jié)構(gòu)。這些圖像可能是灰度,彩色,4通道的(RGB+alpha),其中每個(gè)通道可以包含任意的
整數(shù)或浮點(diǎn)數(shù)。因此,該類(lèi)型比常見(jiàn)的、易于理解的3通道8位RGB圖像更通用。
OpenCV提供了大量實(shí)用的圖像操作符,包括縮放圖像,單通道提取,找出特定通道最大最
小值,兩個(gè)圖像求和,對(duì)圖像進(jìn)行閾值操作,等等。本章我們將仔細(xì)介紹這類(lèi)操
圖3-1:雖然OpenCV是由C語(yǔ)言實(shí)現(xiàn)的,但它使用的結(jié)構(gòu)體也是遵循面向?qū)ο蟮乃枷朐O(shè)計(jì)
的。實(shí)際上,Ipllmage由CvMat派生,而O/Mat由CvArr派生
在開(kāi)始探討圖像細(xì)節(jié)之前,我們需要先了解另?種數(shù)據(jù)類(lèi)型CvMat,OpenCV的矩陣結(jié)構(gòu)。
雖然OpenCV完全由C語(yǔ)言實(shí)現(xiàn),但CvMat和Ipllmage之間的關(guān)系就如同C++中的繼承關(guān)
系。實(shí)質(zhì)上,Ipllmage可以被視為從CvMat中派生的。因此,在試圖了解復(fù)雜的派生類(lèi)之
前,最好先了解基本的類(lèi)。第三個(gè)類(lèi)CvArr,可以被視為一個(gè)抽象基類(lèi),CvMat由它派生。
在函數(shù)原型中,會(huì)經(jīng)??吹紺vArr(更準(zhǔn)確地說(shuō),CvArr*),當(dāng)它出現(xiàn)時(shí),便可以將CvMat*
或Ipllmage*傳遞到程序。
CvMat矩陣結(jié)構(gòu)
在開(kāi)始學(xué)習(xí)矩陣的相關(guān)內(nèi)容之前,我們需要知道兩件事情。第一,在OpenCV中沒(méi)有向量(v
ector)結(jié)構(gòu)。任何時(shí)候需要向量,都只需要一個(gè)列矩陣(如果需要一個(gè)轉(zhuǎn)置或者共施向量,則
需要?個(gè)行矩陣)。第二,OpenCV矩陣的概念與我們?cè)诰€(xiàn)性代數(shù)課上學(xué)習(xí)的概念相比,更
抽象,尤其是矩陣的元素,并非只能取簡(jiǎn)單的數(shù)值類(lèi)型。例如,-個(gè)用于新建一個(gè)二維矩陣
的例程具有以下原型:
cvMat*cvCreateMat(introws,intcols,inttype);
這里type可以是任何預(yù)定義類(lèi)型,預(yù)定義類(lèi)型的結(jié)構(gòu)如下:CV_<bit_depth>(SIUIF)Ccnumb
er_of_channels>o于是,矩陣的元素可以是32位浮點(diǎn)型數(shù)據(jù)(CV_32FC1),或者是無(wú)符號(hào)的
8位三元組的整型數(shù)據(jù)(CV_8UC3),或者是無(wú)數(shù)的其他類(lèi)型的元素。一個(gè)CvMat的元素不?
定就是個(gè)單一的數(shù)字。在矩陣中可以通過(guò)單一(簡(jiǎn)單)的輸入來(lái)表示多值,這樣我們可以在一
個(gè)三原色圖像上描繪多重色彩通道。對(duì)于一個(gè)包含RGB通道的簡(jiǎn)單圖像,大多數(shù)的圖像操
作將分別應(yīng)用于每一個(gè)通道(除非另有說(shuō)明)。
實(shí)質(zhì)上,正如例3-1所示,CvMat的結(jié)構(gòu)相當(dāng)簡(jiǎn)單,(可以自己打開(kāi)文件…/ope〃cM、xc"e/i〃c
lude/cxtypes.h查看)。矩陣由寬度(width)、高度(height)、類(lèi)型(type)、行數(shù)據(jù)長(zhǎng)度(step,行的
氏度用字節(jié)表示而不是整型或者浮點(diǎn)型長(zhǎng)度)和一個(gè)指向數(shù)據(jù)的指針構(gòu)成(現(xiàn)在我們還不能
討論更多的東西)??梢酝ㄟ^(guò)一個(gè)指向CvMat的指針訪(fǎng)問(wèn)這些成員,或者對(duì)于一些普通元素,
使用現(xiàn)成的訪(fǎng)問(wèn)方法。例如,為了獲得矩陣的大小,可通過(guò)調(diào)用函數(shù)vGetSize(CvMat*),返
回一個(gè)CvSize結(jié)構(gòu),便可以獲取任何所需信息,或者通過(guò)獨(dú)立訪(fǎng)問(wèn)高度和寬度,結(jié)構(gòu)為ma
trix->height和matrix->width?!?3?34】
例3-1:Q/Mat結(jié)構(gòu):矩陣頭
typedefstructCvMat{
inttype;
intstep;
int*refcount;//forinternaluseonly
union{
uchar*ptr;
short*s;
int*i;
float*fl;
double*db;
}data;
union{
introws;
intheight;
);
union{
intcols;
intwidth;
);
}CvMat;
此類(lèi)信息通常被稱(chēng)作矩陣頭。很多程序是區(qū)分矩陣頭和數(shù)據(jù)體的,后者是各個(gè)data成員所
指向的內(nèi)存位置。
矩陣有多種創(chuàng)建方法。最常見(jiàn)的方法是用cvCreateMat。,它由多個(gè)原函數(shù)組成,如cvCreat
eMatHeader()^ncvCreateData()ocvCreateMatHeader()函數(shù)創(chuàng)建CvMat結(jié)構(gòu),不為數(shù)據(jù)分配內(nèi)
存,而cvCreateData。函數(shù)只負(fù)責(zé)數(shù)據(jù)的內(nèi)存分配。有時(shí),只需要函數(shù)cvCreateMatHeader(),
因?yàn)橐岩蚱渌碛煞峙淞舜鎯?chǔ)空間,或因?yàn)檫€不準(zhǔn)備分配存儲(chǔ)空間。第三種方法是用函數(shù)c
vCloneMat(CvMat*),它依據(jù)一個(gè)現(xiàn)有矩陣創(chuàng)建一個(gè)新的矩陣。當(dāng)這個(gè)矩陣不再需耍時(shí),可
以調(diào)用函數(shù)cvReleaseMat(CvMat*)釋放它。【34】
例3-2概述了這些函數(shù)及其密切相關(guān)的其他函數(shù)。
例3-2:矩陣的創(chuàng)建和釋放
//Createanewrowsbycolsmatrixoftype'type'.
//
Q/Mat*cvCreateMat(introws,intcols,inttype);
//Createonlymatrixheaderwithoutallocatingdata
//
OMat*cvCreateMatHeader(introws,intcols,inttype);
//InitializeheaderonexistiongCvMatstructure
//
Q/Mat*cvlnitMatHeader(
CvMat*mat,
introws,
intcols,
inttype,
void*data=NULL,
intstep=CV_AUTOSTEP
);
//LikecvlnitMatHeader()butallocatesCvMataswell.
//
Q/MatcvMat(
introws,
int(x)ls,
inttype,
void*data=NULL
);
//Allocateanewmatrixjustlikethematrix'mat'.
//
Q/Mat*cvQoneMat(constcvMat*mat);
//Freethematrix'mat',bothheaderanddata.
//
voidcvReleaseMat(Q/Mat**mat);
與很多OpenCV結(jié)構(gòu)類(lèi)似,有…種構(gòu)造函數(shù)叫cvMat,它可以創(chuàng)建CvMat結(jié)構(gòu),但實(shí)際h
不分配存儲(chǔ)空間,僅創(chuàng)建頭結(jié)構(gòu)(與cvInilMatHeader。類(lèi)似)。這些方法對(duì)于存取到處散放的
數(shù)據(jù)很有作用,可以將矩陣頭指向這些數(shù)據(jù),實(shí)現(xiàn)對(duì)這些數(shù)據(jù)的打包,并用操作矩陣的函數(shù)
去處理這些數(shù)據(jù),如例3-3所示。
例3-3:用固定數(shù)據(jù)創(chuàng)建一個(gè)OpenCV矩陣
//CreateanOpenCVMatrixcontainingsomefixeddata.
//
floatvals[]={0.866025,-0.500000,0.500000,0.866025};
Q/Matrotmat;
cvlnitMatHeader(
&rotmat,
2,
2,
CV_32FC1,
vals
);
一旦我們創(chuàng)建了一個(gè)矩陣,便可用它來(lái)完成很多事情。最簡(jiǎn)單的操作就是查詢(xún)數(shù)組定義和數(shù)
據(jù)訪(fǎng)問(wèn)等。為查詢(xún)矩陣,我們可以使用函數(shù)cvGetElemType(constCvArr*arr).cvGetDims(c
onstCvArr*arr,int*sizes=NULL)和cvGet-DimSize(constCvArr*arr,intindex)?第一個(gè)
返回一個(gè)整型常數(shù),表示存儲(chǔ)在數(shù)組里的元素類(lèi)型(它可以為CV_8UC1和CV_64FC4等類(lèi)
型)。第二個(gè)取出數(shù)組以及一個(gè)可選擇的整型指針,它返回維數(shù)(我們當(dāng)前的實(shí)例是二維,但
是在后面我們將遇到的N維矩陣對(duì)象)。如果整型指針不為空,它將存儲(chǔ)對(duì)應(yīng)數(shù)組的高度和
寬度(或者N維數(shù))。最后的函數(shù)通過(guò)一個(gè)指示維數(shù)的整型數(shù)簡(jiǎn)單地返回矩陣在那個(gè)維數(shù)上矩
陣的大小?!?5?36]
矩陣數(shù)據(jù)的存取
訪(fǎng)問(wèn)矩陣中的數(shù)據(jù)有3種方法:簡(jiǎn)單的方法、麻煩的方法和恰當(dāng)?shù)姆椒ā?/p>
簡(jiǎn)單的方法
從矩陣中得到?個(gè)元素的最簡(jiǎn)單的方法是利用宏CV_MAT_ELEM()?這個(gè)宏(參
見(jiàn)例3-4)傳入矩陣、待提取的元素的類(lèi)型、行和列數(shù)4個(gè)參數(shù),返回提
取出的元素的值。
例3-4:利用CV_MAT_ELEM()宏存取矩陣
Q/Mat*mat=cvCreateMat(5,5,CV_32FC1);
floatelement_3_2=CV_MAT_ELEM(*mat,float,3,2);
更進(jìn)?步,還有一個(gè)與此宏類(lèi)似的宏,叫CV_MAT_ELEM_PTR()。CV_MAT_ELEM_PTR()
(參見(jiàn)例3-5)傳入矩陣、待返回元素的行和列號(hào)這3個(gè)參數(shù),返回指向這個(gè)元素的指針。該
宏和CV_MAT_ELEM()宏的最重要的區(qū)別是后者在指針解引用之前將其轉(zhuǎn)化成指定的類(lèi)型。
如果需要同時(shí)讀取數(shù)據(jù)和設(shè)置數(shù)據(jù),可以直接調(diào)用CV_MAT_ELEM_PTR(),但在這種情況
下,必須自己將指針轉(zhuǎn)化成恰當(dāng)?shù)念?lèi)型。
例3-5:利用宏CV_MAT_ELEM_FTR()為矩陣設(shè)置一個(gè)數(shù)值
Q/Mat*mat=cvCreateMat(5,5,CV_32FC1);
floatelement_3_2=7.7;
*((float*)CV_MAT_ELEM_PTR(*mat,3,2))=element_3_2;
[36]
遺撼的是,這些宏在每次調(diào)用的時(shí)候都重新計(jì)算指針。這意味著要查找指向矩陣基本元素?cái)?shù)
據(jù)區(qū)的指針、計(jì)算目標(biāo)數(shù)據(jù)在矩陣中的相對(duì)地址,然后將相對(duì)位置與基本位置相加。所以,
即使這些宏容易使用,但也不是存取矩陣的最佳方法。在計(jì)劃順序訪(fǎng)問(wèn)矩陣中的所有元素時(shí),
這種方法的缺點(diǎn)尤為突出。下面我們將講述怎么運(yùn)用最好的方法完成這個(gè)重要任務(wù)。
麻煩的方法
在“簡(jiǎn)單的方法”中討論的兩個(gè)宏僅僅適用于訪(fǎng)問(wèn)1維或2維的數(shù)組(回憶一下,I維的數(shù)組,
或者稱(chēng)為“向量”實(shí)際只是一個(gè)"X1維矩陣)。OpenCV提供了處理多維數(shù)組的機(jī)制。事實(shí)上,
OpenCV可以支持普通的N維的數(shù)組,這個(gè)N值可以取值為任意大的數(shù)。
為了訪(fǎng)問(wèn)普通矩陣中的數(shù)據(jù),我們可以利用在例3-6和例3-7中列舉的cvPtr*D和cvGet*D…
等函數(shù)族。cvPtr*D家族包括cvPtrlDO,cvPtr2D(),cvPtr3D()和cvPtrND?!?。這三個(gè)函數(shù)都
可接收CvArr*類(lèi)型的矩陣指針參數(shù),緊隨其后的參數(shù)是表示索引的整數(shù)值,最后是一個(gè)可
選的參數(shù),它表示輸出值的類(lèi)型。函數(shù)返回一個(gè)指向所需元素的指針。對(duì)于cvPtrND()來(lái)說(shuō),
第二個(gè)參數(shù)是一個(gè)指向一個(gè)整型數(shù)組的指針,這個(gè)數(shù)組中包含索引的合適數(shù)字。后文會(huì)再次
介紹此函數(shù)(在這之后的原型中,也會(huì)看到一些可選參數(shù),必要時(shí)會(huì)有講解)。
例3-6:指針訪(fǎng)問(wèn)矩陣結(jié)構(gòu)
uchar*cvPtr1D(
constCvArr*arr,
intidxO,
int*type=NULL
);
uchar*cvPtr2D(
constCvArr*arr,
intidxO,
intidx1,
int*type=NULL
);
uchar*cvPtr3D(
constCvArr*arr,
intidxO,
intidx1,
intidx2,
int*type=NULL
);
uchar*cvPtrND(
constCvArr*arr,
int*idx,
int*type=NULL,
intcreate_node=1,
unsigned*precalc_hashval=NULL
);[37?38]
如果僅僅是讀取數(shù)據(jù),可用另一個(gè)函數(shù)族cvGet*D。如例3?7所示,該例與例3?6類(lèi)似,但
是返回矩陣元素的實(shí)際值。
例3-7:Q/Mat和IPIImage元素函數(shù)
doublecvGetReal1D(constQ/Arr*arr,intidxO);
doublecvGetReal2D(constQ/Arr*arr,intidxO,intidx1);
doublecvGetReal3D(constQ/Arr*arr,intidxO,intidx1,intidx2);
doublecvGetRealND(constCvArr*arr,int*idx);
Q/ScalarcvGet1D(constQ/Arr*arr,intidxO);
Q/ScalarcvGet2D(constOArr*arr,intidxO,intidx1);
Q/ScalarcvGet3D(constCX/Arr*arr,intidxO,intidx1,intidx2);
Q/ScalarcvGetND(constCvArr*arr,int*idx);
cvGet*D中有四個(gè)函數(shù)返回的是整型的,另外四個(gè)的返回值是CvScalar類(lèi)型的。這意味著在
使用這些函數(shù)的時(shí)候,會(huì)有很大的空間浪費(fèi)。所以,只是在你認(rèn)為用這些函數(shù)比較方便和高
效率的時(shí)候才用它們,否則,最好用cvPtr*D。
用cvPtr*D()函數(shù)族還有另外一個(gè)原因,即可以用這些指針函數(shù)訪(fǎng)問(wèn)矩陣中的特定的點(diǎn),然
后由這個(gè)點(diǎn)出發(fā),用指針的算術(shù)運(yùn)算得到指向矩陣中的其他數(shù)據(jù)的指針。在多通道的矩陣中,
務(wù)必記住一點(diǎn):通道是連續(xù)的,例如,在一個(gè)3通道2維的表示紅、綠、藍(lán)(RGB)矩陣中。
矩陣數(shù)據(jù)如下存儲(chǔ)rgbrgbrgb.一。所以,要將指向該數(shù)據(jù)類(lèi)型的指針移動(dòng)到下一通道,我
們只需要將其增加1。如果想訪(fǎng)問(wèn)下一個(gè)“像素”或者元素集,我們只需要增加一定的偏移量,
使其與通道數(shù)相等。
另一個(gè)需要知道的技巧是矩陣數(shù)組的step元素(參見(jiàn)例3-1和例3-3),step是矩陣中行的長(zhǎng)
度,單位為字節(jié)。在那些結(jié)構(gòu)中,僅靠cols或width是無(wú)法在矩陣的不同行之間移動(dòng)指針的,
出于效率的考慮,矩陣或圖像的內(nèi)存分配都是4字節(jié)的整數(shù)倍。所以,三個(gè)字節(jié)寬度的矩陣
將被分配4個(gè)字節(jié),最后一個(gè)字節(jié)被忽略。因此,如果我們得到一個(gè)字節(jié)指針,該指針指向
數(shù)據(jù)元素,那么我們可以用step和這個(gè)指針相加以使指針指向正好在我們的點(diǎn)的下一行元
素。如果我們有?個(gè)整型或者浮點(diǎn)型的矩陣,對(duì)應(yīng)的有整型和浮點(diǎn)型的指針指向數(shù)據(jù)區(qū)域,
我們將讓step/4與指針相加來(lái)移到下一行,對(duì)雙精度型的,我們讓step/8與指針相加(這里
僅僅考慮了C將自動(dòng)地將差值與我們添加的數(shù)據(jù)類(lèi)型的字節(jié)數(shù)相
乘)。
[38]
例3-8中的cvSet*D和cvGet*D多少有些相似,它通過(guò)一次函數(shù)調(diào)用為一個(gè)矩陣或圖像中的
元素設(shè)置值,函數(shù)cvSetReal*D()和函數(shù)cvSet*D()可以用來(lái)設(shè)置矩陣或者圖像中元素的數(shù)值。
例3-8:為CvMat或者IpHmage元素設(shè)定值的函數(shù)
voidcvSetReal1D(CvArr*arr,intidxO,doublevalue);
voidcvSetReal2D(CvArr*arr,intidxO,intidx1,doublevalue);
voidcvSetReal3D(
CvArr*arr,
intidxO,
intidx1,
intidx2,
doublevalue
);
voidcvSetRealND(CX/Arr*arr,int*idx,doublevalue);
voidcvSetlD(CvArr*arr,intidxO,CvScalarvalue);
voidcvSet2D(CvArr*arr,intidxO,intidx1,CvScalarvalue);
voidcvSet3D(
CvArr*arr,
intidxO,
intidx1,
intidx2,
CvScalarvalue
);
voidcvSetND(CvArr*arr,int*idx,CvScalarvalue);
為了方便,我們也可以使用cvmSet()和cvmGet(),這兩個(gè)函數(shù)用于處理浮點(diǎn)型單通道矩陣,
非常簡(jiǎn)單。
doublecvmGet(constCvMat*mat,introw,intcol)
voidcvmSet(CVMat*mat,introw,intcol,doublevalue)
以下函數(shù)調(diào)用cvmSetO:
cvmSet(mat,2,2,0.5000);
等同于cvSetReal2D函數(shù)調(diào)用:
cvSetReal2D(mat,2,2,0.5000);
恰當(dāng)?shù)姆椒?/p>
從以上所有那些訪(fǎng)問(wèn)函數(shù)來(lái)看,你可能會(huì)想,沒(méi)有必要再介紹了。實(shí)際上,這些set和get
函數(shù)很少派上用場(chǎng)。大多數(shù)時(shí)侯,計(jì)算機(jī)視覺(jué)是一種運(yùn)算密集型的任務(wù),因而你想盡量利用
最有效的方法做事。毋庸置疑,通過(guò)這些函數(shù)接口是不可能做到十分高效的。相反地,應(yīng)該
定義自己的指針計(jì)算并且在矩陣中利用自己的方法。如果打算對(duì)數(shù)組中的每一個(gè)元素執(zhí)行一
些操作,使用自己的指針是尤為重要的(假設(shè)沒(méi)有可以為你執(zhí)行任務(wù)的OpenCV函數(shù))。
要想直接訪(fǎng)問(wèn)矩陣,其實(shí)只需要知道一點(diǎn),即數(shù)據(jù)是按光柵掃描順序存儲(chǔ)的,歹ij("x”)是變
化最快的變量。通道是互相交錯(cuò)的,這意味著,對(duì)于?個(gè)多通道矩陣來(lái)說(shuō),它們變化的速度
仍然比較快。例3-9顯示了這一過(guò)程。【39?40]
例3-9:累加一個(gè)三通道矩陣中的所有元素
floatsum(constCvMat*mat){
floats=O.Of;
for(introw=0;row<mat->rows;row++){
constfloat*ptr=(constfloat*)(mat->data.ptr+row*mat->step);
for(col=0;col<mat->cols;col++){
s+=*ptr++;
)
return(s);
)
計(jì)算指向矩陣的指針時(shí).,記住一點(diǎn):矩陣的元素data是一個(gè)聯(lián)合體。所以,對(duì)這個(gè)指針解
引用的時(shí)候,必須指明結(jié)構(gòu)體中的正確的元素以便得到正確的指針類(lèi)型。然后,為了使指針
產(chǎn)生正確的偏移,必須用矩陣的行數(shù)據(jù)長(zhǎng)度(step)元素。我們以前曾提過(guò),行數(shù)據(jù)元素的是
用字節(jié)來(lái)計(jì)算的。為了安全,指針最好用字節(jié)計(jì)算,然后分配恰當(dāng)?shù)念?lèi)型,如浮點(diǎn)型。Cv
Mat結(jié)構(gòu)中為了兼容Iplhnage結(jié)構(gòu),有寬度和高度的概念,這個(gè)概念已經(jīng)被最新的行和列取
代。最后要注意,我們?yōu)槊啃卸贾匦掠?jì)算了ptr,而不是簡(jiǎn)單地從開(kāi)頭開(kāi)始,爾后每次讀的
時(shí)候累加指針。這看起來(lái)好像很繁瑣,但是因?yàn)镃vMat數(shù)據(jù)指針可以指向一個(gè)大型數(shù)組中
的R0I,所以無(wú)法保證數(shù)據(jù)會(huì)逐行連續(xù)存取。
點(diǎn)的數(shù)組
有一個(gè)經(jīng)常提到但又必須理解的問(wèn)題是,包含多維對(duì)象的多維數(shù)組(或矩陣)和包含一維對(duì)象
的高維數(shù)組之間的不同。例如,假設(shè)有〃個(gè)三維的點(diǎn),你想將這些點(diǎn)傳遞到參數(shù)類(lèi)型為Cv
Mat*的一些OpenCV函數(shù)中。對(duì)此,有四種顯而易見(jiàn)的方式,記住,這些方法不一定等價(jià)。
一是用一個(gè)二維數(shù)組,數(shù)組的類(lèi)型是CV32FC1,有”行,3列5x3)。類(lèi)似地,也可以用一
個(gè)3行〃列(3x〃)的二維數(shù)組。也可以用一個(gè)"行1列(〃xl)的數(shù)組或者1行〃歹的數(shù)組,
數(shù)組的類(lèi)型是CV32FC3。這些例子中,有些可以自由轉(zhuǎn)換(這意味著只需傳遞一個(gè),另一個(gè)
便可可以計(jì)算得到),有的則不能。要想理解原因,可以參考圖3-2中的內(nèi)存布
局情況。
從圖中可以看出,在前三種方式中,點(diǎn)集以同樣的方式被映射到內(nèi)存。但最后一種方式則不
同。對(duì)N維數(shù)組的c維點(diǎn),情況變得更為復(fù)雜。需要記住的最關(guān)鍵的一點(diǎn)是,給定點(diǎn)的位
置可以由以下公式計(jì)算出來(lái)。
$=(IDW).取.N…+(coD?Ni+(chaimel)
n-by-132FC3)1-by-n32FC3)
Xoyo2oXi力2lXoyoZoXiyi2l
points
X2Y2z?X3丫3Z3X2y?22X3yjA
(XoyZo)
0x*Y4乙X5Vs4x4VA必V、4
僅1為zj
X6y6qX7y?27%丫6■X7YlZ7
(xjyjZj)x8心Z8y94X8y?4叼y929
(x3y}z3)
dvR
(xsy$zs)n-by-3132FC1)3-by-n32FC1)
僅6丫6勾*0yo20yi2l*0Xi■*3X5
(x?y/z7)勺y:4X3X7XR*9Voyi
僅)
8y8Z8X424X5V,z$V1y$V7
(必丫9與)*6火qMY727ya丫9Z9Ziz2Z3
y?28VQZ9244q27s29
圖3-2:有10個(gè)點(diǎn),每個(gè)點(diǎn)由3個(gè)浮點(diǎn)數(shù)表示,這10個(gè)點(diǎn)被放在4個(gè)結(jié)構(gòu)稍有不同的數(shù)組
中。前3種情況下,內(nèi)存布局情況是相同的,但最后一種情況下,內(nèi)存布局不同
其中,%和Mhanneb分別表示列數(shù)和通道數(shù)。總的來(lái)說(shuō),從這個(gè)公式中可以看出一點(diǎn),一
個(gè)c維對(duì)象的N維數(shù)組和一個(gè)一維對(duì)象的(N+C)維數(shù)組不同。至于N=l(即把向量描繪成"X1
或者1X"數(shù)組),有一個(gè)特殊之處(即圖3-2顯示的等值)值得注意,如果考慮到性能,可以在
有些情況下用到它。
關(guān)于OpenCV的數(shù)據(jù)類(lèi)型,如CvPoint2D和CvPoint2D32f,我們要說(shuō)明的最后一點(diǎn)是:這
些數(shù)據(jù)類(lèi)型被定義為C結(jié)構(gòu),因此有嚴(yán)格定義的內(nèi)存布局。具體說(shuō)來(lái),由整型或者浮點(diǎn)型
組成的結(jié)構(gòu)是順序型的通道。那么,對(duì)于一維的C語(yǔ)言的對(duì)象數(shù)組來(lái)說(shuō),其數(shù)組元素都具
有相同的內(nèi)存布局,形如CV32FC2的?xl或者lx〃數(shù)組。這和申請(qǐng)CvPoint3D32f類(lèi)型的
數(shù)組結(jié)構(gòu)也是相同的。[41]
Ipllmage數(shù)據(jù)結(jié)構(gòu)
掌握了前面的知識(shí),再來(lái)討論Ipllmage數(shù)據(jù)結(jié)構(gòu)就比較容易了。從本質(zhì)上講,它是?個(gè)Cv
Mat對(duì)象,但它還有其他一些成員變量將矩陣解釋為圖像。這個(gè)結(jié)構(gòu)最初被定義為Intel圖
像處理庫(kù)(IPL)的一部分。Ipllmage結(jié)構(gòu)的準(zhǔn)確定義如例3-10所示。
例3-10:IpHmage結(jié)構(gòu)
typedefstruct」plImage{
intnSze;
intID;
intnChannels;
intalphaChannel;
intctepth;
charcolorModel[4];
charchannelSeq[4];
intdataOrder;
intorigin;
intalign;
intwidth;
intheight;
struct」plROI*roi;
structJplImage*maskROI;
void*imageld;
structJpITilelnfo*tileinfo;
intimageSze;
char*imageData;
intwidthStep;
intBorderMode[4];
intBorderConst[4];
char*imageDataOrigin;
}IplImage;
我們?cè)噲D討論這些變量的某些功能。有些變量不是很重要,但是有些變量非常重要,有助于
我們理解OpenCV解釋和處理圖像的方式。
width和height這兩個(gè)變量很重要,其次是depth和nchannals。depth變量的值取自ipl.h中
定義的一組數(shù)據(jù),但與在矩陣中看到的對(duì)應(yīng)變量不同。因?yàn)樵趫D像中,我們往往將深度和通
道數(shù)分開(kāi)處理,而在矩陣中,我們往往同時(shí)表示它們??捎玫纳疃戎等绫?-2所
示。[42]
表3-2:OpenCV圖像類(lèi)型
宏圖像像素類(lèi)型
IPL^DEPTH_8U無(wú)符號(hào)8位整數(shù)(8u)
IPL^DEPTH_8S有符號(hào)8位整數(shù)(8s)
IPL^DEPTH_16S有符號(hào)16位整數(shù)(16s)
IPL_DEPTH_32S有符號(hào)32位整數(shù)(32s)
IPL^DEPTH_32F32位浮點(diǎn)數(shù)單精度(32f)
IPL^DEPTH_64F64位浮點(diǎn)數(shù)雙精度(64f)
通道數(shù)nChannels可取的值是1,2,3或4。
隨后兩個(gè)重要成員是origin和dataOrder。origin變量可以有兩種取值:IPL_ORIGIN_TL或
者IPL_ORIGIN_BL,分別設(shè)置坐標(biāo)原點(diǎn)的位置于圖像的左上角或者左下角。在計(jì)算機(jī)視覺(jué)
領(lǐng)域,一個(gè)重要的錯(cuò)誤來(lái)源就是原點(diǎn)位置的定義不統(tǒng)一。具體而言,圖像的來(lái)源、操作系統(tǒng)、
編解碼器和存儲(chǔ)格式等因素都可以影響圖像坐標(biāo)原點(diǎn)的選取。舉例來(lái)說(shuō),你或許認(rèn)為自己正
在從圖像上面的臉部附近取樣,但實(shí)際上卻在圖像下方的裙子附近取樣。避免此類(lèi)現(xiàn)象發(fā)生
的最好辦法是在最開(kāi)始的時(shí)候檢查一下系統(tǒng),在所操作的圖像塊的地方畫(huà)點(diǎn)東西試試。
dataOrder的取值可以是IPL_DATA_ORDER_PIXEL或IPL_DATA_ORDER_PLANE,前者指
明數(shù)據(jù)是將像素點(diǎn)不同通道的值交錯(cuò)排在一起(這是常用的交錯(cuò)排列方式),后者是把所有像
素同通道值排在一起,形成通道平面,再把平面排列起來(lái)。
參數(shù)widthStep與前面討論過(guò)的CvMat中的step參數(shù)類(lèi)似,包括相鄰行的同列點(diǎn)之間的字節(jié)
數(shù)。僅憑變量width是不能計(jì)算這個(gè)值的,因?yàn)闉榱颂幚磉^(guò)程更高效每行都會(huì)用固定的字節(jié)
數(shù)來(lái)對(duì)齊;因此在第i行末和第/+1行開(kāi)始處可能會(huì)有些冗于字節(jié)。參數(shù)imageData包含一
個(gè)指向第一行圖像數(shù)據(jù)的指針。如果圖像中有些獨(dú)立的平面(如當(dāng)dataOrder=IPL_DATA_
ORDER_PLANE)那么把它們作為單獨(dú)的圖像連續(xù)擺放,總行數(shù)為height和nChannels的乘
積。但通常情況下,它們是交錯(cuò)的,使得行數(shù)等于高度,而且每一行都有序地包含交錯(cuò)的通
道。
最后還有一個(gè)實(shí)用的重要參數(shù)——感興趣的區(qū)域(ROI),實(shí)際上它是另一個(gè)IPL/IPP結(jié)構(gòu)Ip
1R0I的實(shí)例。IplROI包含xOffset,yOffset,height,width和coi成員變量,其中COI代表
channelofinterest(感興趣的通道)。ROI的思想是:一旦設(shè)定ROI,通常作用于整幅圖像的
函數(shù)便會(huì)只對(duì)ROI所表示的子圖像進(jìn)行操作。如果Ipllmage變量中設(shè)置了ROI,則所有的
OpenCV函數(shù)就會(huì)使用該ROI變量。如果C01被設(shè)置成非0值,則對(duì)該圖像的操作就只作
用于被指定的通道上了?不幸的是,許多OpenCV函數(shù)都忽略參數(shù)COI。
訪(fǎng)問(wèn)圖像數(shù)據(jù)
通常,我們需要非常迅速和高效地訪(fǎng)問(wèn)圖像中的數(shù)據(jù)。這意味著我們不應(yīng)受制于存取函數(shù)(如
cvSet*D之類(lèi))。實(shí)際上,我們想要用最直接的方式訪(fǎng)問(wèn)圖像內(nèi)的數(shù)據(jù)。現(xiàn)在,應(yīng)用已掌握的
Ipllmage內(nèi)部結(jié)構(gòu)的知識(shí),我們知道怎樣做才是最佳的方法。
雖然OpenCV中有很多優(yōu)化函數(shù)幫助我們完成大多數(shù)的圖像處理的任務(wù),但是還有一些任
務(wù),庫(kù)中沒(méi)有預(yù)先包裝好的函數(shù)可以幫我們解決。例如,如果我們有一個(gè)三通道HSV圖像[S
mith78],在色度保持不變的情況下,我們要設(shè)置每個(gè)點(diǎn)的飽和度和高度為255(8位圖像的最
大值),我們可以使用指針遍歷圖像,類(lèi)似于例3-9中的矩陣遍歷。然而,有一些細(xì)微的不
同,是源于IpHmage和CvMat結(jié)構(gòu)的差異。例3-11演示了最高效的方法。
例3-11:僅最大化HSV圖像"S’和"V部分
voidsaturate_sv(Ipllmage*img){
for(inty=0;y<img->height;y++){
uchar*ptr=(uchar*)(
img->imageData+y*img->widthStep
);
for(intx=0;x<img->width;x++){
ptr[3*x+1]=255;
ptr[3*x+2]=255;
)
)
)
在以上程序中,我們用指針ptr指向第y行的起始位置。接著,我們從指針中析出飽和度和
高度在x維的值。因?yàn)檫@是一個(gè)三通道圖像,所以C通道在x行的位置是3*x+c。
與CvMat的成員data相比,Ipllmage和CvMat之間的一個(gè)重要度別在于imageData。CvMa
t的data兀素類(lèi)型是聯(lián)合類(lèi)型,所以你必須說(shuō)明需要使用的指針類(lèi)型。imageData指針是字
節(jié)類(lèi)型指針(uchar*)。我們已經(jīng)知道是種類(lèi)型的指針指向的數(shù)據(jù)是uchar類(lèi)型的,這意味
著,在圖像上進(jìn)行指針運(yùn)算時(shí),你可以簡(jiǎn)單地增加widthStep(也以字節(jié)為單位),而不必關(guān)
心實(shí)際數(shù)據(jù)類(lèi)型。在這里重新說(shuō)明一下:當(dāng)要處理的是矩陣時(shí),必須對(duì)偏移并進(jìn)行調(diào)整,因
為數(shù)據(jù)指針可能是非字節(jié)類(lèi)型;當(dāng)要處理的是圖像時(shí).,可以直接使用偏移,因?yàn)閿?shù)據(jù)指針總
是字節(jié)類(lèi)型,因此當(dāng)你要用到它的時(shí)候要清楚是怎么回事。
對(duì)ROI和widthStep的補(bǔ)充
ROI和widthStep在實(shí)際工作中有很重要的作用,在很多情況下,使用它們會(huì)提高計(jì)算機(jī)視
覺(jué)代碼的執(zhí)行速度。這是因?yàn)樗鼈冊(cè)试S對(duì)圖像的某?小部分進(jìn)行操作,而不是對(duì)整個(gè)圖像進(jìn)
行運(yùn)算。在OpenCV中,普遍支持ROI和widthStep,函數(shù)的操作被限于感興趣區(qū)域。要設(shè)
置或取消ROI,就要使用cvSetlmageROI。和cvResetlmageROI。函數(shù)。如果想設(shè)置ROL可
以使用函數(shù)cvSetlmageROK),并為其傳遞一個(gè)圖像指針和矩形。而取消ROL只需要為函
數(shù)cvResetImageROI()傳遞■個(gè)圖像指針。
voidcvSetlmageROI(Ipllmage*image,CvRectrect);
voidcvResetlmageROI(Ipllmage*image);
為了解釋ROI的用法,我們假設(shè)要加載一幅圖像并修改一些區(qū)域,如例3-12的代碼,讀取
了一幅圖像,并設(shè)置了想要的ROI的x,y,width和height的值,最后將ROI區(qū)域中像素
都加上一個(gè)整數(shù)。本例程中通過(guò)內(nèi)聯(lián)的cvRect()構(gòu)造函數(shù)設(shè)置ROI。通過(guò)cvResetlmageROI。
函數(shù)釋放ROI是非常重要的,否則,將忠實(shí)地只顯示ROI區(qū)域。
例3-12:用imageROI來(lái)增加某范圍的像素
//roi_add<image><x><y><width><height><add>
#include<cv.h>
#include<highgui.h>
intmain(intargc,char**argv)
Ipllmage*src;
if(argc==7&&((src=cvLoadlmage(argv[1],1))!=0))
intx=atoi(argv[2]);
inty=atoi(argv[3]);
intwidth=atoi(argv[4]);
intheight=atoi(argv[5]);
intadd=atoi(argv[6]);
cvSetlmageROI(src,cvRect(x,y,width,height));
cvAddS(src,cvScalar(add),src);
cvResetlmageROI(src);
cvNamedWindow("Roi_Add”,1);
cvShowlmage("Roi_Addn,src);
cvWaitKey();
)
return0;
)
使用例3-12中的代碼把ROI集中于一張貓的臉部,并將其藍(lán)色通道增加150后的效果如圖
3-3所示?!?5~46】
圖3-3:在貓臉上用ROI增加150像素的效果
通過(guò)巧妙地使用widthStep,我們可以達(dá)到同樣的效果。要做到這一點(diǎn),我們創(chuàng)建另一個(gè)圖
像頭,讓它的width和height的值等于interest_rect的width和height的值。我們還需要按i
nterest_rect起點(diǎn)設(shè)置圖像起點(diǎn)(左上角或者左下角)。下一步,我們?cè)O(shè)置子圖像的widthStep
與較大的interest_img相同。這樣,即可在子圖像中逐行地步進(jìn)到大圖像里子區(qū)域中下?行
開(kāi)始處的合適位置。最后設(shè)置子圖像的imageDate指針指向興趣子區(qū)域的開(kāi)始,如例3-13
所示。
例3-13:利用其他widthStep方法把interestjmg的所有像素值增加1
//AssumingIplImage*interestjmg;and
//Q/Rectinterest_rect;
//UsewidthSteptogetaregionofinterest
//
//(Alternatemethod)
//
IplImage*subJmg=cvCreatelmageHeader(
cvSize(
interest_rect.width,
interest_rect.height
),
interest_img->depth,
interest_img->nChannels
);
sub_img->origin=interest_img->origin;
sub_img->widthstep=interestJmg->widthstep;
sub_img->imageData=interestJmg->imageData+
interest_rect.y*interestJmg->widthstep+
interest_rect.x*interest_img->nChannels;
cvAddS(subjmg,cvScalar(1),subJmg);
cvReleaselmageHeader(&sub_img);
看起來(lái)設(shè)置和重置ROI更方便一些,為什么還要使用widthstep?原因在于有些時(shí)候在處理
的過(guò)程中,想在操作過(guò)程中設(shè)置和保持一幅圖像的多個(gè)子區(qū)域處于活動(dòng)狀態(tài),但是ROI只
能串行處理并且必須不斷地設(shè)置和重置。
最后,我們要在此提到一個(gè)詞——掩碼或模板,在代碼示例中cvAddS。函數(shù)允許第四個(gè)參
數(shù)默認(rèn)值為空:constCvArr*mask=NULL。這是一個(gè)8位單通道數(shù)組,它允許把操作限制
到任意形狀的非0像素的掩碼區(qū),如果ROI隨著掩碼或模板變化,進(jìn)程將會(huì)被限制在ROI
和掩碼的交集區(qū)域。掩碼或模板只能在指定了其圖像的函數(shù)中使用。
矩陣和圖像操作
表3-3列出了一些操作矩陣圖像的函數(shù),其中的大部分對(duì)于圖像處理非常有效。它們實(shí)現(xiàn)了
圖像處理中的基本操作,例如對(duì)角化、矩陣變換以及一些更復(fù)雜的諸如計(jì)算圖像的統(tǒng)計(jì)操
作。[47]
表3-3:矩陣和圖像基本操作
函數(shù)名稱(chēng)描述
cvAbs計(jì)算數(shù)組中所有元素的絕對(duì)值
cvAbsDiff計(jì)算兩個(gè)數(shù)組差值的絕對(duì)值
續(xù)表
函數(shù)名稱(chēng)描述
cvAbsDiffS計(jì)算數(shù)組和標(biāo)量差值的絕對(duì)值
cvAdd兩個(gè)數(shù)組的元素級(jí)的加運(yùn)算
cvAddS一個(gè)數(shù)組和一個(gè)標(biāo)量的元素級(jí)的相加運(yùn)算
cvAddWeighted兩個(gè)數(shù)組的元素級(jí)的加權(quán)相加運(yùn)算(alpha融合)
cvAvg計(jì)算數(shù)組中所有元素的平均值
cvAvgSdv計(jì)算數(shù)組中所有元素的絕對(duì)值和標(biāo)準(zhǔn)差
cvCalcCovarMatrix計(jì)算一組〃維空間向量的協(xié)方差
cvCmp對(duì)兩個(gè)數(shù)組中的所有元素運(yùn)用設(shè)置的比較操作
cvCmpS對(duì)數(shù)組和標(biāo)量運(yùn)用設(shè)置的比較操作
cvConvertScale用可選的縮放值轉(zhuǎn)換數(shù)組元素類(lèi)型
cvConvertScaleAbs計(jì)算可選的縮放值的絕對(duì)值之后再轉(zhuǎn)換數(shù)組元素的類(lèi)型
cvCopy把數(shù)組中的值復(fù)制到另一個(gè)數(shù)組中
cvCountNonZero計(jì)算數(shù)組中非。值的個(gè)數(shù)
cvCrossProduct計(jì)算兩個(gè)三維向量的向量積(叉積)
cvCvtColor將數(shù)組的通道從一個(gè)顏色空間轉(zhuǎn)換另外一個(gè)顏色空間
cvDet計(jì)算方陣的行列式
cvDiv用另外一個(gè)數(shù)組對(duì)一個(gè)數(shù)組進(jìn)行元素級(jí)的除法運(yùn)算
cvDotProduct計(jì)算兩個(gè)向量的點(diǎn)積
cvBgenW計(jì)算方陣的特征值和特征向量
cvFIip圍繞選定軸翻轉(zhuǎn)
cvGEMM矩陣乘法
cvGetCol從一個(gè)數(shù)組的列中復(fù)制元素
cvGetCols從數(shù)據(jù)的相鄰的多列中復(fù)制元素值
cvGetDiag復(fù)制數(shù)組中對(duì)角線(xiàn)上的所有元素
cvGetDims返回?cái)?shù)組的維數(shù)
cvGetDimSze返回個(gè)數(shù)組的所有維的大小
cvGetRow從個(gè)數(shù)組的行中復(fù)制元素值
cvGetRows從一個(gè)數(shù)組的多個(gè)相鄰的行中復(fù)制元素值
cvGetSize得到二維的數(shù)組的尺寸,以CvSze返回
cvGetSubRect從一個(gè)數(shù)組的子區(qū)域復(fù)制元素值
cvlnRange檢查個(gè)數(shù)組的元素是否在另外兩個(gè)數(shù)組中的值的范圍內(nèi)
cvlnRangeS檢查個(gè)數(shù)組的元素的值是否在另外兩個(gè)標(biāo)量的范圍內(nèi)
續(xù)表
函數(shù)名稱(chēng)描述
cvlnvert求矩陣的轉(zhuǎn)置
cvMahalonobis計(jì)算兩個(gè)向量間的馬氏距離
cvMax在兩個(gè)數(shù)組中進(jìn)行元素級(jí)的取最大值操作
cvMaxS在一個(gè)數(shù)組和一個(gè)標(biāo)量中進(jìn)行元素級(jí)的取最大值操作
cvMerge把幾個(gè)單通道圖像合并為一個(gè)多通道圖像
cvMin在兩個(gè)數(shù)組中進(jìn)行元素級(jí)的取最小值操作
cvMinS在個(gè)數(shù)組和?個(gè)標(biāo)量中進(jìn)行元素級(jí)的取最小值操作
cvMinMaxLoc尋找數(shù)組中的最大最小值
cvMul計(jì)算兩個(gè)數(shù)組的元素級(jí)的乘積
cvNot按位對(duì)數(shù)組中的每一個(gè)元素求反
cvNorm計(jì)算兩個(gè)數(shù)組的正態(tài)相關(guān)性
cvNormalize將數(shù)組中元素進(jìn)行規(guī)一化
cvOr對(duì)兩個(gè)數(shù)組進(jìn)行按位或操作
cvOrS在數(shù)組與標(biāo)量之間進(jìn)行按位或操作
cvReduce通過(guò)給定的操作符將二維數(shù)組約簡(jiǎn)為向量
cvRepeat以平鋪的方式進(jìn)行數(shù)組復(fù)制
cvSet用給定值初始化數(shù)組
cvSetZero將數(shù)組中所有元素初始化為0
cvSetldentity將數(shù)組中對(duì)角線(xiàn)上的元素設(shè)為1,其他置0
cvSolve求出線(xiàn)性方程組的解
cvSplit將多通道所組分割成多個(gè)單通道數(shù)組
cvSub兩個(gè)數(shù)組元素級(jí)的相減
cvSubS元素級(jí)的從數(shù)組中減去標(biāo)量
cvSubRS元素級(jí)的從標(biāo)量中減去數(shù)組
cvSum對(duì)數(shù)組中的所有元素求和
cvSVD二維矩陣的奇異值分解
cvSVBkSb奇異值回代計(jì)算
cvTrace計(jì)算矩陣跡
cvTranspose矩陣的轉(zhuǎn)置運(yùn)算
cvXor對(duì)兩個(gè)數(shù)組進(jìn)行按位異或操作
cvXorS在數(shù)組和標(biāo)量之間進(jìn)行按位異或操作
cvZero將所有數(shù)組中的元素置為0
cvAbs,cvAbsDiff和cvAbsDiffS
voidcvAbs(
constCvArr*src,
constdst
);
voidcvAbsDiff(
constCvArr*src1,
constCvArr*src2,
constdst
);
voidcvAbsDiffS(
constCvArr*src,
CvScalarvalue,
constdst
[501
這些函數(shù)計(jì)算一個(gè)數(shù)組的絕對(duì)值或數(shù)組和其他對(duì)象的差值的絕對(duì)值,cvAbs()函數(shù)計(jì)算src里
的值的絕對(duì)值,然后把結(jié)果寫(xiě)到dst;cvAbsDiff()函數(shù)會(huì)先從srcl減去src2,然后將所得差
的絕對(duì)值寫(xiě)到dst:除了從所有src元素減掉的數(shù)是常標(biāo)量值外,可以看到cvAbsDiffSO函數(shù)
同cvAbsDiff()函數(shù)基本相同。
cvAdd,cvAddS,cvAddWeighted和alpha融合
voidcvAdd(
constCvArr*srcl,
constCvArr*src2,
CvArr*dst,
constCvArr*mask=NULL
voidcvAddS(
constCvArr*src,
CvScalarvalue,
CvArr*dst,
constCvArr*mask=NULL
voidcvAddWeighted(
constCvArr*srd,
doublealpha,
constCvArr*src2,
double
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度稅務(wù)代理與納稅申報(bào)服務(wù)合同
- 二零二五年度互聯(lián)網(wǎng)企業(yè)股份收購(gòu)合同范本
- 二零二五年度消防員勞務(wù)派遣與消防安全檢查及技術(shù)支持合同
- 2025年度企業(yè)財(cái)務(wù)報(bào)表分析與應(yīng)用合同
- 2025年度酒店特色文化體驗(yàn)區(qū)轉(zhuǎn)讓合同
- 2025年度手車(chē)二手市場(chǎng)評(píng)估與交易合同
- 委托施工協(xié)議 委托方
- 2025辦公用品采購(gòu)合同書(shū)協(xié)議模板
- 2025出租車(chē)雇傭合同范文
- 鐵路信號(hào)工程師的專(zhuān)業(yè)知識(shí)與技術(shù)
- 軟件無(wú)線(xiàn)電原理與應(yīng)用第3版 課件 【ch02】軟件無(wú)線(xiàn)電理論基礎(chǔ)
- 國(guó)網(wǎng)山東電力生產(chǎn)技術(shù)改造原則
- 鐵路運(yùn)輸安全現(xiàn)場(chǎng)管理
- 2023年某保險(xiǎn)公司春節(jié)經(jīng)營(yíng)教材
- 劉都才-南方水稻田雜草發(fā)生動(dòng)態(tài)及防控技術(shù)
- 全自動(dòng)化學(xué)發(fā)光分析儀操作規(guī)程
- 北侖區(qū)建筑工程質(zhì)量監(jiān)督站監(jiān)督告知書(shū)
- 深藍(lán)的故事(全3冊(cè))
- GB/T 42461-2023信息安全技術(shù)網(wǎng)絡(luò)安全服務(wù)成本度量指南
- 職校開(kāi)學(xué)第一課班會(huì)PPT
- 央國(guó)企信創(chuàng)白皮書(shū) -基于信創(chuàng)體系的數(shù)字化轉(zhuǎn)型
評(píng)論
0/150
提交評(píng)論