在醫生實際使用過程中,對於有病灶的影像需要一些2D繪圖操作,例如對於病灶的標記和測量,
這就牽涉到在WPF中的2D繪圖操作技術,一般的思路是監聽滑鼠的按下和抬起以及運動軌跡,目前整理出的常用繪圖和測量功能如下:
圖形標記類:(測量類請參考本系列文章:繪圖處理之測量工具)
功能 | 說明 |
選區 | 螞蟻線選擇框 |
線段 | 線段標記 |
折線 | 折線標記 |
圓形 | 空心圓形 |
矩形 | 空心矩形 |
多邊形 | 空心多邊形 |
箭頭 | 指向作用 |
文字 | 文字標記 |
清除所有標記 | 清空單元格繪圖物件 |
撤銷上個標記 | 刪除上一個繪圖物件 |
在WPF中, 推薦使用InkCanvas控制元件。
最終效果:
1.在你的C#工程中新增一個圖形類作為操作基類:
/// <summary> /// 圖形資訊 /// </summary> public class ShapeInfo { #region -----宣告變數----- /// <summary> /// 圖形操作型別 /// </summary> public DrawAction shapeType = DrawAction.None; /// <summary> /// 控制元件畫布物件 /// </summary> public InkCanvas inkCanvas; /// <summary> /// 單點陣圖形畫布物件 /// </summary> public Canvas canvas; /// <summary> /// 圖形 /// </summary> public Shape shape; /// <summary> /// 控制點矩形物件集合 /// </summary> public Dictionary<string, Ellipse> CtrlPoints; /// <summary> /// 範圍選區矩形物件 /// </summary> public Polygon regionRect; /// <summary> /// 當前形狀的幾何體 /// </summary> public Geometry geometry; /// <summary> /// 是否為測量行為 /// </summary> public bool isMeasure = false; /// <summary> /// 測量物件集合 /// </summary> public List<TextBlock> measureList = new List<TextBlock>(); #endregion #region -----基類虛方法----- /// <summary> /// 繪製圖形 /// </summary> /// <param name="point">滑鼠座標</param> public virtual void DrawShape(Point point) { } /// <summary> /// 圖形繪製完成 /// </summary> /// <param name="point">滑鼠座標</param> /// <param name="isCallBack">是否回撥</param> public virtual bool DrawDone(Point point, bool isCallBack) { return true; } /// <summary> /// 繪製完成回撥函式 /// </summary> /// <param name="point">滑鼠座標</param> /// <param name="isCallBack">是否回撥</param> public delegate bool DrawDoneCallBack(Point point, bool isCallBack); /// <summary> /// 繪製完成回撥函式物件 /// </summary> public DrawDoneCallBack drawDoneCallBack; /// <summary> /// 選區移動回撥函式 /// </summary> /// <param name="curPoint">當前滑鼠座標</param> /// <param name="downPoint">按下滑鼠座標</param> public delegate void RegionRectMoveCallBack(Point curPoint, Point downPoint); /// <summary> /// 選區移動回撥函式物件 /// </summary> public RegionRectMoveCallBack regionRectMoveCallBack; #endregion }
2.建立圖形標記的子類來繼承基類,例如繪製一個線段:
/// <summary> /// 線段圖形資訊 /// </summary> public class LineInfo : ShapeInfo
在此類中建立繪製方法
/// <summary> /// 建立線段 /// </summary> /// <param name="point">起點座標</param> public void CreateLine(Point point) { Line line = new Line { //線段顏色 Stroke = ShapeManager.shapeColor, //線段粗細 StrokeThickness = ShapeManager.shapeThickness, //圓角頂點 StrokeLineJoin = PenLineJoin.Round, StrokeEndLineCap = PenLineCap.Round, StrokeStartLineCap = PenLineCap.Round, //起點的X、Y座標 X1 = point.X, Y1 = point.Y, //終點的X、Y座標 X2 = point.X, Y2 = point.Y, };
Canvas canvas = new Canvas(); canvas.Children.Add(line); inkCanvas.Children.Add(canvas); }
監聽滑鼠的的運動軌跡並重新繪製:
/// <summary> /// 繪製圖形 /// </summary> /// <param name="point">當前座標</param> public override void DrawShape(Point point) { line.X2 = point.X; line.Y2 = point.Y; }
繪製控制點:一個白色的圓形內嵌一個黑色的圓形,作為繪圖完成之後的控制點
/// <summary> /// 繪製控制點 /// </summary> /// <param name="point">滑鼠座標</param> /// <param name="tag">控制點標誌</param> /// <returns></returns> public Ellipse DrawCtrlPoint(Point point, string tag) { Ellipse ctrlPoint = new Ellipse { StrokeThickness = ShapeManager.ctrlPointThickness, Stroke = ShapeManager.ctrlPointColor, Fill = ShapeManager.ctrlPointFill, Width = ShapeManager.ctrlPointWidth, Height = ShapeManager.ctrlPointHeight, Margin = new Thickness(point.X - 5, point.Y - 5, point.X - 5, point.Y - 5), Visibility = Visibility.Hidden, }; if (!CtrlPoints.Keys.Contains(tag)) { CtrlPoints.Add(tag, ctrlPoint); canvas.Children.Add(ctrlPoint); ctrlPoint.Tag = tag; } return ctrlPoint; }
看效果:
螞蟻線選區:
/// <summary> /// 建立選擇框 /// </summary> /// <param name="point">起點座標</param> public void CreateSelected(Point point) { Polygon selectedPoly = new Polygon { Stroke = ShapeManager.selectRegColor, StrokeThickness = ShapeManager.selectRegThickness, StrokeDashArray = ShapeManager.selectRegDashArray, Points = { point, point, point, point }, }; canvas.Children.Add(selectedPoly); inkCanvas.Children.Add(canvas); }
其中要注意的是繪製模式改成虛線並控制間隔才能變成螞蟻線:
那麼以此類推,通過名稱空間System.Windows.Shapes,我們可以繼續繪製其他圖形了
最後,關於撤銷上個標記和清除所有標記,只需要將圖形物件儲存在LIst集合中,
需要刪除或撤銷的時候從集合中移除,並在畫布中移除即可。
C#開發PACS、RIS醫學影像處理系統
目錄整理:
(一)PACS客戶端:
C#開發PACS醫學影像處理系統(七):讀取影像Dicom資訊
C#開發PACS醫學影像處理系統(十):Dicom影像下載策略與演算法
C#開發PACS醫學影像處理系統(十一):Dicom影像掛片協議
C#開發PACS醫學影像處理系統(十二):繪圖處理之圖形標記
C#開發PACS醫學影像處理系統(十三):繪圖處理之病灶測量
C#開發PACS醫學影像處理系統(十四):處理Dicom影像窗寬窗位
C#開發PACS醫學影像處理系統(十五):基於體點陣圖交叉定位線演算法
C#開發PACS醫學影像處理系統(十六):2D處理之平移和縮放
C#開發PACS醫學影像處理系統(十七):2D處理之任意角度旋轉與映象翻轉
C#開發PACS醫學影像處理系統(十八):Dicom影像色彩增強(偽彩)
C#開發PACS醫學影像處理系統(十九):Dicom影像反色處理(負片)
C#開發PACS醫學影像處理系統(二十):Dicom影像放大鏡功能
(二)PACS三維:MRP、MIP、VR
C#開發PACS醫學影像三維重建(一):使用VTK三維重建Dicom影像
(三)PACS網頁端:開發Web版本的PACS
C#開發Web端PACS(一):基於PACS客戶端思想重寫Web端
(四)PACS移動端:開發基於HTML5移動端版本的PACS
C#開發移動端PACS(一):使用HTML5和CSS3開發PACS手機端頁面
C#開發移動端PACS(二):使用 .Net MVC 開發手機端PACS服務端
(五)PACS服務端:
C#開發PACS醫學影像處理系統服務端(一):醫療裝置的連線與收圖
C#開發PACS醫學影像處理系統服務端(二):高併發架構
(六)PACS與RIS系統的通訊與整合
在RIS系統中調起PACS並開啟Dicom影像
(七)雲PACS與遠端會診
C#開發PACS醫學影像處理系統之雲PACS(區域PACS)(一):架構概述
C#開發PACS醫學影像處理系統之雲PACS(區域PACS)(二):遠端會診與雙向轉診
(八)科幻級視訊特效:使用Adobe After Effects 製作PACS影像處理系統宣傳視訊
QQ:1850969244 近10年開發經驗,主攻C#、ASP MVC,HTML5, B/S C/S 皆可,目前研究醫療領域醫學影像相關技術, 任何技術問題歡迎加QQ交流。 |