OpenCV C 接口函數 cvmGet 僅支持單通道浮點型矩陣(32F/64F),對 8U(無符號 8 位)等整數類型矩陣調用會導致運行時崩潰(R6010 abort)。本文說明原因並給出正確訪問方式。
CvMat* mat = cvCreateMat(100, 100, CV_8UC1); // 8U 類型
double val = cvmGet(mat, 10, 10); // 崩潰:R6010 abort()
cvmGet 官方文檔明確聲明:
Returns the particular element of single-channel floating-point matrix.
內部實現直接按 float* 或 double* 解引用數據指針,8U 類型數據佈局不匹配,導致非法內存訪問。
CvMat* mat = cvCreateMat(100, 100, CV_8UC1);
// 獲取行指針
uchar* ptr = (uchar*)cvPtr1D(mat, row, NULL);
// 訪問列
uchar value = ptr[col];
// 或一行代碼
uchar value = ((uchar*)(mat->data.ptr + row * mat->step))[col];
cv::Mat mat(100, 100, CV_8UC1);
uchar value = mat.at(row, col); // 編譯期類型檢查
mat.at(row, col) = 255; // 寫入
CvScalar s = cvGet2D(mat, row, col);
uchar value = (uchar)s.val[0];
| OpenCV 類型 | C 對應類型 | C++ 對應類型 | cvmGet 支持 |
|---|---|---|---|
| CV_8U / CV_8UC1 | uchar / unsigned char | uchar | ❌ |
| CV_16U | ushort | ushort | ❌ |
| CV_32S | int | int | ❌ |
| CV_32F | float | float | ✅ |
| CV_64F | double | double | ✅ |
// 舊代碼(C 接口)
IplImage* img = cvLoadImage("test.jpg");
CvMat* mat = cvCreateMat(img->height, img->width, CV_32FC1);
cvConvert(img, mat);
double v = cvmGet(mat, 10, 10);
// 新代碼(C++ 接口)
cv::Mat img = cv::imread("test.jpg", cv::IMREAD_GRAYSCALE);
img.convertTo(img, CV_32F); // 如需浮點
float v = img.at(10, 10); // 類型安全、IDE 提示、無崩潰風險
cvmGet 僅限單通道浮點矩陣(32F/64F)。8U/16U/32S 等整數類型必須使用指針運算(C 接口)或 Mat::at<>()(C++ 接口)。強烈建議新項目全面遷移至 C++ cv::Mat,享受類型安全、自動內存管理、現代 C++ 特性。