2016-07-28 9 views
7

Ich arbeite mit TIF Bilder mit vorzeichenbehafteten ganzzahligen Daten. Nach erfolgreichem Eingeben und Verarbeiten muss ich das Bild im selben Format ausgeben (Eingabe und Ausgabe * .tif Dateien).Integer CV_32S Bild mit OpenCV speichern

Für die Eingabe weiß ich, dass OpenCV nicht weiß, ob die Daten signiert oder unsigniert ist, so dass es unsigned annimmt. Die Verwendung von this trick löst dieses Problem (Wechsel des Typs cv::Mat von Hand).

Wenn ich jedoch das Bild ausgeben und es erneut laden, bekomme ich nicht das erwartete Ergebnis. Die Datei enthält mehrere Segmente (Gruppen von Pixeln), und das Format ist wie folgt (I dieses Format verwenden muß):

  • alle Pixel kein Segment gehören, den Wert -9999
  • alle Pixel Zugehörigkeit zu einem einzelnen Segment die gleiche positive ganze Zahl
  • (zB alle Pixel des ersten Segmentwert haben 1, zweite 2 etc)

und hier ist die EXA Code:

void ImageProcessor::saveSegments(const std::string &filename){ 
    cv::Mat segmentation = cv::Mat(workingImage.size().height, 
            workingImage.size().width, 
            CV_32S, cv::Scalar(-9999)); 

    for (int i=0, szi = segmentsInput.size(); i < szi; ++i){ 
     for (int j=0, szj = segmentsInput[i].size(); j < szj; ++j){ 
      segmentation.at<int>(segmentsInput[i][j].Y, 
           ssegmentsInput[i][j].X) = i+1; 
     } 
    } 
    cv::imwrite(filename, segmentation); 
} 

Sie können davon ausgehen, dass alle Variablen (z. workingImage, segmentsInput) existieren als globale Variablen.

Mit diesem Code, wenn ich das Bild eingab und die Werte untersuche, werden die meisten Werte auf 0 gesetzt, während diejenigen, die gesetzt sind, einen ganzen Bereich von ganzzahligen Werten haben (in meinem Beispiel hatte ich 20 Segmente).

+0

In welchem ​​Format speichern Sie Ihre Matrix? JPEG? – Sunreef

+0

@Sunreef wie ich in meiner ursprünglichen Frage gesagt habe, ist es alles im TIF-Format – penelope

+0

Sie können ganzzahlige Matrizen nicht direkt mit imwrite speichern. Die Dokumentation besagt: "Nur 8-Bit-Bilder (oder 16-Bit unsigniert (CV_16U) bei PNG, JPEG 2000 und TIFF) können einkanalig oder 3-kanalig (mit BGR-Kanalreihenfolge) mit gespeichert werden diese Funktion." – Sunreef

Antwort

1

Sie können Integermatrizen nicht direkt mit imwrite speichern. Wie the documentation besagt: "Nur 8-Bit (oder 16-Bit ohne Vorzeichen (CV_16U) im Falle von PNG, JPEG 2000 und TIFF) können einkanalige oder 3-Kanal-Bilder (mit 'BGR' Kanalreihenfolge) Bilder mit diesem gespeichert werden Funktion."

Allerdings, was Sie tun könnten, um Ihre CV_32S Matrix zu einem CV_8UC4 konvertieren und speichern Sie es als PNG ohne Komprimierung. Natürlich ist dies ein bisschen unsicher, da endianness ins Spiel kommt und Ihre Werte zwischen verschiedenen Systemen oder Compilern ändern können (besonders, da hier von Ganzzahlen mit Vorzeichen gesprochen wird). Wenn Sie immer das gleiche System und Compiler verwenden, können Sie diese verwenden:

cv::Mat segmentation = cv::Mat(workingImage.size().height, 
           workingImage.size().width, 
           CV_32S, cv::Scalar(-9999)); 
cv::Mat pngSegmentation(segmentation.rows, segmentation.cols, CV_8UC4, (cv::Vec4b*)segmentation.data); 
std::vector<int> params; 
params.push_back(CV_IMWRITE_PNG_COMPRESSION); 
params.push_back(0); 
cv::imwrite("segmentation.png", pngSegmentation, params); 
+0

Tyvm, ich werde es ausprobieren und sehen, wie das funktioniert, aber, wie diese Dateien verwendbar sein sollten Auch von anderer Software (zB der, die die originalen TIF-Dateien erzeugt hat), denke ich, dass ich mich am Ende vielleicht mit einem anderen Format begnügen muss – penelope

+0

Wenn Sie mit TIFF-Bildern arbeiten, reichen 16-Bit-Matrizen nicht aus ? Sie können diese mit imwrite speichern. @penelope – Sunreef

+0

@Sunreef meinst du mit endianness, dass das gespeicherte Bild als beschädigte Datei in anderen Systemen gesehen werden kann? –

0

ich auch opencv Matten als tifs speichern, aber ich `t die opencv tif-Lösung verwenden. Ich schließe die libtiff lib auf meinem eigenen (ich glaube, libtiff auch in opencv verwendet wird) und als Sie den folgenden Code verwenden können als TIFF

TIFF* tif = TIFFOpen("file.tif", "w"); 

     if (tif != NULL) { 
      for (int i = 0; i < pages; i++) 
      { 
       TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, TIFF_UINT64_T(x)); // set the width of the image        
       TIFFSetField(tif, TIFFTAG_IMAGELENGTH, TIFF_UINT64_T(y)); // set the height of the image       
       TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1); // set number of channels per pixel 
       TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32); // set the size of the channels 32 for CV_32F         
       TIFFSetField(tif, TIFFTAG_PAGENUMBER, i, pages); 
       TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); // for CV32_F 

       for (uint32 row = 0; row < y; row++) 
       { 
        TIFFWriteScanline(tif, &imageDataStack[i].data[row*x*32/ 8], row, 0); 
       } 
       TIFFWriteDirectory(tif); 
      } 
     } 

imageDataStack ist ein Vektor von cv :: Mat Objekte zu speichern. Dieser Code funktioniert für mich um Tiff Stacks zu speichern.