private static SubgroupOfPoints CountSumOfDistancesFromPlane(double[,] matrix, double[,] vector, List <LasPoint> points, int pointsCount, ref double avgIntensity, ref double avgHeight, int classIndex) { avgIntensity /= pointsCount; avgHeight /= pointsCount; matrix[2, 2] = pointsCount; Matrix <double> A = DenseMatrix.OfArray(matrix); Matrix <double> b = DenseMatrix.OfArray(vector); Matrix <double> x; A = A.Inverse(); x = b.Multiply(A); double[,] myarray; myarray = x.ToArray(); Vector3 abc = new Vector3(Convert.ToSingle(myarray[0, 0]), Convert.ToSingle(myarray[0, 1]), Convert.ToSingle(myarray[0, 2])); double d = 0; for (int k = 0; k < pointsCount; k++) { d += Math.Abs((abc.X * points[k].X) + (abc.Y * points[k].Y) + (abc.Z * points[k].Z)) / Math.Sqrt((abc.X * abc.X) + (abc.Y * abc.Y) + (abc.Z * abc.Z)); } d = d / pointsCount; SubgroupOfPoints group = new SubgroupOfPoints(classIndex, Convert.ToSingle(d), Convert.ToSingle(avgIntensity), abc, Convert.ToSingle(avgHeight)); return(group); }
public static Tuple <double[][], int[]> MakeInputOutputs(List <SubgroupOfPoints> values) { Console.WriteLine("Preparing training dataset... "); Stopwatch sw = Stopwatch.StartNew(); int count = values.Count; int[] outputs = new int[count]; double[][] inputs = new double[count][]; for (int i = 0; i < count; i++) { SubgroupOfPoints value = values[i]; // ClassificationType.Ground if (value.classIndex == 4) { inputs[i] = new double[] { value.avgDistance, value.avgHeight, value.avgIntensity, value.slopeVector.X, value.slopeVector.Y, value.slopeVector.Z }; outputs[i] = 0; } // ClassificationType.HighVegetation else if (value.classIndex == 2) { inputs[i] = new double[] { value.avgDistance, value.avgHeight, value.avgIntensity, value.slopeVector.X, value.slopeVector.Y, value.slopeVector.Z }; outputs[i] = 1; } // ClassificationType.Building else if (value.classIndex == 0) { inputs[i] = new double[] { value.avgDistance, value.avgHeight, value.avgIntensity, value.slopeVector.X, value.slopeVector.Y, value.slopeVector.Z }; outputs[i] = 2; } // ClassificationType.MediumVegetation else if (value.classIndex == 1) { inputs[i] = new double[] { value.avgDistance, value.avgHeight, value.avgIntensity, value.slopeVector.X, value.slopeVector.Y, value.slopeVector.Z }; outputs[i] = 3; } // ClassificationType.LowVegetation else if (value.classIndex == 3) { inputs[i] = new double[] { value.avgDistance, value.avgHeight, value.avgIntensity, value.slopeVector.X, value.slopeVector.Y, value.slopeVector.Z }; outputs[i] = 4; } // ClassificationType.Water else if (value.classIndex == 5) { inputs[i] = new double[] { value.avgDistance, value.avgHeight, value.avgIntensity, value.slopeVector.X, value.slopeVector.Y, value.slopeVector.Z }; outputs[i] = 5; } } sw.Stop(); Console.WriteLine("Preparing training dataset completed [" + sw.Elapsed.TotalSeconds.ToString() + "s]"); return(new Tuple <double[][], int[]>(inputs, outputs)); }
public static SubgroupOfPoints[,] GroupPoints(LasFile file, int divisionCountX, int divisionCountY) { SubgroupOfPoints[,] results = new SubgroupOfPoints[divisionCountX, divisionCountY]; bool enoughPoints; float percentOfClassTypeThreshold; int PointsCount; double minX, minY, ratioX, ratioY; double[,] matrix, vector; List <LasPoint>[,] pieces; PrepareGroupPointsData(file, divisionCountX, divisionCountY, out enoughPoints, out percentOfClassTypeThreshold, out PointsCount, out minX, out minY, out ratioX, out ratioY, out matrix, out vector, out pieces); for (int i = 0; i < PointsCount; i++) { var xReal = (float)file.LasPointDataRecords[i].X; var yReal = (float)file.LasPointDataRecords[i].Y; int arrayX = (int)((xReal - minX) / ratioX); int arrayY = (int)((yReal - minY) / ratioY); if ((arrayX < divisionCountX) && (arrayY < divisionCountY)) { pieces[arrayX, arrayY].Add(file.LasPointDataRecords[i]); } } for (int i = 0; i < divisionCountX; i++) { for (int j = 0; j < divisionCountY; j++) { List <LasPoint> points; int pointsCount; double avgIntensity, avgHeight; int[] groupClass; CountGroupPointsParams(out enoughPoints, matrix, vector, pieces, i, j, out points, out pointsCount, out avgIntensity, out avgHeight, out groupClass); int classIndex = 6; if (pointsCount < 12) { results[i, j] = new SubgroupOfPoints(7); enoughPoints = false; } else { if (groupClass[0] >= (percentOfClassTypeThreshold * pointsCount)) { classIndex = 0; } else if (groupClass[1] >= (percentOfClassTypeThreshold * pointsCount)) { classIndex = 1; } else if (groupClass[2] >= (percentOfClassTypeThreshold * pointsCount)) { classIndex = 2; } else if (groupClass[3] >= (percentOfClassTypeThreshold * pointsCount)) { classIndex = 3; } else if (groupClass[4] >= (percentOfClassTypeThreshold * pointsCount)) { classIndex = 4; } else if (groupClass[5] >= (percentOfClassTypeThreshold * pointsCount)) { classIndex = 5; } } if (enoughPoints) { SubgroupOfPoints group = CountSumOfDistancesFromPlane(matrix, vector, points, pointsCount, ref avgIntensity, ref avgHeight, classIndex); results[i, j] = group; } } } return(results); }
public static List <SubgroupOfPoints> GroupPointsList(LasFile file, int divisionCountX, int divisionCountY) { Console.WriteLine("Preparing input dataset... "); Stopwatch sw = Stopwatch.StartNew(); List <SubgroupOfPoints> results = new List <SubgroupOfPoints>(); bool enoughPoints; float percentOfClassTypeThreshold; int PointsCount; double minX, minY, ratioX, ratioY; double[,] matrix, vector; List <LasPoint>[,] pieces; PrepareGroupPointsData(file, divisionCountX, divisionCountY, out enoughPoints, out percentOfClassTypeThreshold, out PointsCount, out minX, out minY, out ratioX, out ratioY, out matrix, out vector, out pieces); for (int i = 0; i < PointsCount; i++) { var xReal = (float)file.LasPointDataRecords[i].X; var yReal = (float)file.LasPointDataRecords[i].Y; int arrayX = (int)((xReal - minX) / ratioX); int arrayY = (int)((yReal - minY) / ratioY); if ((arrayX < divisionCountX) && (arrayY < divisionCountY)) { pieces[arrayX, arrayY].Add(file.LasPointDataRecords[i]); } } for (int i = 0; i < divisionCountX; i++) { for (int j = 0; j < divisionCountY; j++) { List <LasPoint> points; int pointsCount; double avgIntensity, avgHeight; int[] groupClass; CountGroupPointsParams(out enoughPoints, matrix, vector, pieces, i, j, out points, out pointsCount, out avgIntensity, out avgHeight, out groupClass); int classIndex = 6; if (pointsCount >= 12) { if (groupClass[0] >= (percentOfClassTypeThreshold * pointsCount)) { classIndex = 0; } else if (groupClass[1] >= (percentOfClassTypeThreshold * pointsCount)) { classIndex = 1; } else if (groupClass[2] >= (percentOfClassTypeThreshold * pointsCount)) { classIndex = 2; } else if (groupClass[3] >= (percentOfClassTypeThreshold * pointsCount)) { classIndex = 3; } else if (groupClass[4] >= (percentOfClassTypeThreshold * pointsCount)) { classIndex = 4; } else if (groupClass[5] >= (percentOfClassTypeThreshold * pointsCount)) { classIndex = 5; } } else { enoughPoints = false; } if (enoughPoints) { SubgroupOfPoints group = CountSumOfDistancesFromPlane(matrix, vector, points, pointsCount, ref avgIntensity, ref avgHeight, classIndex); results.Add(group); } } } int[] classCount = new int[8]; float[] percentOfClassInputs = { 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f, 0.25f }; foreach (SubgroupOfPoints group in results) { if (group.classIndex == 0) { classCount[0]++; } else if (group.classIndex == 1) { classCount[1]++; } else if (group.classIndex == 2) { classCount[2]++; } else if (group.classIndex == 3) { classCount[3]++; } else if (group.classIndex == 4) { classCount[4]++; } else if (group.classIndex == 5) { classCount[5]++; } else if (group.classIndex == 6) { classCount[6]++; } } results.Sort((a, b) => a.classIndex.CompareTo(b.classIndex)); List <SubgroupOfPoints> properResults = new List <SubgroupOfPoints>(); properResults.AddRange(results.GetRange(0, (int)(classCount[0] * percentOfClassInputs[0]))); properResults.AddRange(results.GetRange(classCount[0], (int)(classCount[1] * percentOfClassInputs[1]))); properResults.AddRange(results.GetRange(classCount[0] + classCount[1], (int)(classCount[2] * percentOfClassInputs[2]))); properResults.AddRange(results.GetRange(classCount[0] + classCount[1] + classCount[2], (int)(classCount[3] * percentOfClassInputs[3]))); properResults.AddRange(results.GetRange(classCount[0] + classCount[1] + classCount[2] + classCount[3], (int)(classCount[4] * percentOfClassInputs[4]))); properResults.AddRange(results.GetRange(classCount[0] + classCount[1] + classCount[2] + classCount[3] + classCount[4], (int)(classCount[5] * percentOfClassInputs[5]))); sw.Stop(); Console.WriteLine("Preparing input dataset completed [" + sw.Elapsed.TotalSeconds.ToString() + "s]"); return(properResults); }