/// <summary> /// Given an image, says whether classifier should go left or right int the classification tree. /// </summary> /// <param name="grayImage">integral of source image</param> /// <param name="squares">integral of squares</param> /// <param name="i">x coordinate</param> /// <param name="j">y coordinate</param> /// <param name="scale">scale to scale image to (i.e. 2 would look for stuff twice as big)</param> /// <returns></returns> public int getLeftOrRight(int[][] grayImage, int[][] squares, int i, int j, float scale) { // Figure out size of the image int w = (int)(scale * size.X); int h = (int)(scale * size.Y); // can fold w*h into a constant // division? double inv_area = 1 / (double)(w * h); // Get a normalization Coefficient int total_x = grayImage[i + w][j + h] + grayImage[i][j] - grayImage[i][j + h] - grayImage[i + w][j]; int total_x2 = squares[i + w][j + h] + squares[i][j] - squares[i][j + h] - squares[i + w][j]; double moy = total_x * inv_area; double vnorm = total_x2 * inv_area - moy * moy; // sqrt? vnorm = (vnorm > 1) ? Math.Sqrt(vnorm) : 1; int rect_sum = 0; for (int k = 0; k < nb_rects; k++) { RectFeature r = rects[k]; // Get coordinates of rectangles for computation and add them to sum // This is the feature value computation for each feature int rx1 = i + (int)(scale * r.x1); int rx2 = i + (int)(scale * (r.x1 + r.y1)); int ry1 = j + (int)(scale * r.x2); int ry2 = j + (int)(scale * (r.x2 + r.y2)); rect_sum += (int)((grayImage[rx2][ry2] - grayImage[rx1][ry2] - grayImage[rx2][ry1] + grayImage[rx1][ry1]) * r.weight); } // Normalize by area double rect_sum2 = rect_sum * inv_area; // If the sum of the rectangle area is less than the threshold * a normalization factor go left otherwise go right. return((rect_sum2 < threshold * vnorm) ? Tree.LEFT : Tree.RIGHT); }
/// <summary> /// Construct the detector given an XML document describing the model file. /// This method parses the XML file and builds the feature medel /// </summary> /// <param name="document"></param> public Detector(XDocument document) { //Debug.WriteLine("loading document " + document); m_stages = new List <Stage>(); var root = document.Root.Elements().First(); Debug.Assert(root != null, "xml document root is not haarcascade_frontalface_alt"); // Get the size of the classifier (size of the region to look at, i.e. 20 x 20 string[] sizeStr = (from node in root.Descendants() where node.Name.LocalName == "size" select node.Value.Trim().Split(' ')).First().ToArray(); m_size = new System.Windows.Point(Convert.ToDouble(sizeStr[0], CultureInfo.InvariantCulture), Convert.ToDouble(sizeStr[1], CultureInfo.InvariantCulture)); var stagesRoot = root.Descendants().Where(x => x.Name.LocalName == "stages").First(); var stages = stagesRoot.Elements(); foreach (XElement stage in stages) { // There's an extra level for some reason so we have to do down one var trueStage = stage; float stage_threshold = (float)Convert.ToDouble(trueStage.Element("stage_threshold").Value.Trim(), CultureInfo.InvariantCulture); Stage st = new Stage(stage_threshold); var trees = trueStage.Element("trees"); foreach (XElement tree in trees.Elements()) { // There's an extra level for some reason so we have to do down one XElement trueTree = tree.Elements().First(); Tree t = new Tree(); XElement feature = trueTree.Element("feature"); float threshold = (float)Convert.ToDouble(trueTree.Element("threshold").Value.Trim(), CultureInfo.InvariantCulture); int left_node = -1; float left_val = 0; bool has_left_val = false; int right_node = -1; float right_val = 0; bool has_right_val = false; XElement e = trueTree.Element("left_val"); if (e != null) { left_val = (float)Convert.ToDouble(e.Value.Trim(), CultureInfo.InvariantCulture); has_left_val = true; } else { left_node = Convert.ToInt32(trueTree.Element("left_node").Value.Trim(), CultureInfo.InvariantCulture); has_left_val = false; } e = trueTree.Element("right_val"); if (e != null) { right_val = (float)Convert.ToDouble(e.Value.Trim(), CultureInfo.InvariantCulture); has_right_val = true; } else { right_node = Convert.ToInt32(trueTree.Element("right_node").Value.Trim(), CultureInfo.InvariantCulture); has_right_val = false; } Feature f = new Feature(threshold, left_val, left_node, has_left_val, right_val, right_node, has_right_val, m_size); var rects = feature.Element("rects"); foreach (var r in rects.Elements()) { string rstr = r.Value.Trim(); RectFeature rect = RectFeature.fromString(rstr); f.add(rect); } t.addFeature(f); st.addTree(t); } m_stages.Add(st); } //Debug.WriteLine("Number of stages is " + m_stages.Count); //Debug.WriteLine("size str is " + m_stages.Count); }
public void add(RectFeature r) { rects[nb_rects++] = r; }