• C#开发PACS医学影像处理系统(六):加载Dicom影像


    对于一款软件的扩展性和维护性来说,上层业务逻辑和UI表现一定要自己开发才有控制权,否则项目上线之后容易被掣肘,

    而底层图像处理,我们不需要重复造轮子,这里推荐使用fo-dicom,同样基于Dicom3.0协议。

    根据以上原则,后台影像处理完成之后,即可使用自己开发的控件来呈现。

    1.先准备好自己的dcm文件,可以是单个文件或序列文件或DicomDir文件。

    2.在VS编辑器里打开NUGET搜索fo-dicoman安装即可。

    3.使用fo-dicom读取影像。

            //将图像处理模式设置为全局WPF模式
            Dicom.Imaging.ImageManager.SetImplementation(Dicom.Imaging.WPFImageManager.Instance);
    
            //实例化文件处理对象并打开文件
            DicomFile dicomFile = DicomFile.Open(@"C:1011.dcm");
            //获取dicom图像对象
            DicomImage dicomImage = new DicomImage(dicomFile.Dataset);
            //不使用LUT
            dicomImage.UseVOILUT = false;
    
            //转换成一般图像格式,bmp,png等,
            //在WPF中我们转换成WriteableBitmap
            dicomImage.RenderImage().AsWriteableBitmap() :

    4.设置缩放比例,通常dcm影像的大小是不固定的,由设备和技师拍摄手法决定,所以我们要将图像大小缩小或放大到最佳尺寸。

    dicomImage对象中的Scale属性决定了缩放比例,方法参数中Border是边框容器,也可以使用Grid或其他可以呈现图像的容器。

     /// <summary>
     /// 计算图片在容器中的缩放比例
     /// </summary>
     /// <param name="dicomImage">图片</param>
     /// <param name="imgBoxDock">容器</param>
     /// <param name="width">实际长度</param>
     /// <param name="height">实际高度</param>
    public static void SetImageScale(DicomImage dicomImage, Border imgBoxDock, double width = 0, double height = 0)
    {
        double maxWidth = imgBoxDock.Width;
        double maxHeight = imgBoxDock.Height;
        if (double.IsNaN(imgBoxDock.Width) || double.IsNaN(imgBoxDock.Height))
        {
            maxWidth = width;
            maxHeight = height;
        }
        dicomImage.Scale = Math.Min(maxWidth / dicomImage.Width, maxHeight / dicomImage.Height);
    }

    5.设置图像对齐方式,图像的长宽一般是不能恰好填充容器的,尤其是设置缩放比例之后,那我们需要在容器中将图像按照一定规则对齐。

         /// <summary>
            /// 在图片容器中显示一张图片
            /// </summary>
            /// <param name="sourceImg">图片源</param>
            /// <param name="imgBox">图片控件</param>
            /// <param name="imgBoxDock">图片容器</param>
            /// <param name="align">对齐方式</param> 
            /// <param name="width">实际长度</param>
            /// <param name="height">实际高度</param>
            public static void ShowImage(WriteableBitmap sourceImg, InkCanvas imgBox, Border imgBoxDock, ImageAlignment align,  double width = 0, double height = 0)
            {
                try
                {
                    if (sourceImg != null)
                    {
                        ImageBrush ib = new ImageBrush(sourceImg);
                        imgBox.Background = ib;
                    }
    
                    double w = 0;
                    double h = 0;
                    if (double.IsNaN(imgBoxDock.Width) || double.IsNaN(imgBoxDock.Height))
                    {
                        w = width;
                        h = height;
                    }
                    else
                    {
                        if (sourceImg != null)
                        {
                            w = imgBoxDock.Width - sourceImg.Width;
                            h = imgBoxDock.Height - sourceImg.Height;
                        }           else return;
                    }
    
                    if (align == ImageAlignment.Center)
                    {
                        imgBox.Margin = new Thickness(
                            w / 2,
                            h / 2,
                            w / 2,
                            h / 2);
                    }
                    else if (align == ImageAlignment.Left)
                    {
                        imgBox.Margin = new Thickness(
                            0,
                            h / 2,
                            w,
                            h / 2);
                    }
                    else if (align == ImageAlignment.Right)
                    {
                        imgBox.Margin = new Thickness(
                            w,
                            h / 2,
                            0,
                            h / 2);
                    }
                    else if (align == ImageAlignment.Top)
                    {
                        imgBox.Margin = new Thickness(
                            w / 2,
                            0,
                            w / 2,
                            h);
                    }
                    else if (align == ImageAlignment.Bottom)
                    {
                        imgBox.Margin = new Thickness(
                            w / 2,
                            h,
                            w / 2,
                            0);
                    }
                }
                catch (Exception e)
                {
                    LogApi.WriteErrLog(e);
                }
            }

    /// <summary>
        /// 图像对齐方式
        /// </summary>
        public enum ImageAlignment
        {
            /// <summary>
            /// 居左
            /// </summary>
            Left = 0,
    
            /// <summary>
            /// 置顶
            /// </summary>
            Top = 1,
    
            /// <summary>
            /// 居右
            /// </summary>
            Right = 2,
    
            /// <summary>
            /// 置底
            /// </summary>
            Bottom = 3,
    
            /// <summary>
            /// 居中
            /// </summary>
            Center = 4,
    
            /// <summary>
            /// 跟随父级(仅用于Cell中dicom容器)
            /// </summary>
            Parent = 5,
    
        }

    最终呈现效果:

     

    注:一些特殊的类型对齐方式是不一样的,需要对应的挂片协议来控制,详情请参考本系列文章的挂片协议章节。

    例如:钼靶(modality:MG)类型,是按照居左居右对齐。

     

  • 相关阅读:
    Extending Markov to Hidden Markov
    Logistic Regression – Geometric Intuition
    【计算机视觉】会议投稿相关推荐
    NP难问题求解综述
    PCA的数学原理
    Brief History of Machine Learning
    图像局部特征点检测算法综述【修正排版】
    thinkphp输出表格
    1503162139-ny-分数拆分
    C++中经常使用到宏
  • 原文地址:https://www.cnblogs.com/Uncle-Joker/p/13665748.html
Copyright © 2020-2023  润新知