string path; if (Path.GetFileName(path).Equals("DICOMDIR")) retern; TreeView treeView = new TreeView(); TreeNode treeNode = new TreeNode(); List<string[]> imageList = new List<string[]>(); treeNode.Nodes.Clear(); treeView.Nodes.Clear(); //DicomDir dicomDir = new DicomDir(path); //ReadDicomDir(dicomDir); Stream stream = null; DcmParser parser = null; Dataset ds = null; try { stream = new BufferedStream(new FileStream(path, FileMode.Open, FileAccess.Read)); parser = new org.dicomcs.data.DcmParser(stream); org.dicomcs.data.FileFormat format = parser.DetectFileFormat(); if (format != null) { ds = new org.dicomcs.data.Dataset(); parser.DcmHandler = ds.DcmHandler; parser.ParseDcmFile(format); TreeNode nodePatient = new TreeNode(); TreeNode nodeStudy = new TreeNode(); TreeNode nodeSeries = new TreeNode(); TreeNode nodeStudat = new TreeNode(); // int tmpStudat = 0; int patBirdat = 0; string patName = string.Empty; // DcmObject doRoot = (DcmObject)ds; IEnumerator enuRoot = doRoot.GetEnumerator(); int count = 0; while (enuRoot.MoveNext()) { DcmElement elRoot = (DcmElement)enuRoot.Current; if (elRoot.HasItems()) { for (int i = 0; i < elRoot.vm(); i++) { DcmObject dcmObj = (DcmObject)elRoot.GetItem(i); IEnumerator enu = dcmObj.GetEnumerator(); while (enu.MoveNext()) { DcmElement el = (DcmElement)enu.Current; if (el.tag() == DcmTags.DirectoryRecordType) { string rs = el.GetString(Encoding.Unicode); if (rs == "PATIENT") { PatientTable pt = new PatientTable(); if (dcmObj.Contains(Tags.PatientBirthDate)) patBirdat = Convert.ToInt32(dcmObj.GetDate(DcmTags.PatientBirthDate).ToString("yyyyMMdd")); if (dcmObj.Contains(Tags.PatientName)) patName = dcmObj.GetString(DcmTags.PatientName); } else if (rs == "STUDY") { if (dcmObj.Contains(DcmTags.StudyDate)) { int studat = Convert.ToInt32(dcmObj.GetDate(Tags.StudyDate).ToString("yyyyMMdd")); string stuinsuid = string.Empty; string studes = string.Empty; if (dcmObj.Contains(DcmTags.StudyInstanceUID)) stuinsuid = dcmObj.GetString(DcmTags.StudyInstanceUID); if (dcmObj.Contains(DcmTags.StudyDescription)) studes = dcmObj.GetString(DcmTags.StudyInstanceUID); if (studat != tmpStudat) { nodeStudat = new TreeNode(studat.ToString("####/##/##")); nodeStudat.Tag = studat; treeViewStudy.Nodes.Add(nodeStudat); tmpStudat = studat; } nodeStudy = new TreeNode(""); nodeStudat.Nodes.Add(nodeStudy); } } else if (rs == "SERIES") { imageList = new List<string[]>(); string serinsuid = string.Empty; string sernum = string.Empty; ; string numserrelima = string.Empty; string serdes = string.Empty; string bodparexa = string.Empty; string modality = string.Empty; if (dcmObj.Contains(DcmTags.SeriesInstanceUID)) serinsuid = dcmObj.GetString(DcmTags.SeriesInstanceUID); if (dcmObj.Contains(DcmTags.SeriesNumber)) sernum = dcmObj.GetString(DcmTags.SeriesNumber); if (dcmObj.Contains(DcmTags.SeriesDescription)) serdes = dcmObj.GetString(DcmTags.SeriesDescription); if (dcmObj.Contains(DcmTags.Modality)) modality = dcmObj.GetString(DcmTags.Modality); nodeSeries = new TreeNode(modality + "." + sernum); nodeStudy.Nodes.Add(nodeSeries); if (nodeStudy.Text == string.Empty) nodeStudy.Text = modality; nodeSeries.Tag=imageList; //Add (refFile and uid)List } else if (rs == "IMAGE") { string refFileID = string.Empty; string uid = string.Empty; if (dcmObj.Contains(DcmTags.RefFileID)) refFileID = dcmObj.GetString(DcmTags.RefFileID); if (dcmObj.Contains(DcmTags.RefSOPInstanceUIDInFile)) uid = dcmObj.GetString(DcmTags.RefSOPInstanceUIDInFile); string[] ss = new string[2]; ss[0] = refFileID; ss[1] = uid; imageList.Add(ss); } } } } } }
2011年9月17日土曜日
DICOMDIR から TreeNode へ
2011年5月24日火曜日
dicom-cs あるいは dicomネットワークツール
C#用のDICOMネットワークツール。
イメージ用のソースは無いが元ネタのdcm-4cheにあり。
参照設定
log4net用にlog4net.config設定ファイル
[assembly: log4net.Config.XmlConfigurator(ConfigFile = @"log4net.config", Watch = true)]
を入れておく。
出力に
'System.IO.EndOfStreamException' の初回例外が mscorlib.dll で発生しました。
が出る。。。。
stream 読み取り時、エラーが出たら次のtagを読みに行くという設定のためか?
どうしたら出ないようにできるものか。。。。
PixelDataの取得は
イメージ用のソースは無いが元ネタのdcm-4cheにあり。
参照設定
using org.dicomcs.dict;
using org.dicomcs.data;
using org.dicomcs.net;
using org.dicomcs.util;
using log4net;
log4net用にlog4net.config設定ファイル
[assembly: log4net.Config.XmlConfigurator(ConfigFile = @"log4net.config", Watch = true)]
を入れておく。
出力に
'System.IO.EndOfStreamException' の初回例外が mscorlib.dll で発生しました。
が出る。。。。
stream 読み取り時、エラーが出たら次のtagを読みに行くという設定のためか?
どうしたら出ないようにできるものか。。。。
PixelDataの取得は
org.dicomcs.util.ByteBuffer buff = dataSet.GetByteBuffer(Tags.PixelData); byte[] pixelData = (byte[])buff.ToArray();
2011年3月23日水曜日
カラービットマップ
pixelDataからカラービットマップを取得
BGR > RGB の変換が必要
BGR > RGB の変換が必要
{ if(PhotometricInterpretation != "RGB") retern; //dataSet: DicomDataSet Bitmap bitmap; int columns = dataSet.Columns; int rows = dataSet.Rows; byte[] pixelData = dataSet.PixelData; bitmap = new Bitmap(columns, rows, PixelFormat.Format24bppRgb); BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, columns, rows), ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); int padding = bitmapData.Stride - columns; byte* pBitmap = (byte*)bitmapData.Scan0; int j = 0, i = 0; for (int y = 0; y < rows; y++) { j = y * columns; for (int x = 0; x < columns; x++) { i = j + x; pBitmap[i * 3] = pixelData[i * 3 + 2]; //G pBitmap[i * 3 + 1] = pixelData[i * 3 + 1]; //B pBitmap[i * 3 + 2] = pixelData[i * 3]; //R } i += padding; } bitmap.UnlockBits(bitmapData); return bitmap; }.net 4.0から Parallel.For が使えるようになったので一部訂正。2015-08-12
fixed (byte* pData = pixelData) { byte* rgb = pData; int stride = bmpData.Stride; Parallel.For(0, rows, y => { for (int x = 0; x < columns; x++) { int pos = (x * 3) + y * stride; pBitmap[pos] = rgb[pos + 2]; //G pBitmap[pos + 1] = rgb[pos + 1]; //B pBitmap[pos + 2] = rgb[pos]; //R } }); }
2011年3月21日月曜日
マルチフレーム
NumberOfFrames タグ (0028,0008)があるとマルチフレーム画像。
PixelData(7FD0,0010)の長さをNumberOfFramesで割った値が一枚当たりの画像の PixelData 。
PixelData(7FD0,0010)の長さをNumberOfFramesで割った値が一枚当たりの画像の PixelData 。
List<byte[]> pixelDataList = new List<byte[]>();
int numberOfFrames = dicomData.NumberOfFrames;
int length = dicomData.PixelData.Length / numberOfFrames;
for(int k=0; k < numberOfFrames;k++)
{
byte[] buf;
Array.Copy(dicomData.PixelData, numberOfFrames * length, buf, 0, length);
pixelDataList.Add(buf);
}
RescaleIntercept タグ と RescaleSlopeタグ
他院からのCDで Rescale Interceptタグ と Rescale Slopeタグがある DICOM Fileを散見。
シーメンスのCTなど。
画像データに傾斜と切片を付加して8bitグレースケールを得る。
シーメンスのCTなど。
画像データに傾斜と切片を付加して8bitグレースケールを得る。
fixed (byte* pData = pixelData)
{
int pixel;
short* ptr = (short*)pData; //short型ポインタ
byte* pBitmap = (byte*)bitmapData.Scan0;
int j = 0, i = 0;
int difference = max - min;
if (rescaleIntercept == 0.0d )
{
for (int x = 0; x < _columns; x++)
{
pixel = (int)(((*ptr + rescaleIntercept - windowCenter) / windowWidth + 0.5d) * 255.0d);
if (pixel > 255) pixel = 255;
else if (pixel < 0) pixel = 0;
*pBitmap = (byte)pixel; ptr++; pBitmap++;
}
pBitmap += padding;
}
else
{
for (int y = 0; y < _rows; y++)
{
j = y * _columns;
for (int x = 0; x < _columns; x++)
{
pixel = (int)((((int)ptr[j + x] + rescaleIntercept - windowCenter) / windowWidth + 0.5d) * 255.0d);
if (pixel > 255) pixel = 255;
if (pixel < 0) pixel = 0;
pixel = (int)(rescaleSlope * pixel + rescaleIntercept);
pBitmap[i] = (byte)pixel;
i++;
}
i += padding;
}
}
}
16 bit グレースケール
CT, MR, CR, DR などの医用画像は殆どが16bit グレースケール画像。
PCでは8bitしか表示できないので、これを変換。
また Bitmap.SetPixel がとても遅いため LockBits を使用。
1byteが1pixelのグレースケール用ColorPaletteを作成する。
3byte=1pixelのグレースケール(R=G=B)より容量減か。
データの挿入 ()
PCでは8bitしか表示できないので、これを変換。
また Bitmap.SetPixel がとても遅いため LockBits を使用。
using System; using System.Drawing; using System.Drawing.Imaging;DICOMオブジェクト
int columns = dicomData.Columns; int rows = dicomData.Rows; int windowCenter = dicomData.WindowCenter; int windowWidth = dicomData.WindowWidth;ビットマップ
1byteが1pixelのグレースケール用ColorPaletteを作成する。
3byte=1pixelのグレースケール(R=G=B)より容量減か。
byte[] pixelData = dicomData.PixelData;Bitmap bitmap; ColorPalette colorPalette; for (int i = 0; i < 256; i++) colorPalette.Entries[i] = Color.FromArgb(i, i, i); Bitmap bitmap = new Bitmap(columns, rows, PixelFormat.Format8bppIndexed);
データの挿入 ()
public unsafe Bitmap Grayscale16To8() { int padding = bitmapData.Stride - columns; int min = windowCenter - windowWidth / 2; int max = windowCenter + windowWidth / 2; fixed (byte* pData = pixelData) { int pixel; short* ptr = (short*)pData; byte* pBitmap = (byte*)bitmapData.Scan0; int j = 0, i = 0; for (int y = 0; y < _rows; y++) { j = y * _columns; for (int x = 0; x < _columns; x++) { pixel = (int)ptr[j + x]; if (pixel <= min) pixel = 0; else if (pixel >= max) pixel = 255; else pixel = (int)((pixel - min) * 255 / (max - min)); pBitmap[i] = (byte)pixel; i++; } i += padding; } } bitmap.UnlockBits(bitmapData); return bitmap; }
登録:
投稿
(
Atom
)