如何在Xcode中用Python读取.dcm文件?
我正在尝试创建一个应用程序,用于查看和分析DICOM切片。我之前在MATLAB中做过这个应用,但MATLAB的工具不够强大,无法制作出真正好看的界面,而且3D效果也不好。因此,我花了很长时间尝试使用ITK和VTK在Xcode中构建一个应用,但一直没有成功。一天,我发现了一个叫xcodeproject PythonDicomDocument的项目——这个用Python写的项目可以读取和显示DICOM图像!我看过关于Python和Cocoa的教程,但仍然不太明白这个项目是怎么工作的——它有一个文件PythonDicomDocumentDocument.py:
from Foundation import *
from AppKit import *
from iiDicom import *
import objc
import dicom
import numpy
import Image
class PythonDicomDocumentDocument(NSDocument):
imageView = objc.IBOutlet('imageView')
def init(self):
self = super(PythonDicomDocumentDocument, self).init()
self.image = None
return self
def windowNibName(self):
return u"PythonDicomDocumentDocument"
def windowControllerDidLoadNib_(self, aController):
super(PythonDicomDocumentDocument, self).windowControllerDidLoadNib_(aController)
if self.image:
self.imageView.setImageScaling_(NSScaleToFit)
self.imageView.setImage_(self.image)
def dataOfType_error_(self, typeName, outError):
return None
def readFromData_ofType_error_(self, data, typeName, outError):
return NO
def readFromURL_ofType_error_(self, absoluteURL, typeName, outError):
if absoluteURL.isFileURL():
slice = iiDcmSlice.alloc().initWithDicomFileSlice_(absoluteURL.path())
dicomImage = slice.sliceAsNSImage_context_(True, None)
if dicomImage:
self.image = dicomImage
#self.image = dicomImage
return True, None
return False, None
还有一个文件main.m:
**#import "<"Python/Python.h>**
**#import "<"Cocoa/Cocoa.h>**
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *resourcePath = [mainBundle resourcePath];
NSArray *pythonPathArray = [NSArray arrayWithObjects: resourcePath, [resourcePath stringByAppendingPathComponent:@"PyObjC"], @"/System/Library/Frameworks/Python.framework/Versions/Current/Extras/lib/python/", nil];
setenv("PYTHONPATH", [[pythonPathArray componentsJoinedByString:@":"] UTF8String], 1);
NSArray *possibleMainExtensions = [NSArray arrayWithObjects: @"py", @"pyc", @"pyo", nil];
NSString *mainFilePath = nil;
for (NSString *possibleMainExtension in possibleMainExtensions) {
mainFilePath = [mainBundle pathForResource: @"main" ofType: possibleMainExtension];
if ( mainFilePath != nil ) break;
}
if ( !mainFilePath ) {
[NSException raise: NSInternalInconsistencyException format: @"%s:%d main() Failed to find the Main.{py,pyc,pyo} file in the application wrapper's Resources directory.", __FILE__, __LINE__];
}
Py_SetProgramName("/usr/bin/python");
Py_Initialize();
PySys_SetArgv(argc, (char **)argv);
const char *mainFilePathPtr = [mainFilePath UTF8String];
FILE *mainFile = fopen(mainFilePathPtr, "r");
int result = PyRun_SimpleFile(mainFile, (char *)[[mainFilePath lastPathComponent] UTF8String]);
if ( result != 0 )
[NSException raise: NSInternalInconsistencyException
format: @"%s:%d main() PyRun_SimpleFile failed with file '%@'. See console for errors.", __FILE__, __LINE__, mainFilePath];
[pool drain];
return result;
}
所以我想把MATLAB中读取.dcm文件的代码“翻译”过来:
directory = uigetdir; % after this command Finder window will appear and user will choose a folder with .dcm files
fileFolder = directory; % the path to the folder is saved to a variable fileFolder
dirOutput = dir(fullfile(fileFolder,'*.dcm')); % choose files .dcm in specified folder %and save their names
fileNames = {dirOutput.name}';
Names = char(fileNames);
numFrames = numel(fileNames); % count the number of files in the folder
for i = 1:numFrames
Volume(:,:,i) = dicomread(fullfile(fileFolder,Names(i,:))); % create a 3D array of %DICOM pixel data
end;
有没有人能告诉我怎么在Xcode中用Python运行相同的代码来读取.dcm文件???
我听说Python和MATLAB很相似。
1 个回答
1
恭喜你选择Python来处理DICOM文件!根据我的经验,SciPy、numpy和matplotlib这几个库在处理大量数据时,比MATLAB(或者GNU Octave)要好得多。
下面是一些使用GDCM的Python接口、GDCM示例中的ConvertNumpy.py和matplotlib的加载和显示代码:
#!/usr/bin/env python
import gdcm
import ConvertNumpy
import numpy as np
import matplotlib.pyplot as plt
def loadDicomImage(filename):
reader=gdcm.ImageReader()
reader.SetFileName(filename)
reader.Read()
gdcmimage=reader.GetImage()
return ConvertNumpy.gdcm_to_numpy(gdcmimage)
image=loadDicomImage('mydicomfile.dcm')
plt.gray()
plt.imshow(image)
plt.show()
需要注意的是,如果你的DICOM数据中有一些“填充”值远远超出了图像的空气和骨骼范围,可能会让imshow的自动缩放搞混;你可以使用vmax和vmin参数来指定你想要看到的范围,或者自己写一个简单的窗口级别调整代码(在numpy中这很简单)。