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 countXList = new List(); private List countYList = new List(); private List countMidXList = new List(); private List countMidYList = new List(); private List countList = new List(); #endregion #region 实现 /// /// 获取图像坐标系下初始扫查路径点 /// /// /// /// /// 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; } /// /// 人体在X和Y方向的判断 /// /// /// /// /// 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; } } /// /// 轮廓的中心点和外接框宽高 /// /// /// /// /// /// /// 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 contoursX = new List(); List contoursY = new List(); 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; } } /// /// 判断轮廓位置是否正常 /// /// /// 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; } } /// /// 计算两点间距离 /// /// /// /// /// /// 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; } /// /// 轮廓四个顶点 /// /// /// /// /// /// /// 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 } }