2012-08-12 181 views
3

我寫了下面的代碼:初始化矩陣

int _tmain(int argc, _TCHAR* argv[]) 
{ 

int vals[]={1,2,3,4,5,6,7,8,9}; 

CvMat mat = cvMat(3,3,CV_8UC1,vals); 

for(int i=0;i<mat.rows;i++) 
{ 
    int* ptr = (int*) (mat.data.ptr + i* mat.step); 

    for(int j=0;j<mat.cols;j++) 
    { 
       printf("%d\t",*ptr++); 

    } 
    printf("\n"); 
} 

return 0; 
} 

我得到的輸出是:

1    2    3 
512   768    1024 
196608   262144   327680 

矩陣未正確初始化。指針ptr指向每一行的開始,並遞增它給出相應列中的元素。我的假設是否正確?使用cvMat構造函數或元素的訪問方法是否有任何錯誤?

+0

這是C++不是它,而不是C?他們是完全不同的語言。什麼是'CvMat'?什麼是'_Tchar'?你爲什麼使用演員? – 2012-08-12 16:35:26

+0

CvMat是矩陣數據結構。 '_tchar'我在創建一個新項目後就這樣離開了它。 (它默認顯示)。但是你能告訴我主要功能'_tmain'的意思是什麼? (這些東西默認顯示) – 2012-08-12 18:36:30

+0

你還沒有給出你的問題的背景,我們該如何猜測這些東西?請正確標記您的問題。 – 2012-08-12 18:51:58

回答

1

爲什麼不使用cv::Mat類?

它有一些方便的功能,更好地處理內存。

來聲明和你的情況初始化cv::Mat代碼看起來是這樣的:

int main() 
{ 
    int vals[] = {1,2,3,4,5,6,7,8,9}; 

    Mat mat = cv::Mat(3, 3, CV_8UC1, vals).clone(); 

    for(int i = 0; i < mat.rows; i++) 
    { 
     for(int j = 0; j < mat.cols; j++) 
     { 
      cout << mat.at<uchar>(j,i) << " "; 
     } 
     cout << endl; 
    } 
    return 0; 
} 
+0

謝謝...我已經閱讀了一些來自互聯網的教程,其中聲明,初始化和訪問的方式是我在代碼中使用的,可以給我一些鏈接,瞭解你上述的編程風格...一些鏈接,詳細說明你的操作矩陣方法等。 – 2012-08-13 15:57:42

+0

看看[Opencv cheatsheet](http://opencv.willowgarage.com/wiki/Welcome?action = AttachFile&DO = GET和目標= opencv_cheatsheet.pdf)。很多常用的函數在這個cheatsheet中可以很有效地解釋,它也可以在你的opencv源文件夾裏找到。 – masad 2012-08-13 20:46:17

+0

爲什麼你用cout << mat.at (j,i)<<「」;?看來它會逐列初始化矩陣列。 – Guangchun 2013-05-15 17:30:35

1

錯誤。 mat.data.ptr是無符號的字符 從 http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html

uchar* ptr;  // data pointer for an unsigned char matrix 

你應該使用

mat.data.i 

的整數

您正確初始化矩陣,但在打印錯了,因爲使用了錯誤的指針的數據結構。

CvMat      // 2D array 
    |-- int type;   // elements type (uchar,short,int,float,double) and flags 
    |-- int step;   // full row length in bytes 
    |-- int rows, cols; // dimensions 
    |-- int height, width; // alternative dimensions reference 
    |-- union data; 
     |-- uchar* ptr;  // data pointer for an unsigned char matrix 
     |-- short* s;  // data pointer for a short matrix 
     |-- int* i;  // data pointer for an integer matrix 
     |-- float* fl;  // data pointer for a float matrix 
     |-- double* db;  // data pointer for a double matrix 

請參閱?這有幫助嗎?

+0

你似乎對這個問題比這裏寫的更多。您能否通過首先改善問題來爲此做出貢獻? – 2012-08-12 16:38:43

+0

正如我之前所說的,他聲明「ints」(每個4-8字節並使用mat.data.i)並使用其他類型的指針。 mat.data.ptr(每個無符號字符是1個字節) – 2012-08-12 16:51:35

+0

非常感謝你...我得到的是被宣佈爲一個int指針我有hav使用data.i,但你能解釋爲什麼遞增整數指針加1 4地址? int的大小隻有2個字節,所以它應該是地址+2。爲什麼它的地址是+4? – 2012-08-12 19:06:38

0

有你的代碼中的一些奇怪的問題。不幸的是,tuğrulbüyükışık的答案只是一半正確的。看看這些行:

// you reserve 9 integers on the stack (9*4=36bytes) 
int vals[]={1,2,3,4,5,6,7,8,9}; 

// declare a matrix of uchars. 3*3*1 byte = 9 bytes 
// Now, the matrix thinks it has only 9 bytes allocated. 
CvMat mat = cvMat(3,3,CV_8UC1,vals); 

// Now you read the values from the matrix. 
// You actually access all the 36 bytes, but if they weren't wrongly allocated 
// at first, you would have a out-of-bounds access. 
for(int i=0;i<mat.rows;i++) 
{ 
    int* ptr = (int*) (mat.data.ptr + i* mat.step); 
} 

必須將所有的數據轉換爲相同的格式:是int(4個字節),無論是UCHAR(1個字節)

int vals[]={1,2,3,4,5,6,7,8,9}; 
CvMat mat = cvMat(3,3,CV_32SC1,vals); // 32SC1 means signed integer, 32 bits 

OR

unsigned char vals[]={1,2,3,4,5,6,7,8,9}; 
CvMat mat = cvMat(3,3,CV_8UC1,vals); // 8UC1 means unsigned char, 8 bits 
+0

是的,我現在明白了...謝謝你的核心...現在我明白了爲什麼以前我得到3時,我打印墊的價值。步驟(因爲我使用CV_8UC1,矩陣被分配爲9個字節,每個元素一個=> 3個字節),現在我使用CV_32SC1,它爲每個元素分配4個字節=>一行12個字節... @tuğrulbüyükışık's – 2012-08-13 15:38:50

0

除了錯誤的用法(由huseyin tugrul buyukisik解釋),您的錯誤是您在使用時使用了錯誤的類型創建矩陣

int vals[] = {1,2,3,4,5,6,7,8,9}; 
CvMat mat = cvMat(3,3,CV_8UC1,vals); // WRONG TYPE! 

創建矩陣時應使用CV_32SC1(用於signed int)。

另外,訪問矩陣時,應該使用mat.ptr<int>(row)。 完整的示例:

int vals[] = {1,2,3,4,5,6,7,8,9}; 

// Fill matrix content without allocating new memory 
// Beware: changing the content of vals changes the content of mat and vice versa 
// Use correct type CV_32SC1 or let OpenCV find the correct one by using 
// CV_MAKETYPE(cv::DataDepth<int>::value, 1) instead 
cv::Mat mat = cv::Mat(3, 3, CV_32SC1, vals); 

// Print content 
for(int row = 0; row < mat.rows; row++) 
{ 
    int* rowPtr = mat.ptr<int>(row); 

    for(int col = 0; col < mat.cols; col++) 
     std::cout << rowPtr[col] << " "; 

    std::cout << std::endl; 
}