DICOM-Image lesen (evt Framework)



  • Hallo liebe Community,

    ich habe die Aufgabe im Rahmen meiner Bachelor arbeit unter anderem Medizinische Bilddaten in Form von *.dcm-Dateien (DICOM) zu lesen und zu verarbeiten.

    Da der DICOM-Standard allerdings laut meinen Recherchen alles andere als ein vernünftiger Standard ist wollte ich gerne auf ein Framework unter der GPL zurückgreifen.

    Allerdings schein ich zu blöd zu sein so ein Framework zu verwenden (Oder sie funktionieren einfach nicht aber ich denke eher, dass ich zu blöd bin ^^).

    Beispiele:
    DICOMParser (wird scheinbar von ITK und VTK benutzt, und der ITK-DICOM-Reader soll sehr gut sein.)
    Link: http://sourceforge.net/projects/dicomparser/

    Habe es mit der normalen Vorgehensweise probiert.
    CMake - VSStudio build - header in die include path und lib (nur ITKDICOMParser.lib vorhanden - kA ob das richtig ist) in die linker path reingepackt.

    und es funktioniert nicht.

    Meine Anforderungen an das Framework:
    - Minimalistisch (Nur zuverlässiges lesen von DICOM und DICOMDIR)
    - freeware (GPL)
    - für c++

    Meine Umgebung:
    - VS2012
    - c++
    - opengl 4.3
    - glfw3
    - glew
    - Windows7 64-Bit

    Falls jemand von Euch mir helfen kann das Framework ans laufen zu kriegen, oder ein alternatives Framework oder sonstiges kennt, das mir weiterhelfen kann wäre ich Euch sehr dankbar.

    Grüße

    Jango


  • Mod

    so ein ausfuehrlicher text und das ist deine fehlerbeschreibung?

    JangoK schrieb:

    ...
    und es funktioniert nicht.
    ...

    😕



  • JangoK schrieb:

    Da der DICOM-Standard allerdings laut meinen Recherchen alles andere als ein vernünftiger Standard ist wollte ich gerne auf ein Framework unter der GPL zurückgreifen.

    Huh?
    Vernünftig? Das Ding war wegweisend! Da haben andere noch keinen Plan von offenen(!) Standards und Interoperabilität gehabt, und ein "paar Ärzte und Informatiker" hauen so ein Ding raus.
    Aber Deine Schlußfolgerung für DICOM etwas fertiges zu benutzen ist natürlich richtig.

    Stell eine konkrete Frage - mit einem konkreten Problem.

    PS: Schon auf die OFFIS Implementierung geschaut?



  • Sorry wenn die Frage etwas ungenau gestellt war.

    Meine erste Frage ist, kennt jemand ein Framework, welches meine Minimalistischen Anforderungen erfüllt ohne großen Overhead. (Nur DICOM und DICOMDIR lesen)

    Falls wir dann wieder beim DICOMParser landen, erkläre ich Step-By-Step mein vorgehen und Poste meine Fehlermeldungen - ihr könnt mir dann vllt sagen was ich falsch machen.

    @ rapso - Die genauen Fehlerbeschreibungen kommen dann, sobald ich weiß welches Framework ich jetzt wirklich einbinde. Und daran dann verzweifel ^^

    Mit freundlichen Grüßen

    Jango

    PS: Falls du DCMTK meinst, ja das hatte ich mir auch schonmal angeguckt, allerdings hat das für meine anforderungen einen riesen overhead.
    Und ich habs auch nicht ans laufen gekriegt 😃



  • Ich habe DCMTK zum Laufen gekriegt. War etwas anstrengend aber jetzt kenne ich die Stolperfallen. Und ja, DICOM ist ein schrecklicher Standard, wenn man eine konkrete Frage zu irgendeinem Feld hat ist man aufgeschmissen. Die öffentlich zugänglichen DICOM-Viewer sind außerdem sehr verbugt und korrekte Beispiele für DICOM-Dateien zu finden ist kaum möglich (das DICOM Validation Tool hat mir geholfen). DCMTK hat eine fertige Binary, die eine DICOM-Datei in XML umwandelt. Das sind nur ein paar kb und mit XML kann man sehr viel besser umgehen.



  • Okay, dann sollte ich mir das DCMTK vllt doch nochmal genauer anschauen.

    Meine Aufgabe ist folgende.

    Ich habe 2 DICOM-Datensätze.
    1. Ein 2D-DICOM Bild
    2. Ein 3D-DICOM Datensatz

    In diesen Beiden Datensätzen sollen markante Punkte markiert und automatisiert übereinander gelegt werden.

    Ich brauche also die Pixelwerte des 2D-Bildes und die Metainformationen (Slices usw) des 3D-Datensatzes.

    Alles weitere (Datensatz in 3D darstellen, picking, rotation, ...) wollte ich in OpenGL machen.

    Da ich sehr Objekt-Orientiert Arbeite hätte ich jetzt eigentlich nur gerne irgendwas, das ich includen kann und mit hilfe dessen ich mir dann die Oben genannten Informationen z.B. mit Obj->GetSlices() oder so aus den Daten ziehen kann.

    Die fertigen binaries von DCMTK sind alles exe datein...
    Hab kA wie ich damit umgehen soll ^^

    Ist DCMTK dafür gut geeignet oder vllt doch lieber was anderes?
    Wenn ja, wie benutzte ich die binaries(.exe) im Quellcode oder ist es doch besser den source selbst zu builden?!

    Gruß

    Jango



  • Die Holzhammermethode unter Windoof ist system("dcm2xml +Wb inputfile outputfile");
    Unter Linux schreibt man halt noch wine davor 🙄
    Man beachte das +Wb, normalerweise werden die Binärdaten (Pixeldaten) nicht ins XML exportiert. Wahrscheinlich willst du an den anderen Parametern auch noch rumtweaken.
    Ich würde nicht sagen, dass DCMTK für dein Vorhaben gut geeignet ist. Es ist Overkill, inperformant und unnötig schwer zu benutzen. Ich würde aber auch sagen, dass du kaum was besseres finden wirst.
    Da es in deiner Bacherlorarbeit ja nicht ums DICOM-parsen geht sollte es aber annehmbar sein.



  • Ich habe jetzt sowohl den DICOMParser, als auch DCMTK zumindest mal einbinden können.

    Sprich ich habe die Source-Dateien herunter geladen, CMake drüber gejagt und die gebuilded mit VS2012.

    Konnte sie dann auch ohne größere Probleme einbinden.
    Allerdings kann der DICOMParser scheinbar noch weniger als man vermutet und das DCMTK krieg ich noch nicht richtig ans laufen

    Folgender Code

    #include "dcfilefo.h"
    #include "dctagkey.h"
    #include "dcdeftag.h"
    #include "ofcond.h"
    #include "ofstring.h"
    #include <iostream>
    
    using namespace std;
    
    void main() {
    	DcmFileFormat fileformat;
    	OFCondition status = fileformat.loadFile("C:\\Users\\Kleinmanns\\Documents\\Visual Studio 2012\\Projects\\GammaKnife\\GammaKnife\\images\\Fall1\\PA erster\\00053");
    	if (status.good())
    	{
    	  OFString patientName;
    	  if (fileformat.getDataset()->findAndGetOFString(DCM_PatientName, patientName).good())
    	  {
    		cout << "Patient's Name: " << patientName << endl;
    	  } else
    		cerr << "Error: cannot access Patient's Name!" << endl;
    	} else
    	  cerr << "Error: cannot read DICOM file (" << status.text() << ")" << endl;
    }
    

    Alles was in der main methode steht ist aus nem Beispiel aus der DCMTK-Doku kopiert.

    Die includes sind anhand von Fehlermeldungen mühsam zusammen gekratzt, da es ja scheinbar mode ist Beispiele ohne die nötigen includes online zu stellen 😕 😕

    Aus irgendlwelchen Gründen die ich nicht verstehe sind in die Header-Dateien die includes mit einem .h ausgestattet. (Beispiel #inlcude <iostream.h>
    Was natürlich Fehlermeldungen wirft.

    Entferne ich diese im DCMTK eigenen Code bleibt folgende Fehler-Meldung übrig.

    1>------ Erstellen gestartet: Projekt: DCMTKTest, Konfiguration: Debug Win32 ------
    1>  main.cpp
    1>c:\users\(zensiert)\downloads\dcmtk-3.6.0\ofstd\include\dcmtk\ofstd\ofstream.h(92): fatal error C1004: Unerwartetes Dateiende gefunden.
    ========== Erstellen: 0 erfolgreich, 1 fehlerhaft, 0 aktuell, 0 übersprungen ==========
    

    Entferne ich diese nicht

    1>------ Erstellen gestartet: Projekt: DCMTKTest, Konfiguration: Debug Win32 ------
    1>  main.cpp
    1>c:\users\(zensiert)\downloads\dcmtk-3.6.0\ofstd\include\dcmtk\ofstd\ofstream.h(67): fatal error C1083: Datei (Include) kann nicht geöffnet werden: "iostream.h": No such file or directory
    ========== Erstellen: 0 erfolgreich, 1 fehlerhaft, 0 aktuell, 0 übersprungen ==========
    

    Wo liegt der Fehler? ^^

    Gruß

    Jango

    PS: würde es sich evt sogar rentieren VTK/ITK zu verwenden?
    BZW ist es überhaupt möglich VTK/ITK code in die OpenGL-Rendering-Pipeline ein zu bauen?

    Die haben ja ne eigene Rendering pipeline?!?!



  • Leider habe ich hier eine andere Toolchain (g++).
    Aber Deinen Code bekomme ich zum laufen.

    #include <iostream>
    
    #include "dcmtk/dcmdata/dcfilefo.h"
    #include "dcmtk/dcmdata/dctagkey.h"
    #include "dcmtk/dcmdata/dcdeftag.h"
    #include "dcmtk/ofstd/ofcond.h"
    #include "dcmtk/ofstd/ofstring.h"
    
    using namespace std;
    
    int main() {
      const char* file = "/tmp/Case22 [Case22]/"
        "20071030 021043 [ - MAMMOGRAM DIGITAL DX BILAT]/Series 71100000 [MG - L CC]/"
        "1.3.6.1.4.1.5962.99.1.2280943358.716200484.1363785608958.480.0.dcm";
      DcmFileFormat fileformat;
      OFCondition status = fileformat.loadFile(file);
      if (status.good())
        {
          OFString patientName;
          if (fileformat.getDataset()->findAndGetOFString(DCM_PatientName, patientName).good())
    	{
    	  cout << "Patient's Name: " << patientName << endl;
    	} else
            cerr << "Error: cannot access Patient's Name!" << endl;
        } else
        cerr << "Error: cannot read DICOM file (" << status.text() << ")" << endl;
    }
    
    g++ -std=c++11 -Wall -pedantic -g -otest test.cc -I/tmp/dcmtk/include/  -L/tmp/dcmtk/lib/ -lz -ldcmdata -loflog -lofstd -lpthread
    

    Mit diesen Mammo Bildern (131MB!), kommt da (wenig überraschend):

    Patient's Name: Case22
    

    Zum Thema <iostream.h> steht was unter "Known limitations of DCMTK on the Windows platform." in der Dokumentation.

    Bonne chance!



  • Dann bin ich schonmal beruhigt, dass es an meiner Unfähigkeit liegt 😉

    Ich probier mal nen bisl rum mit der Info in der doku und berichte.

    EDIT: Ich seh grad, dass die Einstellungen in der osconfig.h schon so vorgenommen sind, dass es auf die neue Schreibweise passt. 😞

    EDIT2: Mir ist gerade bei der Analyse deines Codes aufgefallen, dass du lediglich /tmp/dcmtk/includes/ als zusätzliche include-Pfade an deinen Compiler übergibst.

    Wenn ich DCMTK builde habe ich allerdings einen dcmtk-Orderner der Unterordner wie z.B.
    -dcmdata
    -dcmimage
    -dcmimgle
    -dcmjpeg
    -...
    enthält.
    und jeder dieser Unterordner hat eigenen "include" ordner.

    Hast du dir die selbst zusammen kopiert, oder hab ich was falsch gemacht?

    Zur Sicherheit hier nochmal mein vorgehen.

    1: ftp://dicom.offis.de/pub/dicom/offis/software/dcmtk/dcmtk360/dcmtk-3.6.0.tar.gz
    Herunterladen

    2: entpacken

    3: CMake Starten
    - input folder dcmtk-3.6.0
    - output folder dcmtk-bin

    Configure mit dem VS2012 Compiler (VS11)

    EXE (dcmtk-exe) und LIB(dcmtk-lib) part angeben - ansonsten hab ich an den Einstellungen nichts geändert

    4: Erneut configure drücken damit die Einstellungen gespeichert werden
    5: Generate

    6: Ins verzeichnis dcmtk-bin gehen
    7: *.sln mit VS2012 Öffnen und Projekt neu Erstellen (müsste dem make all entsprechen - dcmtk-lib und dcmtk-exe werden erstellt)

    8: Projekt Anlegen
    9: dcmtk-3.6.0 alle nötigen include Pfade setzten
    10: Lib such-Pfad auf dcmtk-lib erweitern
    11: Libs dem projekt hinzufügen

    Los Proggen glücklich sein, dass Nichts funktioniert 😃

    Gruß



  • Oha!
    Ich sollte vielleicht noch sagen, dass ich den "neuesten Snapshot" (dcmtk-3.6.1_20131114.tar.gz) benutzt habe.



  • Oh du hast ja schon wieder was gepostet 😃

    Ich hab meinen vorherigen Beitrag editiert, ich zitiere es eben nochmal.

    Wäre nett wenn du mal drüber schauen könntest, ob ich mir nen groben schnitzer geleistet hab.

    JangoK schrieb:

    EDIT2: Mir ist gerade bei der Analyse deines Codes aufgefallen, dass du lediglich /tmp/dcmtk/includes/ als zusätzliche include-Pfade an deinen Compiler übergibst.

    Wenn ich DCMTK builde habe ich allerdings einen dcmtk-Orderner der Unterordner wie z.B.
    -dcmdata
    -dcmimage
    -dcmimgle
    -dcmjpeg
    -...
    enthält.
    und jeder dieser Unterordner hat eigenen "include" ordner.

    Hast du dir die selbst zusammen kopiert, oder hab ich was falsch gemacht?

    Zur Sicherheit hier nochmal mein vorgehen.

    1: ftp://dicom.offis.de/pub/dicom/offis/software/dcmtk/dcmtk360/dcmtk-3.6.0.tar.gz
    Herunterladen

    2: entpacken

    3: CMake Starten
    - input folder dcmtk-3.6.0
    - output folder dcmtk-bin

    Configure mit dem VS2012 Compiler (VS11)

    EXE (dcmtk-exe) und LIB(dcmtk-lib) part angeben - ansonsten hab ich an den Einstellungen nichts geändert

    4: Erneut configure drücken damit die Einstellungen gespeichert werden
    5: Generate

    6: Ins verzeichnis dcmtk-bin gehen
    7: *.sln mit VS2012 Öffnen und Projekt neu Erstellen (müsste dem make all entsprechen - dcmtk-lib und dcmtk-exe werden erstellt)

    8: Projekt Anlegen
    9: dcmtk-3.6.0 alle nötigen include Pfade setzten
    10: Lib such-Pfad auf dcmtk-lib erweitern
    11: Libs dem projekt hinzufügen

    Los Proggen glücklich sein, dass Nichts funktioniert 😃

    Habe mir jetzt auch mal eben den 3.6.1 herunter geladen - wenn du keinen groben schnitzer findest werde ich die o.g. anweisungen nochmal mit dem durchgehen

    Gruß



  • Wie gesagt: ich bin hier mit Linux und Gedöns unterwegs. Von daher kann ich nicht viel beisteuern.
    Was Du beschreibst scheint aber "ziemlich genau"(TM) dem zu entsprechen, was in der Anleitung steht. 🙂



  • Hab jetzt mal alles mit Version 3.6.1 probiert und die selben libs gelinkt wie du.

    Außerdem habe ich alle includes in einen ordner rein Kopiert, damit das mit den Such Pfaden für den Compiler einfacher klappt.

    Kriege nun folgende Fehlermeldung

    1>------ Erstellen gestartet: Projekt: DCMTKTest, Konfiguration: Debug Win32 ------
    1>  main.cpp
    1>c:\users\kleinmanns\documents\visual studio 2012\projects\dcmtk\include\dcmtk\oflog\tracelog.h(59): error C2678: Binärer Operator '+': Es konnte kein Operator gefunden werden, der einen linksseitigen Operanden vom Typ 'const wchar_t [8]' akzeptiert (oder keine geeignete Konvertierung möglich)
    1>          c:\users\kleinmanns\documents\visual studio 2012\projects\dcmtk\include\dcmtk\ofstd\ofstring.h(867): kann 'OFString operator +(const OFString &,const OFString &)' sein
    1>          c:\users\kleinmanns\documents\visual studio 2012\projects\dcmtk\include\dcmtk\ofstd\ofstring.h(874): oder "OFString operator +(const char *,const OFString &)"
    1>          c:\users\kleinmanns\documents\visual studio 2012\projects\dcmtk\include\dcmtk\ofstd\ofstring.h(881): oder "OFString operator +(char,const OFString &)"
    1>          c:\users\kleinmanns\documents\visual studio 2012\projects\dcmtk\include\dcmtk\ofstd\ofstring.h(888): oder "OFString operator +(const OFString &,const char *)"
    1>          c:\users\kleinmanns\documents\visual studio 2012\projects\dcmtk\include\dcmtk\ofstd\ofstring.h(895): oder "OFString operator +(const OFString &,char)"
    1>          bei Anpassung der Argumentliste '(const wchar_t [8], dcmtk::log4cplus::tstring)'
    1>c:\users\kleinmanns\documents\visual studio 2012\projects\dcmtk\include\dcmtk\oflog\tracelog.h(64): error C2678: Binärer Operator '+': Es konnte kein Operator gefunden werden, der einen linksseitigen Operanden vom Typ 'const wchar_t [8]' akzeptiert (oder keine geeignete Konvertierung möglich)
    1>          c:\users\kleinmanns\documents\visual studio 2012\projects\dcmtk\include\dcmtk\ofstd\ofstring.h(867): kann 'OFString operator +(const OFString &,const OFString &)' sein
    1>          c:\users\kleinmanns\documents\visual studio 2012\projects\dcmtk\include\dcmtk\ofstd\ofstring.h(874): oder "OFString operator +(const char *,const OFString &)"
    1>          c:\users\kleinmanns\documents\visual studio 2012\projects\dcmtk\include\dcmtk\ofstd\ofstring.h(881): oder "OFString operator +(char,const OFString &)"
    1>          c:\users\kleinmanns\documents\visual studio 2012\projects\dcmtk\include\dcmtk\ofstd\ofstring.h(888): oder "OFString operator +(const OFString &,const char *)"
    1>          c:\users\kleinmanns\documents\visual studio 2012\projects\dcmtk\include\dcmtk\ofstd\ofstring.h(895): oder "OFString operator +(const OFString &,char)"
    1>          bei Anpassung der Argumentliste '(const wchar_t [8], dcmtk::log4cplus::tstring)'
    1>c:\users\kleinmanns\documents\visual studio 2012\projects\dcmtk\include\dcmtk\oflog\logmacro.h(107): error C2665: "dcmtk::log4cplus::Logger::getInstance": Durch keine der 2 Überladungen konnten alle Argumenttypen konvertiert werden.
    1>          c:\users\kleinmanns\documents\visual studio 2012\projects\dcmtk\include\dcmtk\oflog\logger.h(112): kann 'dcmtk::log4cplus::Logger dcmtk::log4cplus::Logger::getInstance(const dcmtk::log4cplus::tstring &)' sein
    1>          bei Anpassung der Argumentliste '(const dcmtk::log4cplus::tchar *)'
    ========== Erstellen: 0 erfolgreich, 1 fehlerhaft, 0 aktuell, 0 übersprungen ==========
    

    Diese lässt sich beheben, wenn ich den Zeichensatz nicht mehr auf UNICODE stehen habe.

    Dann kommt aber natürlich direkt eine neue Fehlermeldung 😉

    1>------ Erstellen gestartet: Projekt: DCMTKTest, Konfiguration: Debug Win32 ------
    1>  main.cpp
    1>dcmdata.lib(dcuid.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "_Netbios@4" in Funktion ""unsigned char * __cdecl getMACAddress(unsigned char * const)" (?getMACAddress@@YAPAEQAE@Z)".
    1>dcmdata.lib(dcuid.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "_gethostbyname@4" in Funktion ""long __cdecl gethostid(void)" (?gethostid@@YAJXZ)".
    1>ofstd.lib(ofstd.obj) : error LNK2001: Nicht aufgelöstes externes Symbol "_gethostbyname@4".
    1>dcmdata.lib(dcuid.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "_gethostname@8" in Funktion ""long __cdecl gethostid(void)" (?gethostid@@YAJXZ)".
    1>dcmdata.lib(dcuid.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "_WSAStartup@8" in Funktion ""long __cdecl gethostid(void)" (?gethostid@@YAJXZ)".
    1>dcmdata.lib(dcuid.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "_WSACleanup@0" in Funktion ""long __cdecl gethostid(void)" (?gethostid@@YAJXZ)".
    1>oflog.lib(oflog.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__WSAStartup@8" in Funktion ""void __cdecl OFLog_init(void)" (?OFLog_init@@YAXXZ)".
    1>oflog.lib(winsock.obj) : error LNK2001: Nicht aufgelöstes externes Symbol "__imp__WSAStartup@8".
    1>oflog.lib(winsock.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__accept@12" in Funktion ""int __cdecl dcmtk::log4cplus::helpers::acceptSocket(int,enum dcmtk::log4cplus::helpers::SocketState &)" (?acceptSocket@helpers@log4cplus@dcmtk@@YAHHAAW4SocketState@123@@Z)".
    1>oflog.lib(winsock.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__bind@12" in Funktion ""int __cdecl dcmtk::log4cplus::helpers::openSocket(unsigned short,enum dcmtk::log4cplus::helpers::SocketState &)" (?openSocket@helpers@log4cplus@dcmtk@@YAHGAAW4SocketState@123@@Z)".
    1>oflog.lib(winsock.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__closesocket@4" in Funktion ""int __cdecl dcmtk::log4cplus::helpers::closeSocket(int)" (?closeSocket@helpers@log4cplus@dcmtk@@YAHH@Z)".
    1>oflog.lib(winsock.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__connect@12" in Funktion ""int __cdecl dcmtk::log4cplus::helpers::connectSocket(class OFString const &,unsigned short,bool,enum dcmtk::log4cplus::helpers::SocketState &)" (?connectSocket@helpers@log4cplus@dcmtk@@YAHABVOFString@@G_NAAW4SocketState@123@@Z)".
    1>oflog.lib(winsock.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__htonl@4" in Funktion ""int __cdecl dcmtk::log4cplus::helpers::openSocket(unsigned short,enum dcmtk::log4cplus::helpers::SocketState &)" (?openSocket@helpers@log4cplus@dcmtk@@YAHGAAW4SocketState@123@@Z)".
    1>oflog.lib(sockbuff.obj) : error LNK2001: Nicht aufgelöstes externes Symbol "__imp__htonl@4".
    1>oflog.lib(winsock.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__htons@4" in Funktion ""int __cdecl dcmtk::log4cplus::helpers::connectSocket(class OFString const &,unsigned short,bool,enum dcmtk::log4cplus::helpers::SocketState &)" (?connectSocket@helpers@log4cplus@dcmtk@@YAHABVOFString@@G_NAAW4SocketState@123@@Z)".
    1>oflog.lib(sockbuff.obj) : error LNK2001: Nicht aufgelöstes externes Symbol "__imp__htons@4".
    1>oflog.lib(winsock.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__listen@8" in Funktion ""int __cdecl dcmtk::log4cplus::helpers::openSocket(unsigned short,enum dcmtk::log4cplus::helpers::SocketState &)" (?openSocket@helpers@log4cplus@dcmtk@@YAHGAAW4SocketState@123@@Z)".
    1>oflog.lib(winsock.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__recv@16" in Funktion ""long __cdecl dcmtk::log4cplus::helpers::read(int,class dcmtk::log4cplus::helpers::SocketBuffer &)" (?read@helpers@log4cplus@dcmtk@@YAJHAAVSocketBuffer@123@@Z)".
    1>oflog.lib(winsock.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__send@16" in Funktion ""long __cdecl dcmtk::log4cplus::helpers::write(int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (?write@helpers@log4cplus@dcmtk@@YAJHABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z)".
    1>oflog.lib(winsock.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__setsockopt@20" in Funktion ""int __cdecl dcmtk::log4cplus::helpers::setTCPNoDelay(int,bool)" (?setTCPNoDelay@helpers@log4cplus@dcmtk@@YAHH_N@Z)".
    1>oflog.lib(winsock.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__gethostbyname@4" in Funktion ""int __cdecl dcmtk::log4cplus::helpers::connectSocket(class OFString const &,unsigned short,bool,enum dcmtk::log4cplus::helpers::SocketState &)" (?connectSocket@helpers@log4cplus@dcmtk@@YAHABVOFString@@G_NAAW4SocketState@123@@Z)".
    1>oflog.lib(winsock.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__gethostname@8" in Funktion ""class OFString __cdecl dcmtk::log4cplus::helpers::getHostname(bool)" (?getHostname@helpers@log4cplus@dcmtk@@YA?AVOFString@@_N@Z)".
    1>oflog.lib(winsock.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__WSACleanup@0" in Funktion ""public: __thiscall `anonymous namespace'::WinSockInitializer::~WinSockInitializer(void)" (??1WinSockInitializer@?A0x0e240de9@@QAE@XZ)".
    1>oflog.lib(winsock.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__WSAGetLastError@0" in Funktion ""int __cdecl dcmtk::log4cplus::helpers::connectSocket(class OFString const &,unsigned short,bool,enum dcmtk::log4cplus::helpers::SocketState &)" (?connectSocket@helpers@log4cplus@dcmtk@@YAHABVOFString@@G_NAAW4SocketState@123@@Z)".
    1>oflog.lib(winsock.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__WSASocketA@24" in Funktion ""int __cdecl dcmtk::log4cplus::helpers::connectSocket(class OFString const &,unsigned short,bool,enum dcmtk::log4cplus::helpers::SocketState &)" (?connectSocket@helpers@log4cplus@dcmtk@@YAHABVOFString@@G_NAAW4SocketState@123@@Z)".
    1>oflog.lib(winsock.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__WSAStringToAddressA@20" in Funktion ""int __cdecl dcmtk::log4cplus::helpers::connectSocket(class OFString const &,unsigned short,bool,enum dcmtk::log4cplus::helpers::SocketState &)" (?connectSocket@helpers@log4cplus@dcmtk@@YAHABVOFString@@G_NAAW4SocketState@123@@Z)".
    1>oflog.lib(sockbuff.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__ntohl@4" in Funktion ""public: unsigned int __thiscall dcmtk::log4cplus::helpers::SocketBuffer::readInt(void)" (?readInt@SocketBuffer@helpers@log4cplus@dcmtk@@QAEIXZ)".
    1>oflog.lib(sockbuff.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "__imp__ntohs@4" in Funktion ""public: unsigned short __thiscall dcmtk::log4cplus::helpers::SocketBuffer::readShort(void)" (?readShort@SocketBuffer@helpers@log4cplus@dcmtk@@QAEGXZ)".
    1>ofstd.lib(ofstd.obj) : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol "_gethostbyaddr@12" in Funktion ""public: static class OFStandard::OFHostent __cdecl OFStandard::getHostByAddr(char const *,int,int)" (?getHostByAddr@OFStandard@@SA?AVOFHostent@1@PBDHH@Z)".
    1>C:\Users\Kleinmanns\documents\visual studio 2012\Projects\DCMTKTest\Debug\DCMTKTest.exe : fatal error LNK1120: 25 nicht aufgelöste Externe
    ========== Erstellen: 0 erfolgreich, 1 fehlerhaft, 0 aktuell, 0 übersprungen ==========
    

    (zlib ist eingebunden)

    Nachdem ich zu der zlib_d.lib noch folgende libs gebunden hab, hats geklappt

    zlib_o.lib;netapi32.lib;wsock32.lib;WS2_32.Lib

    Kann aus meinem DICOM zwar kein patienten namen ziehen.
    Allerdings ist mein test-DICOM auch anonymisiert, also sollte das passen

    Gott wasn stress mit dem **** ^^

    Gruß



  • Ja dann: Viel Erfolg für die Arbeit! 🙂



  • Also das DCMTK-Framework läuft jetzt soweit und ich kann damit arbeiten,

    allerdings verzweifle ich immernoch am DICOM-Format 😕 😕

    Ich habe ein DICOM-Bild eingelesen und kann auch ganz gut auf alle Header-Informationen zugreifen, die abgespeichert sind.

    Ich würde allerdings gerne auf die einzelnen Farbwerte jedes Pixels zugreifen.

    Anhand von

    data->findAndGetOFString(DCM_Columns, width);
    data->findAndGetOFString(DCM_Rows, height);
    

    kann ich ermitteln, dass mein Bild 1024x1024 Pixel groß ist.

    Ich würde also 1.048.576 Grauwerte erwarten (1024*1024 eben)
    wenn ich in das Bild rein schaue habe ich effektiv 691.290 Grauwerte.

    Also fehlen mir grob 300.000 Grauwerte.
    Daraus lässt sich leicht schließen, dass meine Bilddaten Komprimiert sind.

    Nach ein wenig googeln habe ich folgenden Code gefunden/ausprobiert der angeblich meine Daten dekomprimieren sollte.

    ...
    
    // Der Code ist bereits aus meinem Projekt kopiert, original Code hier zu finden
    // http://support.dcmtk.org/wiki/dcmtk/howto/accessing-compressed-data
    
    	DcmFileFormat dfile;
    	if(dfile.loadFile(filename.c_str()).bad())
    		return 1;
    
    	DcmDataset *data = dfile.getDataset();
    
    	DcmPixelData *pixelData;
    	DcmElement *dcmElement;
    	data->findAndGetElement(DCM_PixelData, dcmElement);
    	pixelData = OFstatic_cast(DcmPixelData*, dcmElement);
    
    	E_TransferSyntax transferSyntax = EXS_Unknown;
    	const DcmRepresentationParameter *repPara = NULL;
    	pixelData->getOriginalRepresentationKey(transferSyntax, repPara);
    
    	DcmPixelSequence *pixelSequence = NULL;
    	if(pixelData->getEncapsulatedRepresentation(transferSyntax, repPara, pixelSequence).good() && pixelSequence != NULL) {
    		DcmPixelItem *i1;
    		pixelSequence->getItem(i1, 0);
    		DcmPixelItem *i2;
    		pixelSequence->getItem(i2, 1);
    
    		i1->print(cout);
    		i2->print(cout);
    	}
    ...
    

    Ausgabe:

    (fffe,e000) pi 00\00\00\00     #    4  ,1 Item
    (fffe,e000) pi (not loaded)    # 691290,1 Item
    

    es scheitert am angeblich ^^

    Ich habe leider keinerlei Informationen darüber wie die Daten komprimiert sind
    und auch im DICOM-Header habe ich nichts gefunden,
    falls es hilft kann ich Euch auch ein Beispiel-File zu verfügung stellen, meine Projekt-Daten sind ohnehin Anonymisiert.

    Kann mir jemand helfen?
    Ich bin echt am verzweifeln 😞

    EDIT: Link zum DICOM-Image
    https://www.dropbox.com/s/aoxmm8ukyitwa6f/00063

    Gruß



  • Oh man: ich merke ich habe seit Urzeiten nix mehr mit DICOM gemacht. 🙂
    Seinerzeit fand ich allerdings dcmdump aus dem dcmtk immer praktisch.
    Evtl. hilft Dir das ja schon.



  • Falls jemand vor dem selben Problem steht.

    dieser Code funktioniert für JPG-Compressed Images mit DCMTK

    #ifndef DICOMREADER_HPP
    #define DICOMREADER_HPP
    
    #include <string>
    #include "dcmtk/dcmdata/dctk.h"
    
    using namespace std;
    
    class DicomReader {
    protected:
    	int width;
    	int height;
    	unsigned char *pixelData;
    	DcmDataset *data;
    	DcmFileFormat *dcmFileFormat;
    
    	void calcWidth();
    	void calcHeight();
    	void calcPixelData();
    
    public:
    	DicomReader();
    	DicomReader(string filename);
    	void readFile(string filename);
    
    	int getWidth();
    	int getHeight();
    	unsigned char *getPixelData();
    
    	~DicomReader();
    };
    
    #endif
    
    #include "DicomReader.hpp"
    
    #include "dcmtk/config/osconfig.h" 
    #include "dcmtk/dcmdata/dcfilefo.h" 
    #include "dcmtk/dcmdata/dctagkey.h" 
    #include "dcmtk/dcmdata/dcdeftag.h" 
    #include "dcmtk/ofstd/ofcond.h" 
    #include "dcmtk/ofstd/ofstring.h" 
    #include "dcmtk/dcmjpeg/djdecode.h"
    
    DicomReader::DicomReader() {
    	this->dcmFileFormat = new DcmFileFormat();
    	this->data = NULL;
    	this->pixelData = NULL;
    	this->width = 0;
    	this->height = 0;
    }
    DicomReader::DicomReader(string filename) {
    	this->dcmFileFormat = new DcmFileFormat();
    	this->readFile(filename);
    	this->pixelData = NULL;
    	this->width = 0;
    	this->height = 0;
    }
    
    void DicomReader::readFile(string filename) {
    	if(this->dcmFileFormat->loadFile(filename.c_str()).bad())
    		cerr << "Could not load File" << endl;
    	else
    		this->data = this->dcmFileFormat->getDataset();
    }
    
    void DicomReader::calcPixelData() {
    	Uint16 tmpWidth;
    	Uint16 tmpHeight;
    
    	DJDecoderRegistration::registerCodecs();
    
    	this->data->findAndGetUint16(DCM_Rows, tmpHeight);
    	this->data->findAndGetUint16(DCM_Columns, tmpWidth);
    
    	// decompress
    	this->data->chooseRepresentation(EXS_LittleEndianExplicit, NULL);
    
    	if (data->canWriteXfer(EXS_LittleEndianExplicit)) {
    		const Uint16 *pixelData16;
    		this->pixelData = new unsigned char [tmpHeight*tmpWidth];
    
    		this->data->findAndGetUint16Array(DCM_PixelData, pixelData16);
    		// 16Bit (12 used) Greyscale to 8Bit Greyscale
    		for(int i = 0; i < tmpHeight*tmpWidth; i++) {
    			this->pixelData[i] = pixelData16[i] / 8;
    		}
    		this->width = (int)tmpWidth;
    		this->height = (int)tmpHeight;
    	}
    	DJDecoderRegistration::cleanup();
    }
    unsigned char *DicomReader::getPixelData() {
    	if(this->pixelData == NULL)
    		this->calcPixelData();
    	return this->pixelData;
    }
    
    void DicomReader::calcWidth() {
    	Uint16 tmpWidth;
    	this->data->findAndGetUint16(DCM_Columns, tmpWidth);
    	this->width = (int)tmpWidth;
    }
    int DicomReader::getWidth() {
    	if(this->width == 0)
    		this->calcWidth();
    	return this->width;
    }
    void DicomReader::calcHeight() {
    	Uint16 tmpHeight;
    	this->data->findAndGetUint16(DCM_Rows, tmpHeight);
    	this->height = (int)tmpHeight;
    }
    int DicomReader::getHeight() {
    	if(this->height == 0)
    		this->calcHeight();
    	return this->height;
    }
    
    DicomReader::~DicomReader() {
    	delete this->dcmFileFormat;
    	// delete this->data; Wird im destruktor von dcmFileFormat schon gekillt
    	delete[] this->pixelData;
    }
    

Log in to reply