2017-07-17 6 views
1

Angenommen, ich habe eine vector<Mat> namens regionFeaMat und regionFeaMat.size() == 81. Mit anderen Worten, regionFeaMat haben 81 gleich große Matrix und regionFeaMat[0].rows==256 und regionFeaMat[0].cols==1. Ich möchte reginFeaMat in vector<float> reginFeaVec konvertieren. Ich habe versucht mit folgendem Code, aber ich habe falsch Ergebnis:Wie konvertiert man Vektor <Mat> in Vektor ?

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

Antwort

1

Sie scheinen ein paar falsche Annahmen gemacht haben.

std::vector hat seine Elemente speichern aneinander angrenzend in einem Speicher, aber cv::Mat ist ein Header einen Zeiger auf seinen internen Puffer enthält, so nur Zeiger in vector<Mat> gespeichert sind aneinander angrenzend, nicht die Daten selbst, Mat. Aus diesem Grund ist der Speicher, der zwischen (float*)regionFeaMat[0].dataend und (float*)regionFeaMat[80].datastart liegt, ein zufälliger Müll - wenn er andere Mat-Daten teilweise enthält, ist es pures Glück.

Aufgrund der obigen Angaben können Sie keinen Vektor mit einem Liner zuordnen und müssen stattdessen jede Matte separat einfügen. Probieren Sie etwas wie folgt aus:

// 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); 
     } 
    } 
} 

Bitte beachte, dass ich überprüft habe, ob ein bestimmtes Objekt Mat kontinuierlich ist, weil nach OpenCV docs, jede Zeile Lücken am Ende in einigen Fällen enthalten kann, und in diesem Fall müssen wir Lesen Sie die Matrix Zeile für Zeile.

Dieser Code kann vereinfacht werden, denn wenn Matrix kontinuierlich ist, können wir es als 1D-Vektor gemäß den oben genannten Dokumente behandeln kann:

// 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); 
    } 
} 

Wenn Sie Vektor Umschichtung in allgemeineren Fällen verhindern wollen, Sie müssen auch die Berechnungsmethode für die Anzahl der Elemente ändern, die an reserve() übergeben werden. Die von mir verwendete Methode geht davon aus, dass alle Mat-Objekte nur zwei Dimensionen haben, die für alle Objekte gleich sind, da Sie so Ihr Problem beschrieben haben.

Auch wenn Sie es vector<float> zuweisen möchten, stellen Sie sicher, dass der Elementtyp regionFeaMatCV_32F ist.

+0

thanx Mann, aber ich habe diesen Fehler in 'regionFeaVec.insert (...)' line: 'Severity \t-Code \t Beschreibung Projekt \t Datei \t Linie \t Unterdrückungszustand Fehler (aktiv) \t keine Instanz von überladener Funktion„std: : vector <_Ty, _Alloc> :: einfügen [mit _Ty = float, _Alloc = std :: allocator ] "entspricht der Liste der Argumente" –

+1

Oh, ich sehe, ich habe einen Fehler gemacht. Einfügen nimmt Iterator als erstes Argument, also sollte end(), nicht size() sein. Siehe meine korrigierte Antwort :) – KjMag

+1

cv :: Mat puffs Zeilen zu einer 32-Bit-Grenze, so ist es unwahrscheinlich, dass ein Float-Typ nicht zusammenhängend wäre –

Verwandte Themen