123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- using AI.Common;
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows.Media;
- namespace HumanOrganSegDemo.RoughPositioningAnalyser
- {
- public class RoughPositioningAnalyser :IRoughPositioningAnalyser
- {
- #region private
- private int countSum = 0;
- private List<int> countXList = new List<int>();
- private List<int> countYList = new List<int>();
- private List<int> countMidXList = new List<int>();
- private List<int> countMidYList = new List<int>();
- private List<int> countList = new List<int>();
- #endregion
- #region 实现
- /// <summary>
- /// 获取图像坐标系下初始扫查路径点
- /// </summary>
- /// <param name="organ"></param>
- /// <param name="HumanOrientationInPCS"></param>
- /// <param name="OrganContours"></param>
- /// <returns></returns>
- public Point2D[] GetRoughSanPathInPCS(EnumOrgans organ, Point2D humanOrientationInPCS, Rect humanRoi, ContourPoints organContours)
- {
- Point2D[] result;
- switch (organ)
- {
- case EnumOrgans.Liver:
- result = GetLiverRoughSanPathInPCS(humanOrientationInPCS, humanRoi, organContours);
- break;
- case EnumOrgans.Heart:
- result = GetHeartRoughSanPathInPCS(humanOrientationInPCS, humanRoi, organContours);
- break;
- default:
- throw new Exception("Invalid organ name!");
- }
- return result;
- }
- #endregion
- #region private funcs
- private Point2D[] GetLiverRoughSanPathInPCS(Point2D humanOrientationInPCS, Rect humanRoi, ContourPoints organContours)
- {
- int tempX = 0;
- int tempY = 0;
- Point2D[] contours = (Point2D[])organContours.Points.Clone();
- for (int j = 0; j < contours.Length - 1; j++)
- {
- if (contours[j + 1].X < contours[j].X)
- {
- tempY = contours[j].Y;
- tempX = contours[j].X;
- contours[j].X = contours[j + 1].X;
- contours[j + 1].X = tempX;
- }
- }
- int X = (int)(humanRoi.Width * 0.08);
- int Y = (int)(humanRoi.Height * 0.1);
- Point2D[] points = { new Point2D(tempX - X, tempY), new Point2D(tempX - X, tempY + Y) };
- return points;
- }
- /// <summary>
- /// 人体在X和Y方向的判断
- /// </summary>
- /// <param name="humanOrientationInPCS"></param>
- /// <param name="humanOrientationFlagX"></param>
- /// <param name="humanOrientationFlagY"></param>
- /// <returns></returns>
- private bool humanOrientationInPCSFlag(Point2D humanOrientationInPCS,out int humanOrientationFlagX, out int humanOrientationFlagY)
- {
- //每一张图都判断它的方向向量
- countSum++;
- humanOrientationFlagX=0;
- humanOrientationFlagY=0;
- if (humanOrientationInPCS.X > 0)
- {
- countXList.Add(1);
- }
- else
- {
- countXList.Add(0);
- }
- if (humanOrientationInPCS.Y > 0)
- {
- countYList.Add(1);
- }
- else
- {
- countYList.Add(0);
- }
- //多张图人体朝向概率
- if(countSum>15)
- {
- countXList.RemoveAt(0);
- countYList.RemoveAt(0);
- if (((float)countXList.Sum() / 15) > 0.5f)
- {
- humanOrientationFlagX = 1;
- }
- else
- {
- humanOrientationFlagX = 0;
- }
- if (((float)countYList.Sum() / 15) > 0.5f)
- {
- humanOrientationFlagY = 1;
- }
- else
- {
- humanOrientationFlagY = 0;
- }
- return true;
- }
- else
- {
- return false;
- }
- }
- /// <summary>
- /// 轮廓的中心点和外接框宽高
- /// </summary>
- /// <param name="organContours"></param>
- /// <param name="midX"></param>
- /// <param name="midY"></param>
- /// <param name="distanceX"></param>
- /// <param name="distanceY"></param>
- /// <returns></returns>
- private bool GetContourCenPoint(ContourPoints organContours,out int midX, out int midY,out int distanceX,out int distanceY)
- {
- midX = 0;
- midY = 0;
- distanceX=0;
- distanceY = 0;
- Point2D[] contours = (Point2D[])organContours.Points.Clone();
- int len = contours.Length;
- if (len == 0)
- {
- return false;
- }
- else
- {
- //轮廓中心点
- List<int> contoursX = new List<int>();
- List<int> contoursY = new List<int>();
- for (int i = 0; i < len; i++)
- {
- contoursX.Add(contours[i].X);
- contoursY.Add(contours[i].Y);
- }
- contoursX.Sort();
- contoursY.Sort();
- midX = (contoursX[0] + contoursX[len - 1]) / 2;
- midY = (contoursY[0] + contoursY[len - 1]) / 2;
- distanceX = (contoursX[len - 1] - contoursX[0]);
- distanceY = (contoursY[len - 1] - contoursY[0]);
- return true;
- }
- }
- /// <summary>
- /// 判断轮廓位置是否正常
- /// </summary>
- /// <param name="organContours"></param>
- /// <returns></returns>
- private bool SegPositionFlag(ContourPoints organContours)
- {
- int meanCountMidX, meanCountMidY;
- int midX=0;
- int midY = 0;
- int distanceX = 0;
- int distanceY = 0;
- bool isTureInSegContours = GetContourCenPoint(organContours, out midX, out midY, out distanceX, out distanceY);
- if(isTureInSegContours)
- {
- //多张图的轮廓中心点平均范围
- countMidXList.Add(midX);
- countMidYList.Add(midY);
- countList.Add(1);
- if (countMidXList.Count > 100)
- {
- countMidXList.RemoveRange(0, 50);
- countMidYList.RemoveRange(0, 50);
- countList.RemoveRange(0, 50);
- }
- meanCountMidX = countMidXList.Sum() / countList.Sum();
- meanCountMidY = countMidYList.Sum() / countList.Sum();
- if ((Math.Abs(countMidXList[countMidXList.Count - 1] - meanCountMidX) > distanceX / 2) || (Math.Abs(countMidYList[countMidXList.Count - 1] - meanCountMidY) > distanceY / 2))
- {
- return false;
- }
- else
- {
- return true;
- }
- }
- else
- {
- return false;
- }
- }
- /// <summary>
- /// 计算两点间距离
- /// </summary>
- /// <param name="x1"></param>
- /// <param name="y1"></param>
- /// <param name="x2"></param>
- /// <param name="y2"></param>
- /// <returns></returns>
- private float GetDistance(int x1,int y1,int x2,int y2)
- {
- float distance=(float)Math.Sqrt(Math.Pow(x1-x2,2) + Math.Pow(y1-y2,2));
- return distance;
- }
- /// <summary>
- /// 轮廓四个顶点
- /// </summary>
- /// <param name="contours"></param>
- /// <param name="midX"></param>
- /// <param name="midY"></param>
- /// <param name="flag"></param>
- /// <param name="pointX"></param>
- /// <param name="pointY"></param>
- private void GetPoints(Point2D[] contours,int midX,int midY,int flag, out int pointX, out int pointY)
- {
- int len = contours.Length;
- pointX = 0;
- pointY = 0;
- bool enable=false;
-
- for (int i = 0; i < len - 1; i++)
- {
- switch (flag)
- {
- case 1:
- enable = (contours[i + 1].X > midX && contours[i + 1].Y > midY);
- break;
- case 2:
- enable = (contours[i + 1].X < midX && contours[i + 1].Y < midY);
- break;
- case 3:
- enable = (contours[i + 1].X > midX && contours[i + 1].Y < midY);
- break;
- case 4:
- enable = (contours[i + 1].X < midX && contours[i + 1].Y > midY);
- break;
- default:
- break;
- }
- if (enable)
- {
- if (GetDistance(contours[i + 1].X, contours[i + 1].Y, midX, midY) < GetDistance(contours[i].X, contours[i].Y, midX, midY))
- {
- pointY = contours[i].Y;
- contours[i].Y = contours[i + 1].Y;
- contours[i + 1].Y = pointY;
- pointX = contours[i].X;
- contours[i].X = contours[i + 1].X;
- contours[i + 1].X = pointX;
- }
- }
- }
- }
- private Point2D[] GetHeartRoughSanPathInPCS(Point2D humanOrientationInPCS, Rect humanRoi, ContourPoints organContours)
- {
- Point2D[] result;
- int pointX1 = 0;
- int pointY1 = 0;
- int pointX2 = 0;
- int pointY2 = 0;
- int pointX3 = 0;
- int pointY3 = 0;
- int pointX4 = 0;
- int pointY4 = 0;
- int humanOrientationFlagX = 0;
- int humanOrientationFlagY=0;
- int midX = 0;
- int midY = 0;
- int distanceX = 0;
- int distanceY = 0;
- //轮廓是否存在,取中心点
- bool isTureInSegContours = GetContourCenPoint(organContours, out midX, out midY, out distanceX, out distanceY);
- //分割位置判断
- bool isTrueInSegPosition=SegPositionFlag(organContours);
- //人体朝向判断
- bool isDoneInHumanOrientation = humanOrientationInPCSFlag(humanOrientationInPCS, out humanOrientationFlagX, out humanOrientationFlagY);
- Point2D[] contours = (Point2D[])organContours.Points.Clone();
- if (!isTureInSegContours || !isTrueInSegPosition || !isDoneInHumanOrientation)
- {
- return null;
- }
- else
- {
- //得到轮廓距离中心点最远的四个点
- GetPoints(contours, midX, midY, 1, out pointX1, out pointY1);
- GetPoints(contours, midX, midY, 2, out pointX2, out pointY2);
- GetPoints(contours, midX, midY, 3, out pointX3, out pointY3);
- GetPoints(contours, midX, midY, 4, out pointX4, out pointY4);
- //长短轴距离
- float distance1 = GetDistance(pointX1, pointY1, midX, midY) + GetDistance(pointX2, pointY2, midX, midY);
- float distance2 = GetDistance(pointX3, pointY3, midX, midY) + GetDistance(pointX4, pointY4, midX, midY);
- //长短轴斜率
- float k1 = (float)(pointY2 - pointY1) / (pointX2 - pointX1);
- float k2 = (float)(pointY4 - pointY3) / (pointX4 - pointX3);
- if ((distance1 >= distance2)&&k1>0)
- {
- if (humanOrientationFlagY == 0)
- {
- Point2D[] points = { new Point2D(pointX1, pointY1), new Point2D(midX + distanceX/4, midY) };
- result = points;
- }
- else
- {
- Point2D[] points = { new Point2D(pointX2, pointY2), new Point2D(midX - distanceX/4, midY) };
- result = points;
- }
- }
- else if((distance1 <= distance2) && k2 < 0)
- {
- if (humanOrientationFlagX == 0)
- {
- Point2D[] points = { new Point2D(pointX3, pointY3), new Point2D(midX, midY + distanceY/4) };
- result = points;
- }
- else
- {
- Point2D[] points = { new Point2D(pointX4, pointY4), new Point2D(midX, midY - distanceY/4) };
- result = points;
- }
- }
- else
- {
- return null;
- }
- }
- return result;
- }
- #endregion
- }
- }
|