UMat 通过使用UMat对象,OpenCV会自动在支持OpenCL的设备上使用GPU运算,在不支持OpenCL的设备仍然使用CPU运算,这样就避免了程序运行失败,而且统一了接口。UMat::getMat()转换为Mat, Mat::getUMat()转换为UMat
Mat类
cv::Mat::isContinuous()检查行是否连续,如果行连续,则可以将Mat看做一行,加快某些算法处理速度。
矩阵元素遍历
1.使用C操作符[]
Mat& ScanImageAndReduceC(Mat& I, const uchar* const table) { // accept only char type matrices CV_Assert(I.depth() == CV_8U); int channels = I.channels(); int nRows = I.rows; int nCols = I.cols * channels; if (I.isContinuous()) { nCols *= nRows; nRows = 1; } int i,j; uchar* p; for( i = 0; i < nRows; ++i) { p = I.ptr<uchar>(i); //获取行首指针 for ( j = 0; j < nCols; ++j) { p[j] = table[p[j]]; } } return I; }
2.使用迭代器
Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table) { // accept only char type matrices CV_Assert(I.depth() == CV_8U); const int channels = I.channels(); switch(channels) { case 1: { MatIterator_<uchar> it, end; for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it) *it = table[*it]; break; } case 3: { MatIterator_<Vec3b> it, end; for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it) { (*it)[0] = table[(*it)[0]]; (*it)[1] = table[(*it)[1]]; (*it)[2] = table[(*it)[2]]; } } } return I; }
3.使用at (速度慢)
Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar* const table) { // accept only char type matrices CV_Assert(I.depth() == CV_8U); const int channels = I.channels(); switch(channels) { case 1: { for( int i = 0; i < I.rows; ++i) for( int j = 0; j < I.cols; ++j ) I.at<uchar>(i,j) = table[I.at<uchar>(i,j)]; break; } case 3: { Mat_<Vec3b> _I = I; for( int i = 0; i < I.rows; ++i) for( int j = 0; j < I.cols; ++j ) { _I(i,j)[0] = table[_I(i,j)[0]]; _I(i,j)[1] = table[_I(i,j)[1]]; _I(i,j)[2] = table[_I(i,j)[2]]; } I = _I; break; } } return I; }
4.使用查找表LUT
Mat::convertTo() convert Mat to another data type with optional scalling,可用于图像线性对比度变换g(i,j)=α⋅f(i,j)+β
Mat类由矩阵头(包含矩阵尺寸、存储方法、存储地址等信息)和一个指向存储像素值的矩阵的指针。矩阵头尺寸是一个常数值。
Mat类使用引用计数机制,赋值一个Mat对象的信息头时,会增加矩阵的引用计数。当引用计数值为零时矩阵会被清理。
如果想复制矩阵本身,则可以使用clone()或者copyTo()函数。
void cv::Mat::copyTo(OutputArray m) const
调用copyTo函数时,会默认先自动调用m.create(this->size(),this->type());
void cv::Mat::copyTo(OutputArray m,InputArray mask ) const
mask of the same size as *this. Its non-zero elements indicate which matrix elements need to be copied. The mask has to be of type CV_8U and can have 1 or multiple channels.
int main()
{
Mat A, C;
A = imread("1.jpg", IMREAD_COLOR);
Mat B(A); //拷贝构造函数,只复制信息头和矩阵指针,不复制矩阵
C = A; //赋值运算符,只复制信息头和矩阵指针,不复制矩阵
Mat D(A, Rect(10, 10, 100, 100)); //创建ROI,使用矩形界定
Mat E = A(Range::all(), Range(1, 3)); //使用行列界定
Mat F = A.clone(); //复制矩阵
Mat G;
A.copyTo(G); //复制矩阵
waitKey(0);
return 0;
}