一、保存Mat数据,使用UltraCompare比对,检测代码的正确性
Python:
np.array([img.shape[0], img.shape[1], img.shape[2]], dtype=np.int32).tofile("d:\\shape_py.bin")
img.tofile("d:\\data_py.bin") # 按行优先保存
C++:
void save_mat(cv::Mat mat) {
// 保存尺寸信息
std::ofstream shape_file("d:\\shape_cpp.bin", std::ios::binary);
int shape[3] = { mat.rows, mat.cols, mat.channels() };
shape_file.write(reinterpret_cast<char*>(shape), 3 * sizeof(int));
shape_file.close();
// 保存数据(按行优先保存)
std::ofstream data_file("d:\\data_cpp.bin", std::ios::binary);
data_file.write(reinterpret_cast<char*>(mat.data), mat.total() * mat.elemSize());
data_file.close();
}
二、打印Mat数据,直接比对
Python:
print(image)
C++:
void print_mat(cv::Mat mat)
{
//设定后续以科学计数法表示浮点数
cout.setf(ios::scientific);
for (int i = 0; i < mat.rows; ++i) {
for (int j = 0; j < mat.cols; ++j) {
double value = mat.at<double>(i, j);
std::cout << std::setprecision(8) << value << " ";
}
std::cout << std::endl;
}
}
三、打印vector
Python:print(...)
C++
// 打印vector<float>
void printVector(const std::vector<float>& vec) {
std::cout << "[";
for (size_t i = 0; i < vec.size(); ++i) {
std::cout << vec[i];
if (i != vec.size() - 1) {
std::cout << ", ";
}
}
std::cout << "]" << std::endl;
}
// 打印vector<pair<float, float>>
void printVectorOfPairs(const std::vector<std::pair<float, float>>& vec) {
std::cout << "[";
for (size_t i = 0; i < vec.size(); ++i) {
std::cout << "(" << vec[i].first << ", " << vec[i].second << ")";
if (i != vec.size() - 1) {
std::cout << ", ";
}
}
std::cout << "]" << std::endl;
}
四、C++库
onnxruntime,opencv,cnpy
五、辅助工具
DeepSeek,豆包
六、cv::Mat注意点
cv::Mat 是 OpenCV 中用于存储图像和矩阵数据的核心类,它采用 引用计数(Reference Counting) 机制来管理内存,以提高性能并减少不必要的拷贝。
-
cv::Mat的引用计数机制-
当
cv::Mat被赋值或传参时,默认是 浅拷贝(Shallow Copy),即只复制 头信息(header)(如尺寸、数据类型、指针等),而 不复制实际的像素数据。 -
多个
cv::Mat对象可以共享同一块内存,OpenCV 通过引用计数(refcount)来跟踪内存的使用情况。 -
当最后一个引用该内存的
cv::Mat被销毁时,OpenCV 才会释放这块内存。
-
-
问题场景:返回局部变量的
cv::Mat-
在你的代码中,
result是一个局部变量:cv::Mat result; cv::warpPerspective(image, result, matrix, dst_size); return std::make_tuple(result, ...); // 返回浅拷贝
-
当
perspective_transform()函数结束时,局部变量result会被销毁,但由于cv::Mat的引用计数机制:-
如果
result被浅拷贝到tuple,tuple中的cv::Mat仍然指向原数据。 -
当
result析构时,如果引用计数降为 0,内存会被释放。 -
但外部代码尝试访问
tuple中的cv::Mat时,可能访问到已释放的内存,导致 堆损坏(Heap Corruption) 或 断言失败(Debug Assertion)。
-
-
-
为什么
.clone()能解决问题?-
.clone()会执行 深拷贝(Deep Copy),即 分配新内存并复制所有像素数据,使返回的cv::Mat完全独立于原对象:return std::make_tuple(result.clone(), ...); // 返回深拷贝
-
这样:
-
tuple中的cv::Mat拥有自己的数据,不受局部变量result析构的影响。 -
避免了引用计数归零导致的内存释放问题。
-
-
5649

被折叠的 条评论
为什么被折叠?



