从std::vector高效创建OpenCV Mat的方法及优化问询
Mat from a std::vector Without Cloning First, a quick correction: in your example code, the type parameter 1 is incorrect for a std::vector<double>. You should use CV_64F (or CV_64FC1 for single-channel) to match the double-precision floating-point type—using an incorrect type will lead to undefined behavior.
Now, onto your core problem: avoiding the overhead of clone() when dealing with temporary std::vector instances, where the default non-copying Mat constructor would leave you with a dangling pointer once the vector is destroyed. Here are three efficient solutions, ordered by preference:
1. Generate Data Directly in the Mat (No Intermediate Vector)
The most efficient approach is to skip the std::vector entirely and work directly with the Mat's internal memory. This eliminates any intermediate data storage or copying:
cv::Mat create100x100Mat() { // Create a 100x100 single-channel double-precision Mat cv::Mat m(100, 100, CV_64F); // Get a pointer to the Mat's data double* dataPtr = m.ptr<double>(); // Fill the data directly (example using std::iota for sequential values) std::iota(dataPtr, dataPtr + m.total(), 0.0); // Return the Mat—its internal memory is managed automatically return m; }
This way, you avoid the overhead of allocating and copying the vector entirely. The Mat owns its memory, so returning it is safe and efficient.
2. Bind the std::vector to the Mat's Lifecycle
If you must use a std::vector (e.g., your data generation logic is already tied to it), you can attach the vector to the Mat as user data, ensuring the vector isn't destroyed until the Mat is. This lets you use the vector's memory directly without cloning:
cv::Mat createMatFromVector() { // Allocate the vector on the heap (so it outlives the function scope) auto* myData = new std::vector<double>(100 * 100); // Fill your vector with data here // ... // Create the Mat using the vector's data cv::Mat m(100, 100, CV_64F, myData->data()); // Set a custom cleanup callback: when the Mat is destroyed, delete the vector m.setUserdata(myData, [](void* ptr) { delete static_cast<std::vector<double>*>(ptr); }); return m; }
The Mat will now manage the vector's memory—when the Mat goes out of scope, the lambda callback runs, deleting the vector automatically. No cloning is needed, and you avoid dangling pointers.
3. Move Vector Data into the Mat (For Non-Primitive Types)
While this doesn't help with primitive types like double (since moving is identical to copying), if you're working with non-primitive types (e.g., custom structs), you can use std::move to transfer elements into the Mat without copying:
cv::Mat createMatFromMovedVector() { std::vector<MyCustomType> myData(100 * 100); // Populate myData... cv::Mat m(100, 100, CV_8UC(sizeof(MyCustomType))); // Adjust type to match your struct std::move(myData.begin(), myData.end(), m.begin<MyCustomType>()); return m; }
Again, this is only useful for types where moving is cheaper than copying—stick to the first two methods for primitive numeric types.
Key Takeaways
- Avoid temporary
std::vectorinstances with the non-copyingMatconstructor unless you explicitly manage the vector's lifecycle. - Directly writing to the
Mat's memory is the most efficient option when possible. - Use the user data callback to bind heap-allocated vectors to the
Matif you can't avoid using a vector.
内容的提问来源于stack exchange,提问作者abdolahS

