下面是一个OpenCV的小程序:
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
template<typename _Tp>
vector<_Tp> convertMat2Vector(const Mat &_t1f)
{
//_t1f.convertTo(t1f, CV_64F);
return (vector<_Tp>)(_t1f.reshape(1, 1));//通道数不变,按行转为一行
}
template<typename _Tp>
cv::Mat convertVector2Mat(vector<_Tp> v,int cn,int rows)
{
cv::Mat mat = cv::Mat(v);//将vector变成一列的mat
cv::Mat dest=mat.reshape(cn, rows);
cout << "dest=\n" << dest << endl;
return dest;
}
int main()
{
int arr[4][3] = { { 1, 1,1 },{ 2, 2,2 },{ 3, 3,3 },{ 4,4, 4 } };
cv::Mat srcData(4, 3, CV_8UC1, arr);
cout << "srcData=\n"<< srcData<< endl;
vector<uchar> v = convertMat2Vector<uchar>(srcData);
cv::Mat dest =convertVector2Mat<uchar>(v,1, 4);//函数里的dest和还回dest的结果为什么不一样的呀?
cout << "dest=\n" << dest << endl;
system("pause");
waitKey();
return 0;
}
运行结果:
问题是:各位大神啊,我这哪里出问题?为什么函数里的dest和还回的dest的结果值为什么不一样的呀?
因为第2个方法的mat对象会释放,而dest引用的数据是来自于mat,并没有拷贝数据,因此在mat没有释放的情况下是正常的,
之后引用的内存就被释放而成为野数据。另外你srcData也不对。修改如下:
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
template<typename _Tp>
vector<_Tp> convertMat2Vector(const Mat &_t1f)
{
//_t1f.convertTo(t1f, CV_64F);
return (vector<_Tp>)(_t1f.reshape(1, 1));//通道数不变,按行转为一行
}
template<typename _Tp>
cv::Mat convertVector2Mat(vector<_Tp> v,int cn,int rows)
{
cv::Mat mat = cv::Mat(v);//将vector变成一列的mat
cv::Mat dest=mat.reshape(cn, rows).clone();
cout << "dest=\n" << dest << endl;
return dest;
}
int main()
{
char arr[4][3] = { {1, 1, 1 },{ 2, 2, 2 },{ 3, 3, 3 },{ 4, 4, 4 } };
cv::Mat srcData(4, 3, CV_8UC1, arr);
cout << "srcData=\n"<< srcData<< endl;
vector<uchar> v = convertMat2Vector<uchar>(srcData);
cout << v.size() << endl;
cv::Mat dest =convertVector2Mat<uchar>(v,1, 4);//函数里的dest和还回dest的结果为什么不一样的呀?
cout << "dest=\n" << dest << endl;
system("pause");
waitKey();
return 0;
}
return dest1;
cv::Mat dest2 =convertVector2Mat
这句话的执行顺序是:
1、默认构造DEST2
2、以DEST1为源,赋值(operater=) 给DEST2
3、析构DEST1
不过大部份编译器为将其优化为:
1、以DEST1为源,拷贝构造给DEST2
2、析构DEST1
所以原因应该是CV:MAT未定义合适的拷贝构造函数所致。
如是这个原因,还会发生更有趣的事情:
在convertVector2Mat函数内部增加如下代码:
cv::Mat dest=mat.reshape(cn, rows);
cout << "dest=\n" << dest << endl;
cv::Mat dest2=dest
cout << "dest2=\n" << dest2 << endl;
这两个结果都应该不一样了。
解决办法有两个:
1、定义合适的拷贝构造函数与赋值函数。
2、改变实现形式,不再靠return赋值,而将结果能过 指针或引用 的参数返回。
我试了几次,如果convertVector2Mat里面是这样设置dest,可以返回:
Mat dest = (Mat_(4, 3) << 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4);
但如果这样设置,就返回不了:
int arr[4][3] = { { 1, 1, 1 }, { 2, 2, 2 }, { 3, 3, 3 }, { 4, 4, 4 } };
cv::Mat dest(4, 3, CV_8UC1, arr);
跟mat.reshape(cn, rows);是一个效果
我觉得应该跟动态分配有关系,这个是在接口内做的,建议你涉及动态分配的这些函数还是别用返回值来做。
输出如下:
srcData=
[ 1, 1, 1;
2, 2, 2;
3, 3, 3;
4, 4, 4]
12
dest=
[ 1, 1, 1;
2, 2, 2;
3, 3, 3;
4, 4, 4]
dest=
[ 1, 1, 1;
2, 2, 2;
3, 3, 3;
4, 4, 4]