private static ITemplate create(IEnumerable <PointF> normalizedPoints,
                                        int scale,
                                        int rotation,
                                        string label = "")
        {
            var pointTransform = Transforms2D.Combine
                                 (
                Transforms2D.Scale(scale, scale),
                Transforms2D.Rotation((float)Angle.ToRadians(rotation))
                                 );

            var transformedPts = normalizedPoints.Transform(pointTransform).ToList();

            var boundingRect = transformedPts.BoundingRect();
            var offset       = boundingRect.Location;

            transformedPts = transformedPts.Transform(Transforms2D.Translation(-offset.X, -offset.Y)).ToList();

            var template = new OpenHandTemplate();

            var features = new List <Feature>();

            //var validIdxRange = CardinalSpline.ValidIndicesRange(transformedPts.Count);
            //for (int i = validIdxRange.Min; i <= validIdxRange.Max; i++)
            for (int i = CardinalSpline.MIN_INDEX; i < (transformedPts.Count - 1 - CardinalSpline.MAX_INDEX_OFFSET); i++)
            {
                var intPt = transformedPts[i].Round();

                var direction = CardinalSpline.NormalAt(transformedPts, CONTOUR_TENSION, i);
                var orientDeg = (int)Angle.ToDegrees(Math.Atan2(direction.Y, direction.X));
                orientDeg = (int)Angle.NormalizeDegrees(orientDeg + 180);

                var feature = createFeature(intPt.X, intPt.Y, orientDeg);
                features.Add(feature);
            }

            template.Features   = features.ToArray();
            template.Size       = Size.Round(boundingRect.Size);
            template.ClassLabel = label;

            return(template);
        }
        private void timer_Tick(object sender, EventArgs e)
        {
            const int BORDER_OFFSET = 20;

            scale += 10 * dScale; if (scale > 300)
            {
                dScale = -1;
            }
            if (scale < 100)
            {
                dScale = 1;
            }
            angle += 5 * dAngle;  if (angle > 360)
            {
                dAngle = -1;
            }
            if (dAngle < 0)
            {
                dAngle = 1;
            }

            var transformation = Transforms2D.Combine
                                 (
                Transforms2D.Rotation((float)Angle.ToRadians(angle)),
                Transforms2D.Scale(scale, scale)
                                 );

            IEnumerable <PointF> pts = modelPts.Transform(transformation);

            var box = pts.BoundingRect(); //maybe apply it to bounding box instead of points (expensive)

            pts = pts.Transform(Transforms2D.Translation(-box.X + BORDER_OFFSET, -box.Y + BORDER_OFFSET));

            var image = new Image <Bgr, byte>(scale + BORDER_OFFSET * 2, scale + BORDER_OFFSET * 2);

            drawContour(pts.ToList(), image);
            pictureBox.Image = image.ToBitmap();
        }