예제 #1
0
        static Point[] ScaleRegion(Point[] region, Point target, bool uniformScaling)
        {
            var centroid = Point2f.Zero;
            var min      = new Point(int.MaxValue, int.MaxValue);
            var max      = new Point(int.MinValue, int.MinValue);

            for (int i = 0; i < region.Length; i++)
            {
                centroid.X += region[i].X;
                centroid.Y += region[i].Y;
                min.X       = Math.Min(min.X, region[i].X);
                min.Y       = Math.Min(min.Y, region[i].Y);
                max.X       = Math.Max(max.X, region[i].X);
                max.Y       = Math.Max(max.Y, region[i].Y);
            }

            centroid.X /= region.Length;
            centroid.Y /= region.Length;
            var scale = new Point2f(
                2 * (target.X - centroid.X) / (max.X - min.X),
                2 * (target.Y - centroid.Y) / (max.Y - min.Y));

            if (uniformScaling)
            {
                var scaleNorm = (float)Math.Sqrt(scale.X * scale.X + scale.Y * scale.Y);
                scale.X = scaleNorm;
                scale.Y = scaleNorm;
            }
            return(Array.ConvertAll(region, point => new Point(
                                        (int)((point.X - centroid.X) * scale.X + centroid.X),
                                        (int)((point.Y - centroid.Y) * scale.Y + centroid.Y))));
        }
예제 #2
0
 static Point[] CreateRectangularRegion(Point origin, Point location)
 {
     return(new[]
     {
         origin, new Point(location.X, origin.Y),
         location, new Point(origin.X, location.Y)
     });
 }
        static RotatedRect CreateEllipseRegion(Point origin, Point location)
        {
            RotatedRect region;

            region.Size   = new Size2f(Math.Abs(location.X - origin.X), Math.Abs(location.Y - origin.Y));
            region.Center = new Point2f((location.X + origin.X) / 2f, (location.Y + origin.Y) / 2f);
            region.Angle  = 0;
            return(region);
        }
예제 #4
0
 int NearestPoint(Point[] region, Point location)
 {
     return((from point in region.Select((p, i) => new { p, i })
             let distanceX = location.X - point.p.X
                             let distanceY = location.Y - point.p.Y
                                             orderby distanceX * distanceX + distanceY * distanceY ascending
                                             select point.i)
            .FirstOrDefault());
 }
        float TestIntersection(RotatedRect region, Point point)
        {
            var dx = point.X - region.Center.X;
            var dy = point.Y - region.Center.Y;
            var a  = region.Size.Width * region.Size.Width / 4;
            var b  = region.Size.Height * region.Size.Height / 4;

            return(dx * dx / a + dy * dy / b);
        }
예제 #6
0
        Tuple <int, int> NearestLine(Point[] region, Point location)
        {
            var pointIndex = region
                             .Concat(Enumerable.Repeat(region[0], 1))
                             .Select((p, i) => new { p, i = i % region.Length });

            return((from line in pointIndex.Zip(pointIndex.Skip(1), (l0, l1) => Tuple.Create(l0, l1))
                    let lineDistance = PointLineSegmentDistance(location, line.Item1.p, line.Item2.p)
                                       orderby lineDistance ascending
                                       select Tuple.Create(line.Item1.i, line.Item2.i))
                   .FirstOrDefault());
        }
예제 #7
0
        double TestIntersection(Point[] region, Point point)
        {
            var regionHandle = GCHandle.Alloc(region, GCHandleType.Pinned);

            try
            {
                using (var mat = new Mat(region.Length, 1, Depth.S32, 2, regionHandle.AddrOfPinnedObject()))
                {
                    return(CV.PointPolygonTest(mat, new Point2f(point.X, point.Y), true));
                }
            }
            finally { regionHandle.Free(); }
        }
예제 #8
0
        static Point[] CreateEllipseRegion(Point origin, Point location)
        {
            var region = new Point[36];
            var scaleX = Math.Abs(location.X - origin.X) / 2f;
            var scaleY = Math.Abs(location.Y - origin.Y) / 2f;
            var center = new Point2f((location.X + origin.X) / 2f, (location.Y + origin.Y) / 2f);

            for (int i = 0; i < region.Length; i++)
            {
                var angle = i * 2 * Math.PI / region.Length;
                region[i].X = (int)Math.Round(Math.Cos(angle) * scaleX + center.X);
                region[i].Y = (int)Math.Round(Math.Sin(angle) * scaleY + center.Y);
            }

            return(region);
        }
        static RotatedRect ScaleRegion(RotatedRect region, Point target, bool uniformScaling)
        {
            var size = new Size2f(
                2 * Math.Abs(target.X - region.Center.X),
                2 * Math.Abs(target.Y - region.Center.Y));

            if (uniformScaling)
            {
                var sizeNorm = (float)Math.Sqrt(size.Width * size.Width + size.Height * size.Height);
                region.Size.Width  = sizeNorm;
                region.Size.Height = sizeNorm;
            }
            else
            {
                region.Size = size;
            }
            return(region);
        }
 Point EnsureSizeRatio(Point origin, Point location, bool square)
 {
     if (square)
     {
         var dx     = location.X - origin.X;
         var dy     = location.Y - origin.Y;
         var width  = Math.Abs(dx);
         var height = Math.Abs(dy);
         if (width < height)
         {
             location.Y -= Math.Sign(dy) * (height - width);
         }
         else
         {
             location.X -= Math.Sign(dx) * (width - height);
         }
     }
     return(location);
 }
 static RotatedRect MoveRegion(RotatedRect region, Point displacement)
 {
     region.Center += new Point2f(displacement);
     return(region);
 }
예제 #12
0
 public void SetPoint(int regionIndex, int pointIndex, Point value)
 {
     Items[regionIndex][pointIndex] = value;
     OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
 }
예제 #13
0
        void Canvas_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.PageUp)
            {
                ImageScale += ScaleIncrement;
            }
            if (e.KeyCode == Keys.PageDown)
            {
                ImageScale -= ScaleIncrement;
            }
            if (e.Control && e.KeyCode == Keys.Z)
            {
                commandExecutor.Undo();
            }
            if (e.Control && e.KeyCode == Keys.Y)
            {
                commandExecutor.Redo();
            }
            if (e.Control && e.KeyCode == Keys.V)
            {
                var roiText = (string)Clipboard.GetData(DataFormats.Text);
                try
                {
                    var mousePosition = PointToClient(MousePosition);
                    var offset        = NormalizedLocation(mousePosition.X, mousePosition.Y);
                    var roiData       = (int[])ArrayConvert.ToArray(roiText, 1, typeof(int));
                    var roi           = new Point[roiData.Length / 2];
                    for (int i = 0, k = 0; i < roi.Length && k < roiData.Length; i++, k += 2)
                    {
                        roi[i].X = roiData[k + 0] - roiData[0] + offset.X;
                        roi[i].Y = roiData[k + 1] - roiData[1] + offset.Y;
                    }

                    var selection = selectedRoi;
                    commandExecutor.Execute(
                        () => AddRegion(roi),
                        () => { regions.Remove(roi); SelectedRegion = selection; });
                }
                catch (ArgumentException) { }
                catch (InvalidCastException) { }
                catch (FormatException) { }
            }

            if (selectedRoi.HasValue)
            {
                if (e.Control && e.KeyCode == Keys.C)
                {
                    var roi     = regions[selectedRoi.Value];
                    var roiData = new int[roi.Length * 2];
                    for (int i = 0, k = 0; i < roi.Length && k < roiData.Length; i++, k += 2)
                    {
                        roiData[k + 0] = roi[i].X;
                        roiData[k + 1] = roi[i].Y;
                    }
                    Clipboard.SetData(DataFormats.Text, ArrayConvert.ToString(roiData));
                }

                if (e.KeyCode == Keys.Delete)
                {
                    var selection = selectedRoi.Value;
                    var region    = regions[selection];
                    commandExecutor.Execute(
                        () => { regions.RemoveAt(selection); SelectedRegion = null; },
                        () => { regions.Insert(selection, region); SelectedRegion = selection; });
                }
            }
        }
예제 #14
0
 static float PointLineSegmentDistance(Point point, Point line0, Point line1)
 {
     return(PointLineSegmentDistance(new Vector2(point.X, point.Y), new Vector2(line0.X, line0.Y), new Vector2(line1.X, line1.Y)));
 }
예제 #15
0
 static Point[] MoveRegion(Point[] region, Point displacement)
 {
     return(Array.ConvertAll(region, point => point + displacement));
 }
예제 #16
0
        public ImageRoiPicker()
        {
            Canvas.KeyDown += Canvas_KeyDown;
            commandExecutor.StatusChanged += commandExecutor_StatusChanged;
            regions.CollectionChanged     += regions_CollectionChanged;
            var mouseDoubleClick = Observable.FromEventPattern <MouseEventArgs>(Canvas, "MouseDoubleClick").Select(e => e.EventArgs);
            var mouseMove        = Observable.FromEventPattern <MouseEventArgs>(Canvas, "MouseMove").Select(e => e.EventArgs);
            var mouseDown        = Observable.FromEventPattern <MouseEventArgs>(Canvas, "MouseDown").Select(e => e.EventArgs);
            var mouseUp          = Observable.FromEventPattern <MouseEventArgs>(Canvas, "MouseUp").Select(e => e.EventArgs);

            var roiSelected = from downEvt in mouseDown
                              where Image != null
                              let location = NormalizedLocation(downEvt.X, downEvt.Y)
                                             let selection = (from region in regions.Select((polygon, i) => new { polygon, i = (int?)i })
                                                              let distance = TestIntersection(region.polygon, location)
                                                                             where distance > 0
                                                                             orderby distance
                                                                             select region.i)
                                                             .FirstOrDefault()
                                                             select new Action(() => SelectedRegion = selection);

            var roiMoveScale = (from downEvt in mouseDown
                                where Image != null && downEvt.Button == MouseButtons.Left && selectedRoi.HasValue
                                let location = NormalizedLocation(downEvt.X, downEvt.Y)
                                               let selection = selectedRoi.Value
                                                               let region = regions[selection]
                                                                            select(from moveEvt in mouseMove.TakeUntil(mouseUp)
                                                                                   let target = NormalizedLocation(moveEvt.X, moveEvt.Y)
                                                                                                let modifiedRegion = ModifierKeys.HasFlag(Keys.Shift)
                                            ? ScaleRegion(region, target, ModifierKeys.HasFlag(Keys.Control))
                                            : MoveRegion(region, target - location)
                                                                                                                     let modifiedRectangle = RegionRectangle(modifiedRegion)
                                                                                                                                             where modifiedRectangle.Left >= 0 && modifiedRectangle.Top >= 0 &&
                                                                                                                                             modifiedRectangle.Right < Image.Width && modifiedRectangle.Bottom < Image.Height
                                                                                                                                             select modifiedRegion)
                                                                            .Publish(ps =>
                                                                                     ps.TakeLast(1).Do(modifiedRegion =>
                                                                                                       commandExecutor.Execute(
                                                                                                           () => regions[selection] = modifiedRegion,
                                                                                                           () => regions[selection] = region))
                                                                                     .Merge(ps))
                                                                            .Select(displacedRegion => new Action(() => regions[selectedRoi.Value] = displacedRegion)))
                               .Switch();

            var pointMove = (from downEvt in mouseDown
                             where Image != null && downEvt.Button == MouseButtons.Right && selectedRoi.HasValue
                             let location = NormalizedLocation(downEvt.X, downEvt.Y)
                                            let selection = selectedRoi.Value
                                                            let region = regions[selection]
                                                                         let nearestPoint = NearestPoint(region, location)
                                                                                            let source = regions[selection][nearestPoint]
                                                                                                         select(from moveEvt in mouseMove.TakeUntil(mouseUp)
                                                                                                                let target = NormalizedLocation(moveEvt.X, moveEvt.Y)
                                                                                                                             select target)
                                                                                                         .Publish(ps =>
                                                                                                                  ps.TakeLast(1).Do(target =>
                                                                                                                                    commandExecutor.Execute(
                                                                                                                                        () => regions.SetPoint(selection, nearestPoint, target),
                                                                                                                                        () => regions.SetPoint(selection, nearestPoint, source)))
                                                                                                                  .Merge(ps))
                                                                                                         .Select(target => new Action(() => regions.SetPoint(selection, nearestPoint, target))))
                            .Switch();

            var regionInsertion = (from downEvt in mouseDown
                                   where Image != null && downEvt.Button == MouseButtons.Left && !selectedRoi.HasValue
                                   let count = regions.Count
                                               let origin = NormalizedLocation(downEvt.X, downEvt.Y)
                                                            select(from moveEvt in mouseMove.TakeUntil(mouseUp)
                                                                   let location = EnsureSizeRatio(origin, NormalizedLocation(moveEvt.X, moveEvt.Y), ModifierKeys.HasFlag(Keys.Control))
                                                                                  select ModifierKeys.HasFlag(Keys.Shift)
                                               ? CreateEllipseRegion(origin, location)
                                               : CreateRectangularRegion(origin, location))
                                                            .Publish(ps =>
                                                                     ps.TakeLast(1).Do(region =>
                                                                                       commandExecutor.Execute(
                                                                                           () => { if (count == regions.Count)
                                                                                                   {
                                                                                                       AddRegion(region);
                                                                                                   }
                                                                                           },
                                                                                           () => { regions.Remove(region); SelectedRegion = null; }))
                                                                     .Merge(ps))
                                                            .Select(region => new Action(() =>
            {
                if (selectedRoi.HasValue)
                {
                    regions[selectedRoi.Value] = region;
                }
                else
                {
                    AddRegion(region);
                }
            })))
                                  .Switch();

            var pointInsertion = from clickEvt in mouseDoubleClick
                                 where Image != null && clickEvt.Button == MouseButtons.Left && selectedRoi.HasValue
                                 let location = NormalizedLocation(clickEvt.X, clickEvt.Y)
                                                let region = regions[selectedRoi.Value]
                                                             let nearestLine = NearestLine(region, location)
                                                                               select new Action(() =>
            {
                var resizeRegion = region;
                var line0        = region[nearestLine.Item1];
                var line1        = region[nearestLine.Item2];
                var midPoint     = new Point((line0.X + line1.X) / 2, (line0.Y + line1.Y) / 2);
                Array.Resize(ref resizeRegion, resizeRegion.Length + 1);
                for (int i = resizeRegion.Length - 1; i > nearestLine.Item2; i--)
                {
                    resizeRegion[i] = resizeRegion[i - 1];
                }

                var selection = selectedRoi.Value;
                resizeRegion[nearestLine.Item2] = midPoint;
                commandExecutor.Execute(
                    () => regions[selection] = resizeRegion,
                    () => regions[selection] = region);
            });

            var pointDeletion = from clickEvt in mouseDoubleClick
                                where Image != null && clickEvt.Button == MouseButtons.Right && selectedRoi.HasValue
                                let region = regions[selectedRoi.Value]
                                             where region.Length > 3
                                             let location = NormalizedLocation(clickEvt.X, clickEvt.Y)
                                                            let nearestPoint = NearestPoint(region, location)
                                                                               select new Action(() =>
            {
                var selection    = selectedRoi.Value;
                var resizeRegion = new Point[region.Length - 1];
                Array.Copy(region, resizeRegion, nearestPoint);
                Array.Copy(region, nearestPoint + 1, resizeRegion, nearestPoint, region.Length - nearestPoint - 1);
                commandExecutor.Execute(
                    () => regions[selection] = resizeRegion,
                    () => regions[selection] = region);
            });

            var roiActions = Observable.Merge(roiSelected, pointMove, roiMoveScale, pointInsertion, pointDeletion, regionInsertion);

            roiActions.Subscribe(action =>
            {
                action();
            });
        }
예제 #17
0
 public MatchPoint(OpenCV.Net.Point pt, double val)
 {
     X           = pt.X;
     Y           = pt.Y;
     Punctuality = val;
 }