OpenCV实现Mat与vector,Mat与数组互转
OpenCV實現Mat與vector互轉
【尊重原創,轉載請注明出處】https://blog.csdn.net/guyuealian/article/details/80253066
1、Mat與vector互轉
? ?下面是鄙人實現的Mat與vector互轉的方法,需要注意的是vector轉Mat時,使用reshape()后,必須clone()一份,否則返回的結果出錯,關于這方面的原因,可以參考鄙人的博客:https://blog.csdn.net/guyuealian/article/details/80252853
#include <opencv2/opencv.hpp>using namespace cv; using namespace std;/***************** Mat轉vector **********************/ template<typename _Tp> vector<_Tp> convertMat2Vector(const Mat &mat) {return (vector<_Tp>)(mat.reshape(1, 1));//通道數不變,按行轉為一行 }/****************** vector轉Mat *********************/ template<typename _Tp> cv::Mat convertVector2Mat(vector<_Tp> v, int channels, int rows) {cv::Mat mat = cv::Mat(v);//將vector變成單列的matcv::Mat dest = mat.reshape(channels, rows).clone();//PS:必須clone()一份,否則返回出錯return dest; }int main() {/* char ->CV_8SC* unsigned char,uchar ->CV_8UC* unsigned short int,ushort->CV_16UC* short int->CV_16SC* int ->CV_32SC* float ->CV_32FC* double->CV_64FC*/uchar arr[4][3] = { { 1, 1,1 },{ 2, 2,2 },{ 3, 3,3 },{ 4,4, 4 } };cv::Mat srcData(4, 3, CV_8UC1, arr);cout << "srcData=\n" << srcData << endl;vector<uchar> v = convertMat2Vector<uchar>(srcData);cv::Mat dest = convertVector2Mat<uchar>(v, 1, 4);//把數據轉為1通道,4行的Mat數據cout << "dest=\n" << dest << endl;system("pause");waitKey();return 0; }運行結果:
srcData= [ 1, 1, 1;2, 2, 2;3, 3, 3;4, 4, 4] dest= [ 1, 1, 1;2, 2, 2;3, 3, 3;4, 4, 4]2、Mat與數組互轉
? ? ? 利用Mat來存儲數據,避免使用數組等操作
cv::Mat mean = (cv::Mat_<float>(2, 1) << 0.4404, 0.3111); cout << "mean=" << mean << endl; float a=mean.at<float>(0, 0); float b = mean.at<float>(0, 0);? ? ? ?將數組內容傳遞給Mat,示例代碼:
unsigned char cbuf[height][width]; cv::Mat img(height, width, CV_8UC1, (unsigned char*)cbuf);? ? ? ?將Mat中的內容傳遞給數組,如果Mat中的數據是連續的,那么對于傳遞到一維vector我們可以這樣:
std::vector<uchar> array(mat.rows*mat.cols); if (mat.isContinuous())array = mat.data;? ? ? ?同樣的,傳遞到一維數組我們可以這樣
unsigned char *array=new unsigned char[mat.rows*mat.cols];if (mat.isContinuous())array = mat.data;? ? ? ? 對于二維vector的傳值,我們可以這樣處理???????
uchar **array = new uchar*[mat.rows]; for (int i=0; i<mat.rows; ++i)array[i] = new uchar[mat.cols];for (int i=0; i<mat.rows; ++i)array[i] = mat.ptr<uchar>(i);?RGB圖與數組轉換(3維矩陣)
BYTE* iPtr = new BYTE [height*width*3];for(int i=0;i<height;i++){for(int j=0;j<width;j++){for(int k=0;k<3;k++){iPtr[i*width*3+j*3+k] = img.at<Vec3b>(i,j)[k];}}}? ? ? ? 其中,img是一個3維uchar的Mat,Vec3b代表3個uchar,對于灰度圖、4維矩陣等,只要把通道數和at的數據類型改一下就可以套用以上格式。還有一點千萬注意,Mat的(i,j)是按(行,列)的規則,而圖像中則是(高,寬),跟Size(x,y),Rect(x,y)的(x,y)是不同的
4字節對齊的情況
? ? ? ? http://lib.csdn.net/article/opencv/24030
? ? ? ? 但如果圖像大小不是4的整數倍,某些場合下不能直接使用Mat::data。因為圖像在OpenCV里的存儲機制問題,行與行之間可能有空白單元(一般是補夠4的倍數或8的倍數,稱為padding。這些空白單元對圖像來說是沒有意思的,只是為了在某些架構上能夠更有效率,比如intel MMX可以更有效的處理那種個數是4或8倍數的行。Mat提供了一個檢測圖像是否連續的函數isContinuous()。當圖像連通時,我們就可以把圖像完全展開,看成是一行。此時調用Mat::ptr<>()方法就等價于Mat::data:
int nr=image.rows; int nc=image.cols; if(image.isContinuous()) { nr=1; nc=nc*image.rows*image.channels(); } for(int i=0;i<nr;i++) { const uchar* inData=image.ptr<uchar>(i); uchar* outData=outImage.ptr<uchar>(i); for(int j=0;j<nc;j++) { *outData++=*inData++; } }? ? ? ? 例如保存BMP格式的圖像時,BMP要求圖像數據按四字節對齊,此時就需要對Mat中的數據進行補零
 對齊方法就是在每一行尾部補零,零的個數可能是1~3個
? ? ? ? 但其實大部分時候,Mat的內存都是連續的,只有極個別時候需要擔心這個問題,這里有說明,和這里
總結
以上是生活随笔為你收集整理的OpenCV实现Mat与vector,Mat与数组互转的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: OpenCV reshape函数需要注意
- 下一篇: C++数组(一维、二维、三维)的动态分配
