今天在寫代碼的時候遇到這樣一個問題
先來看個函數,這是一段更新subShape的函數:
void updateSubShape()
{
double sub_shape_01_brow_left_data[10] = {
mShape.part(17).x(),mShape.part(17).y(),
mShape.part(18).x(),mShape.part(18).y(),
mShape.part(19).x(),mShape.part(19).y(),
mShape.part(20).x(),mShape.part(20).y(),
mShape.part(21).x(),mShape.part(21).y()};
sub_shape_01_brow_left = cv::Mat(5, 2, CV_64FC1, sub_shape_01_brow_left_data);
double sub_shape_02_brow_right_data[10] = {
mShape.part(22).x(),mShape.part(22).y(),
mShape.part(23).x(),mShape.part(23).y(),
mShape.part(24).x(),mShape.part(24).y(),
mShape.part(25).x(),mShape.part(25).y(),
mShape.part(26).x(),mShape.part(26).y()};
sub_shape_02_brow_right = cv::Mat(5, 2, CV_64FC1, sub_shape_02_brow_right_data);
double sub_shape_03_eye_left_data[12] = {
mShape.part(36).x(),mShape.part(36).y(),
mShape.part(37).x(),mShape.part(37).y(),
mShape.part(38).x(),mShape.part(38).y(),
mShape.part(39).x(),mShape.part(39).y(),
mShape.part(40).x(),mShape.part(40).y(),
mShape.part(41).x(),mShape.part(41).y()};
sub_shape_03_eye_left = cv::Mat(6, 2, CV_64FC1, sub_shape_03_eye_left_data);
double sub_shape_04_eye_right_data[12] = {
mShape.part(42).x(),mShape.part(42).y(),
mShape.part(43).x(),mShape.part(43).y(),
mShape.part(44).x(),mShape.part(44).y(),
mShape.part(45).x(),mShape.part(45).y(),
mShape.part(46).x(),mShape.part(46).y(),
mShape.part(47).x(),mShape.part(47).y()};
......
sub_shape_04_eye_right = cv::Mat(6, 2, CV_64FC1, sub_shape_04_eye_right_data);
std::cout << "sub_shape_01_brow_left:" << sub_shape_01_brow_left << std::endl;
std::cout << "sub_shape_02_brow_right:" << sub_shape_02_brow_right << std::endl;
std::cout << "sub_shape_03_eye_left:" << sub_shape_03_eye_left << std::endl;
std::cout << "sub_shape_04_eye_right:" << sub_shape_04_eye_right << std::endl;
......
}
筆者在當前函數內打印出01,02,03,04四個Mat的信息如下:
sub_shape_01_brow_left:
[77, 83;
83, 78;
92, 77;
100, 79;
107, 84]
sub_shape_02_brow_right:[122, 86;
131, 84;
141, 85;
150, 90;
156, 97]
sub_shape_03_eye_left:[85, 96;
90, 95;
96, 96;
101, 99;
95, 100;
90, 99]
sub_shape_04_eye_right:[128, 103;
134, 102;
139, 103;
145, 106;
139, 106;
133, 106]
然而神奇的一幕來啦,當筆者在另外一個函數中調用上述函數,打印出01,02,03,04四個Mat的信息如下:
sub_shape_01_brow_left:
[77, 83;
83, 78;
92, 77;
100, 79;
107, 84]
sub_shape_02_brow_right:[122, 86;
131, 84;
141, 85;
150, 90;
156, 97]
sub_shape_03_eye_left:[85, 96;
1.197398590121304e-47, 95;
6.952696120312864e-310, 6.952696120312864e-310;
6.444060669718295e-316, 1.427990031124621e-316;
6.952696120331045e-310, 4.940656458412465e-324;
3.458459520888726e-323, 6.937713299605351e-310]
sub_shape_04_eye_right:[128.0001200092957, 6.444533391728236e-316;
6.444533391728236e-316, 6.444533391728236e-316;
6.444533391728236e-316, 6.444533638761059e-316;
6.444533737574188e-316, 6.444533391728236e-316;
6.444533737574188e-316, 0;
0, 0]
發現竟然01,02指向的Mat數據正確,03,04指向的數據就完全錯了,這是神馬情況。然而在cv::Mat(xxx)後添加.clone()後就可以解決上述問題。
原來Mat有淺拷貝和深拷貝的區分,cv::Mat C(xxx)只是一個淺拷貝的狀況,淺拷貝後的變量指針都會與Mat指向同一個內存地址,在上述函數中筆者使用了大量的cv::Mat(xxx)進行淺拷貝,筆者猜測應當是opencv在函數操作中對Mat的內存分配是存在一定限制的,由於筆者使用的cv::Mat(xxx)過多,已經超出了opencv的限制,因此在函數結束後,部分內存被自動釋放,所以導致了上述這個問題。而採用clone的深拷貝的方式,會完整的爲變量字段開闢一個屬於自己的內存空間,函數結束後,內存不能被自動釋放,所以不會出現上述問題。
由此可見,使用opencv的Mat,一定要深入理解淺拷貝和深拷貝的含義啊,clone也對於Mat變得無比重要。