Mat::copyTo()
はディープコピーですが、代入演算子はディープコピーではないことがわかります。私の質問:
cv::Mat func()
などの関数からcv::Mat
を返すにはどうすればよいですか?
ドキュメントによると、cv::Mat
を返すと、その関数のcv::Mat
のローカルコピーが返された後、その関数のcv::Mat
のローカルコピーが破棄されるため、返される値を受け入れるため、使用できません。関数の外側は、ランダムなアドレスを指している必要があります。奇妙なことは、(ほとんどの場合)正しく動作することです。たとえば、次のように機能します。
cv::Mat CopyOneImage(const cv::Mat& orgImage)
{
cv::Mat image;
orgImage.copyTo(image);
return image;
}
int main()
{
std::string orgImgName("a.jpg");
cv::Mat orgImage;
orgImage = cv::imread(orgImgName);
cv::Mat aCopy;
aCopy = CopyOneImage(orgImage);
return 1;
}
しかし、なぜ?ディープコピーではありません。
質問3.また、割り当て演算子もディープコピーのように見える場合があります。
int main()
{
std::string orgImgName("a.jpg");
cv::Mat orgImage;
orgImage = cv::imread(orgImgName);
cv::Mat aCopy;
orgImage.copyTo(aCopy);
cv::Mat copyCopy1;
copyCopy1 = aCopy;
cv::namedWindow("smallTest", 1);
cv::imshow("smallTest", copyCopy1);
uchar key = (uchar)cv::waitKey();
cv::Mat orgImage2 = cv::imread("b.jpg");
orgImage2.copyTo(aCopy);
cv::imshow("smallTest", copyCopy1);
return 1;
}
次に、2つのディスプレイに同じ画像a.jpgが表示されます。どうして?また、他の場合には機能しません。 (元のコードは長すぎますが、上記の場合に単純化することもできます)。当時、割り当て演算子は実際には「浅い」コピーのようです。どうして?
どうもありがとう!
割り当ての使用は、マトリックスコピーの最良の方法ではないと思います。マトリックスの新しい完全なコピーが必要な場合は、次を使用します。
Mat a=b.clone();
他のマトリックスからのデータを置き換えるためにマトリックスをコピーしたい場合(メモリの再割り当てを避けるため):
Mat a(b.size(),b.type());
b.copyTo(a);
1つのマトリックスを他のマトリックスに割り当てると、マトリックスデータへのスマートポインターの参照のカウンターが1つ増加し、マトリックスを解放すると(コードブロックを離れるときに暗黙的に実行できます)、1つ減少します。ゼロに等しくなると、割り当てられたメモリの割り当てが解除されます。
関数使用リファレンスから結果を取得したい場合は、より高速です:
void Func(Mat& input,Mat& output)
{
somefunc(input,output);
}
int main(void)
{
...
Mat a=Mat(.....);
Mat b=Mat(.....);
Func(a,b);
...
}
私はしばらくの間OpenCVを使用してきましたが、cv :: Matも私を混乱させたので、読書をしました。
cv :: Matは、実際の画像データを保持する* dataポインターを指すヘッダーです。また、参照カウントも実装します。現在* dataポインターを指している_cv::Mat
_ヘッダーの数を保持します。したがって、次のような通常のコピーを実行する場合:
_cv::Mat b;
cv::Mat a = b;
_
a
はb
のデータをポイントし、その参照カウントがインクリメントされます。同時に、以前にb
でポイントされたデータの参照カウントが減らされます(減分後に0の場合、メモリは解放されます)。
質問1:プログラムによって異なります。詳細については、この質問を参照してください: is-cvmat-class-flawed-by-design
質問2:関数は値で戻ります。つまり、_return image
_はマットをコピーし、参照カウントを増やし(現在はref_count = 2)、新しいマットを返します。関数が終了すると、イメージは破棄され、ref_countは1つ減ります。ただし、ref_countが0ではないため、メモリは解放されません。したがって、返されるcv :: Matはランダムなメモリ位置を指していません。
質問3:同様のことが起こります。 orgImage2.copyTo(aCopy);
と言うと、aCopy
が指すデータのref_countは減少します。次に、コピーされる新しいデータを保存するために新しいメモリが割り当てられます。そのため、_copyCopy1
_はこれを行ったときに変更されませんでした。
C++ 11を見てください std :: shared_ptr 参照カウンターcv :: Matを使用することで、同じ方法で効果的に動作します。自動的に解放されます。つまり、メモリの割り当てが解除され、cv :: Matは使用できなくなります。これは事実上「浅いコピー」であり、大量のメモリの割り当て/割り当て解除でリソースを節約します。
一方、cv :: Mat :: cloneは、マトリックスの常駐する新しいメモリブロック全体を割り当てる「ディープコピー」を提供します。これは、必要な画像に変換を行う場合に役立ちます。ただし、元に戻すと、メモリの割り当て/割り当て解除により多くのリソースが必要になります。
これが誰かを助けることを願っています。