cvCopy与cvCloneImage的区别

 

/* Copies source array to destination array */
CVAPI(void)  cvCopy( const CvArr* src, CvArr* dst,
                     const CvArr* mask CV_DEFAULT(NULL) );

/* Creates a copy of IPL image (widthStep may differ) */
CVAPI(IplImage*) cvCloneImage( const IplImage* image );

如果设定了ROI等参数的时候,cvCopy只是复制被设定的区域,复制到一个和所设定参数相吻合的新的IplImage中
而cvCloneImage则是将整个IplImage结构复制到新的IplImage中,其中的ROI等参数也会一同复制。新的IplImage将会和原来的一模一样。




ref:

    http://blog.csdn.net/jianguo_cui/article/details/7387169
下面對Mat矩陣進行一些說明:

 

1. cv::Mat中的數據不需要釋放.cv::Mat會自動釋放.

例如,cv::Mat m=cv::imread("123.jpg"); 然後進行數據操作,最後根本不用對m進行釋放,也不需要調用其他的任何release函數.

       

2. cv::Mat的depth()函數可以得到圖像的深度,值類似于CV_8U.CV_16F等..可以理解為單個channel中的單個元素的大小(bit)與類型.8U表示8-bit unsigned char.

3. cv::Mat的cols表示圖像的width,rows表示圖像的height.

4. cv::Mat在取底層數據的時候使用at函數,類似于src.at<cv::Point3i>(i,j)[0]的方式,取出第i行第j列的像素的第0個channel的值.尖括號中的類型為Mat元素的類型.例如單channel的8U圖像可以使用unsigned char型,由於是單channel就不要後面的中括號了.3channel的BGR圖像可以使用cv::Point3i的格式.

5. cv::Mat的類型是由深度和channel數一起決定的,類似于CV_8UC3,表示深度為CV_8U,channel數為CV_C1.可以使用CV_MAKETYPE(depth,cn) 宏來合成類型值.

6. cv::Mat 默認情況下是不進行數據拷貝的,只是生成一個Mat頭信息,所以就導致如果兩個Mat指向同一個數據的時候,其中一個進行了變更,另一個也會變更.如果要進行實際數據的拷貝可以使用下面的2中方式:

cv::Mat m1=cv::imread("123.jpg");

cv::Mat m2=m1; //沒有數據拷貝

cv::Mat m3=m2.clone();//有數據拷貝

cv::Mat m4;

m2.copyTo(m4); //有數據拷貝

7. 當多個cv::Mat 指向同一組數據的時候,只有所有的Mat都釋放之後實際數據才會釋放,否則只是進行計數累加. 當其中一個Mat調用Relese函數后,只是釋放當前Mat的頭信息,如果此時還有其他Mat在使用這些實際數據,則這些實際數據并不釋放.也就是說cv::Mat.Relese()只是減少一個引用計數,并清空Mat頭,其他無影響.

 
 
下面說明一下cv::Mat的成員函數和成員變量:
Mat row(int y) const; 使用第y行的數據新建一個Mat,不進行數據拷貝.
Mat col(int x) const; 使用第x列的數據新建一個Mat,不進行數據拷貝.
Mat rowRange(int startrow, int endrow) const; 使用第startrow行到第endrow行的數據新建一個Mat,不進行數據拷貝.
Mat rowRange(const Range& r) const; 使用Range 中的行的數據新建一個Mat,不進行數據拷貝.
Mat colRange(int startcol, int endcol) const;使用第startcol列到第endcol列的數據新建一個Mat,不進行數據拷貝.
Mat colRange(const Range& r) const; 使用Range 中的列的數據新建一個Mat,不進行數據拷貝.
Mat diag(int d=0) const; 使用對角線(從左上到右下)中的數據新建一個單列的Mat,不進行數據拷貝.d=0時為主對角線,d>0表示主對角線下面的第d個對角線,d<0表示主對角線上面的第d個對角線.
Mat clone() const; 產生一個新的Mat,并複製實際數據.實際數據存儲在一個連續的total()*elemSize()大小的空間之中.
例如, cv::Mat m=src.diag(0);//m中存儲這一個對角線數據,實際上還是src中的數據,所以這些對角線數據是被其他值分開的.每行只有1個值有用.
          cv::Mat m2=m.clone(); //ma中的對角線數據是連續的,一個值接著一個值,中間沒有被其他值分開.
void copyTo( OutputArray m ) const;拷貝實際數據到m中,m會根據源Mat的大小重建.(如果m中有數據則會先釋放).
void copyTo( OutputArray m, InputArray mask ) const; 功能同 copyTo( OutputArray m ) ,只是只會拷貝mask中對應不是0的值.mask與源Mat要有相同的size. m在被拷貝之前會用0填充.
void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const; 將源Mat的格式轉換為另一種數據格式存儲到m中,如果m的格式或大小不正確則會重新創建.rtype為轉換后的類型,如果為負數,則與源Mat相同.這個函數可以對其中的值進行縮放和偏移,公式為 m(x,y)=newtype((alpha*src(x,y)+beta));
void assignTo( Mat& m, int type=-1 ) const; 內部函數,功能同convertTo.
Mat=Scalar; 重載等號,將Mat的中每一個元素都填充為一個Scalar.
Mat& setTo(InputArray value, InputArray mask=noArray());根據mask的將M中的元素設置為value.
Mat reshape(int _cn, int _rows=0) const; //將源Mat的改成cn個channel和rows行數據,不進行數據拷貝.使用reshape函數有一個要點就是rows*cols*channels的值必須等於源Mat.也就是實際數據保持不變._rows=0表示rows與源Mat相同,_cn=0表示channel數量與源Mat相同,
例如:
cv::Mat src(200,400,CV_8UC3);
cv::Mat m1=src.reshape(2,0); //將圖像變成2個channel的圖像.由於rows不變,所以cols變為src.rows*src.cols*src.channels()/src.rows/2;圖像顯示為顏色失真(少了一個channel嘛)圖像寬度變大.這是由於原來的第3個channel的值被當做下一個元素的第一個值來使用了,所以圖像看起來并不是從圖像中截取一截放到右邊,而是像是使用差值的方式進行擴展了(實際上再轉換成4channel的時候就是差值的方式,只是在沒兩個元素後面插入2個零).
創作者介紹
創作者 大玩家闖天涯 的頭像
大玩家闖天涯

大玩家闖天涯的部落格

大玩家闖天涯 發表在 痞客邦 留言(0) 人氣()