cv::Mat转std::vector<double>数值异常及代码报错问题求助
Let's break down the two separate issues you're hitting, then walk through the fixes step by step:
1. Why You're Getting Tiny (~1e-180) Values
When you convert your image to grayscale with cvtColor(img, img, COLOR_RGB2GRAY), the resulting cv::Mat stores pixel data as 8-bit unsigned integers (CV_8U)—values from 0 to 255, not double.
Your first conversion code:
std::vector<double> imgvec; imgvec.assign(img.begin<double>(), img.end<double>());
forces OpenCV to interpret 8-bit byte data as 64-bit double values. This type mismatch reads the tiny 8-bit pixel patterns as full 64-bit doubles, which results in nonsensical, extremely small numbers.
2. Why the Second Code Snippet Throws a Compile Error
The shared code has two critical mistakes:
- You're trying to fetch a
double*pointer from aCV_8UMat—this is a type mismatch, since the underlying data isuchar, notdouble. - The
insertcall is malformed: you only pass an end pointer (img.ptr<double>(i) + img.cols), butinsertrequires a full range (start and end pointers/iterators).
The Correct Conversion Approach
Since your grayscale image is CV_8U, you need to explicitly convert each 8-bit pixel to a double during the transfer. Here's the fixed code, handling both continuous and non-continuous Mats:
std::vector<double> imgvec; imgvec.reserve(img.total()); // Preallocate space to avoid reallocations if (img.isContinuous()) { // For continuous Mats, process the entire data block in one go const uchar* data = img.data; for (size_t i = 0; i < img.total(); ++i) { imgvec.push_back(static_cast<double>(data[i])); } } else { // For non-continuous Mats, process each row individually for (int i = 0; i < img.rows; ++i) { const uchar* row_ptr = img.ptr<uchar>(i); for (int j = 0; j < img.cols; ++j) { imgvec.push_back(static_cast<double>(row_ptr[j])); } } }
Alternative: Use OpenCV's Built-in Conversion
If you prefer a more concise, OpenCV-native approach, first convert the CV_8U Mat to a CV_64F (double-precision) Mat, then copy to the vector:
cv::Mat img_double; img.convertTo(img_double, CV_64F); // Converts 0-255 uchar values to 0.0-255.0 doubles std::vector<double> imgvec; imgvec.assign(img_double.begin<double>(), img_double.end<double>());
This works because img_double now stores actual double values, so using begin<double>() and end<double>() is valid.
内容的提问来源于stack exchange,提问作者user7845839

