2017-07-17 15 views
1

vector<Mat>regionFeaMatregionFeaMat.size() == 81とします。つまり、regionFeaMatは81の等しいサイズの行列を持ち、regionFeaMat[0].rows==256regionFeaMat[0].cols==1です。 reginFeaMatvector<float> reginFeaVecに変換したいと思います。私は次のコードで試しましたが、私は間違った結果を得ました:ベクトル<Mat>をベクトル<float>に変換しますか?

vector<float> regionFeaVec; 
regionFeaVec.assign((float*)regionFeaMat[0].datastart, (float*)regionFeaMat[80].dataend); 

答えて

1

あなたはいくつか間違った仮定をしているようです。

std::vector

は、メモリ内に連続し、その要素を格納し、しかしcv::Matは、内部バッファへのポインタを含むヘッダ、そうvector<Mat>にのみポインタが連続して格納されている、いないマットデータそのものです。そのため、(float*)regionFeaMat[0].dataend(float*)regionFeaMat[80].datastartの間にあるメモリはランダムなゴミです。他のMatのデータが部分的に含まれていれば、それは純粋な運です。

上記のため、1つのライナーを他のベクターに割り当てることはできず、代わりに各マットを挿入する必要があります。特定のマットオブジェクトが連続している場合OpenCV docsごとに、各行はいくつかのケースで終わりにギャップが含まれていてもよいので、私は、チェックしています、その場合には、我々がする必要が

// prevent vector reallocation after each Mat insertion: 
regionFeaVec.reserve(regionFeaMat.size()*regionFeaMat[0].cols*regionFeaMat[0].rows); 
for (int i = 0; i < regionFeaMat.size(); ++i) 
{ 
    if (regionFeaMat[i].isContinuous()) 
     regionFeaVec.insert(
          regionFeaVec.end(), 
          (float*)regionFeaMat[i].datastart, 
          (float*)regionFeaMat[i].dataend 
          ); 
    else 
    { 
     for (int j = 0; j < regionFeaMat[i].rows; ++j) 
     { 
       const float* row = regionFeaMat[i].ptr<float>(j); 
       regionFeaVec.insert(regionFeaVec.end(), row, row + regionFeaMat[i].cols); 
     } 
    } 
} 

注:このような何かを試してみてください行ごとに行列を読みます。行列が連続している場合、我々は上記の参照ドキュメントごとに1次元ベクトルとして扱うことがあるので

このコードは、単純化することができます。

// prevent vector reallocation after each Mat insertion: 
regionFeaVec.reserve(regionFeaMat.size()*regionFeaMat[0].cols*regionFeaMat[0].rows); 
for (int i = 0; i < regionFeaMat.size(); ++i) 
{ 
    cv::Size size = regionFeaMat[i].size(); 
    if (regionFeaMat[i].isContinuous()) 
    { 
     size.width *= size.height; 
     size.height = 1; 
    } 
    for (int j = 0; j < size.height; ++j) 
    { 
     const float* row = regionFeaMat[i].ptr<float>(j); 
     regionFeaVec.insert(regionFeaVec.end(), row, row + size.width); 
    } 
} 

あなたは、より一般的なケースでは、ベクトル再割り当てを防止したい場合は、渡される要素の数を計算する方法をreserve()に変更する必要もあります。私が使用する方法では、すべてのMatオブジェクトがすべてのオブジェクトで等しい2つの次元しかないと仮定しています。

また、vector<float>に割り当てる場合は、regionFeaMatの要素タイプがCV_32Fであることを確認してください。

+0

ありがとうの男が、私は、 'regionFeaVec.insert(...)でこのエラーを持っている'行: '重大\tコード\t説明プロジェクト\tファイル\tライン\t抑制状態エラー(アクティブ)\tオーバーロードされた関数「のstdのインスタンス: :ベクトル<_Ty, _Alloc> :: insert [_Ty = float、_Alloc = std :: allocator ]は引数リストと一致します。 –

+1

ああ、私は間違いをしました。 Insertは最初の引数としてイテレータを取るので、size()ではなくend()が必要です。私の訂正された答えを見てください:) – KjMag

+1

cv :: Matは32ビット境界に行をパディングしますので、フロート型は連続していない可能性はありません –

関連する問題