public void GenerateFeaturesTree(IRaster3DInteger raster, IMaxTreeNode <float> bottom_level_node, float[,] features) { //Generate from the leafs downwards Queue <IMaxTreeNode <float> > queue = new Queue <IMaxTreeNode <float> >(); Stack <IMaxTreeNode <float> > node_stack = new Stack <IMaxTreeNode <float> >(); queue.Enqueue(bottom_level_node); while (queue.Count != 0) { IMaxTreeNode <float> node = queue.Dequeue(); node_stack.Push(node); foreach (IMaxTreeNode <float> child_node in node.GetNodeChildren()) { queue.Enqueue(child_node); } } while (node_stack.Count != 0) { IMaxTreeNode <float> node = node_stack.Pop(); GenerateFeaturesNode(raster, node, features); } }
/** Scale and rotation invariant 3D features * As in disertation Fred Kawanuka page 79 & Wilkinson Roerding for scale invariant matrix */ private void GenerateFeaturesNode( IRaster3DInteger raster, IMaxTreeNode <float> node, float [,] features) { int node_index = node.NodeIndex; // 1 get_size float size = node.CulmativeRealSize; // 2 compute geometric moments int [] elements = node.GetElementIndexArrayNodeReal(); foreach (int element_index in elements) { raster.GetElementCoordinatesRBA(element_index, element_coordinates); features[node_index, IndexSX] += element_coordinates[0]; features[node_index, IndexSY] += element_coordinates[1]; features[node_index, IndexSZ] += element_coordinates[2]; features[node_index, IndexSXX] += element_coordinates[0] * element_coordinates[0]; features[node_index, IndexSYY] += element_coordinates[1] * element_coordinates[1]; features[node_index, IndexSZZ] += element_coordinates[2] * element_coordinates[2]; features[node_index, IndexSXY] += element_coordinates[0] * element_coordinates[1]; features[node_index, IndexSXZ] += element_coordinates[0] * element_coordinates[2]; features[node_index, IndexSYZ] += element_coordinates[1] * element_coordinates[2]; } foreach (IMaxTreeNode <float> child in node.GetNodeChildren()) { int child_node_index = child.NodeIndex; features[node_index, IndexSX] += features[child_node_index, IndexSX]; features[node_index, IndexSY] += features[child_node_index, IndexSY]; features[node_index, IndexSZ] += features[child_node_index, IndexSY]; features[node_index, IndexSXX] += features[child_node_index, IndexSXX]; features[node_index, IndexSYY] += features[child_node_index, IndexSYY]; features[node_index, IndexSZZ] += features[child_node_index, IndexSZZ]; features[node_index, IndexSXY] += features[child_node_index, IndexSXY]; features[node_index, IndexSXZ] += features[child_node_index, IndexSXZ]; features[node_index, IndexSYZ] += features[child_node_index, IndexSYZ]; } // 2 compute covariance matrix (only the parts we will use note tha) float x_mean = features[node_index, IndexSX] / size; float y_mean = features[node_index, IndexSY] / size; float z_mean = features[node_index, IndexSZ] / size; covariance_matrix[0] = features[node_index, IndexSXX] - 2 * features[node_index, IndexSX] * x_mean + x_mean * x_mean * size; covariance_matrix[4] = features[node_index, IndexSYY] - 2 * features[node_index, IndexSY] * y_mean + y_mean * y_mean * size; covariance_matrix[8] = features[node_index, IndexSZZ] - 2 * features[node_index, IndexSZ] * z_mean + z_mean * z_mean * size; covariance_matrix[1] = features[node_index, IndexSXY] - features[node_index, IndexSX] * y_mean - features[node_index, IndexSY] * x_mean + x_mean * y_mean * size; covariance_matrix[2] = features[node_index, IndexSXZ] - features[node_index, IndexSX] * z_mean - features[node_index, IndexSZ] * x_mean + x_mean * z_mean * size; covariance_matrix[5] = features[node_index, IndexSYZ] - features[node_index, IndexSY] * z_mean - features[node_index, IndexSZ] * y_mean + y_mean * z_mean * size; ; covariance_matrix[0] = (covariance_matrix[0] + size / 12.0f) / (float)Math.Pow(size, 5.0 / 3.0); covariance_matrix[4] = (covariance_matrix[4] + size / 12.0f) / (float)Math.Pow(size, 5.0 / 3.0); covariance_matrix[8] = (covariance_matrix[8] + size / 12.0f) / (float)Math.Pow(size, 5.0 / 3.0); covariance_matrix[1] = covariance_matrix[1] / (float)Math.Pow(size, 5.0 / 3.0); covariance_matrix[2] = covariance_matrix[2] / (float)Math.Pow(size, 5.0 / 3.0); covariance_matrix[5] = covariance_matrix[5] / (float)Math.Pow(size, 5.0 / 3.0); // CollectionTools.print(covariance_matrix); // 3 compute eigenvalues ToolsMathMatrix3Float32.EigenvaluesSymetricRBA(covariance_matrix, eigenvalues); // compute non-compactness features[node_index, IndexNonCompactness] = eigenvalues[0] + eigenvalues[1] + eigenvalues[2]; // 4 sort so that e_abs[0] < e_abs[1] < e_abs[2] eigenvalues[0] = Math.Abs(eigenvalues[0]); eigenvalues[1] = Math.Abs(eigenvalues[1]); eigenvalues[2] = Math.Abs(eigenvalues[2]); Array.Sort(eigenvalues); // 5 compute d values float d0 = (float)Math.Sqrt((eigenvalues[0] * 20)); float d1 = (float)Math.Sqrt((eigenvalues[1] * 20)); float d2 = (float)Math.Sqrt((eigenvalues[2] * 20)); // 6 Compute features: // compute elongation differ features[node_index, IndexElongation] = eigenvalues[2] / eigenvalues[1]; // compute flasness features[node_index, IndexFlatness] = eigenvalues[1] / eigenvalues[0]; // compute sparceness features[node_index, IndexSparceness] = d0 * d1 * d2; features[node_index, IndexSize] = size; }