check point
This commit is contained in:
@@ -0,0 +1,329 @@
|
||||
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using Hawkeye.VisionBuilder.Workflow;
|
||||
using Hawkeye.VisionBuilder.Workflow.Datatypes;
|
||||
using Hawkeye.VisionBuilder.Workflow.Datatypes.Elements;
|
||||
using Hawkeye.VisionBuilder.Workflow.Datatypes.Elements.Origin;
|
||||
using Hawkeye.VisionBuilder.Workflow.Datatypes.Elements.Poly;
|
||||
using OpenCvSharp;
|
||||
using OpenCvSharp.Extensions;
|
||||
using Point = System.Drawing.Point;
|
||||
using PointF = System.Drawing.PointF;
|
||||
using Matrix = Hawkeye.VisionBuilder.Workflow.Matrix;
|
||||
using Vector2 = Hawkeye.VisionBuilder.Workflow.Vector2;
|
||||
|
||||
namespace Hawkeye.VisionBuilder.Features.ImagePreview
|
||||
{
|
||||
public partial class ImagePreviewControl : UserControl,ICanvas
|
||||
{
|
||||
private Bitmap _backBuffer;
|
||||
public List<IGraphicsElement> GraphicsElements { get; set; }=new List<IGraphicsElement>();
|
||||
public EControlMode Mode { get; set; } = EControlMode.Preview;
|
||||
|
||||
public Hawkeye.VisionBuilder.Workflow.Datatypes.HawkeyeImage Image
|
||||
{
|
||||
get => _image;
|
||||
set
|
||||
{
|
||||
var needsCentering = _image == null;
|
||||
_image = value;
|
||||
if(needsCentering) CenterImage();
|
||||
}
|
||||
}
|
||||
|
||||
public void CenterImage()
|
||||
{
|
||||
TransformationMatrix= Workflow.Matrix.Identity;
|
||||
var hRatio = Width/ (float)_image.ImageData.Width;
|
||||
var vRatio = Height / (float) _image.ImageData.Height;
|
||||
TransformationMatrix*=Matrix.CreateScale(Math.Min(hRatio,vRatio));
|
||||
var shift = new Vector2(Width,Height)- Vector2.Transform(new Vector2(_image.ImageData.Width, _image.ImageData.Height),
|
||||
TransformationMatrix);
|
||||
TransformationMatrix *= Matrix.CreateTranslation(shift.X / 2f, shift.Y / 2f, 0);
|
||||
|
||||
}
|
||||
|
||||
public ImagePreviewControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
_backBuffer = new Bitmap(Width, Height);
|
||||
|
||||
MouseWheel += ZoomPictureBoxWheel_MouseWheel;
|
||||
DoubleClick += ZoomPictureBoxWheel_DoubleClick;
|
||||
DoubleBuffered = true;
|
||||
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
|
||||
}
|
||||
|
||||
private void ZoomPictureBoxWheel_DoubleClick(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
private float _zoom = 1;
|
||||
private void ZoomPictureBoxWheel_MouseWheel(object sender, MouseEventArgs e)
|
||||
{
|
||||
_zoom *= (e.Delta > 0) ? 0.9f : (1f / 0.9f);
|
||||
TransformationMatrix = TransformationMatrix
|
||||
* Matrix.CreateTranslation(-_lastMousePosition.X, -_lastMousePosition.Y, 0)
|
||||
* Matrix.CreateScale((e.Delta > 0) ? 0.9f : (1f / 0.9f))
|
||||
* Matrix.CreateTranslation(_lastMousePosition.X, _lastMousePosition.Y, 0);
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
public void FitToScreen()
|
||||
{
|
||||
if (Image == null) return;
|
||||
var width = Image.ImageData.Width;
|
||||
var height = Image.ImageData.Height;
|
||||
var aspectRatio = (float)width / height;
|
||||
var screenAspectRatio = (float)Width / Height;
|
||||
|
||||
if (aspectRatio > screenAspectRatio)
|
||||
{
|
||||
_zoom = Width / (float)width;
|
||||
TransformationMatrix = Matrix.Identity;
|
||||
TransformationMatrix *= Matrix.CreateScale(_zoom);
|
||||
var shift = new Vector2(Width, Height) - Vector2.Transform(new Vector2(width, height),
|
||||
TransformationMatrix);
|
||||
TransformationMatrix *= Matrix.CreateTranslation(shift.X / 2f, shift.Y / 2f, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
_zoom = Height / (float)height;
|
||||
TransformationMatrix = Matrix.Identity;
|
||||
TransformationMatrix *= Matrix.CreateScale(_zoom);
|
||||
var shift = new Vector2(Width, Height) - Vector2.Transform(new Vector2(width, height),
|
||||
TransformationMatrix);
|
||||
TransformationMatrix *= Matrix.CreateTranslation(shift.X / 2f, shift.Y / 2f, 0);
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
private MouseButtons _mouseButton = MouseButtons.None;
|
||||
|
||||
public Matrix TransformationMatrix { get; set; }=Matrix.Identity;
|
||||
|
||||
|
||||
private Vector2 _lastMousePosition;
|
||||
private const float NODE_SIZE = 10;
|
||||
protected override void OnMouseDown(MouseEventArgs e)
|
||||
{
|
||||
_mouseButton = e.Button;
|
||||
_lastMousePosition = new Vector2(e.X, e.Y);
|
||||
var threshold = NODE_SIZE / _zoom ;
|
||||
|
||||
var inverted = Matrix.Invert(TransformationMatrix);
|
||||
|
||||
var imageCoords = Vector2.Transform(new Vector2(e.X, e.Y), inverted);
|
||||
_selectedNode=GraphicsElements.Where(x=>x.Editable).Select(x => x.GetNode(imageCoords, threshold)).FirstOrDefault(x => x != null);
|
||||
}
|
||||
|
||||
protected override void OnMouseUp(MouseEventArgs e)
|
||||
{
|
||||
_mouseButton = MouseButtons.None;
|
||||
}
|
||||
ToolTip _toolTip = new ToolTip();
|
||||
|
||||
static bool RectangleContainsPoint(int x, int y, int width, int height, int px, int py)
|
||||
{
|
||||
return px >= x && px <= x + width && py >= y && py <= y + height;
|
||||
}
|
||||
|
||||
protected override void OnMouseLeave(EventArgs e)
|
||||
{
|
||||
_toolTip.Hide(this);
|
||||
}
|
||||
|
||||
string GetContourInfo(Mat image, int x, int y)
|
||||
{
|
||||
var contours = image.FindContoursAsArray(RetrievalModes.List, ContourApproximationModes.ApproxSimple);
|
||||
var contour = contours.FirstOrDefault(c => Cv2.PointPolygonTest(c, new Point2f(x, y), false) >= 0);
|
||||
if (contour == null) return "No contour";
|
||||
var area = Cv2.ContourArea(contour);
|
||||
var rect = Cv2.BoundingRect(contour);
|
||||
var width = rect.Width;
|
||||
var height = rect.Height;
|
||||
return $"Area: {area}, Width: {width}, Height: {height}";
|
||||
|
||||
}
|
||||
|
||||
protected override void OnMouseMove(MouseEventArgs e)
|
||||
{
|
||||
// if Ctrl is pressed
|
||||
|
||||
|
||||
|
||||
if ((ModifierKeys & Keys.Control) != 0&&_mouseButton == MouseButtons.None)
|
||||
{
|
||||
if(Image==null||Image.ImageData==null) return;
|
||||
var inverted = Matrix.Invert(TransformationMatrix);
|
||||
var imageCoords = Vector2.Transform(new Vector2(e.X, e.Y), inverted);
|
||||
if(!RectangleContainsPoint(0,0,Image.ImageData.Width,Image.ImageData.Height,(int)imageCoords.X,(int)imageCoords.Y)) return;
|
||||
if (Image.ImageData.Type() == MatType.CV_8UC3)
|
||||
{
|
||||
var pixel = Image.ImageData.Get<Vec3b>((int)imageCoords.Y,(int)imageCoords.X);
|
||||
_toolTip.Show($"R:{pixel.Item0} G:{pixel.Item1} B:{pixel.Item2}", this, e.X + 15, e.Y + 15, 5000);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Image.ImageData.Type() == MatType.CV_8UC1)
|
||||
{
|
||||
var pixel = Image.ImageData.Get<byte>((int)imageCoords.Y,(int)imageCoords.X);
|
||||
var info= GetContourInfo(Image.ImageData, (int)imageCoords.X, (int)imageCoords.Y);
|
||||
_toolTip.Show($"Gray:{pixel}\n"+info, this, e.X+15, e.Y+15,5000);
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Mode == EControlMode.Preview)
|
||||
{
|
||||
if (_mouseButton == MouseButtons.Middle)
|
||||
{
|
||||
TransformationMatrix *=
|
||||
Matrix.CreateTranslation(e.X - _lastMousePosition.X, e.Y - _lastMousePosition.Y, 0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
_mouseShift = new Vector2(e.X, e.Y) - _lastMousePosition;
|
||||
if (_mouseButton == MouseButtons.Left&& _selectedNode != null)
|
||||
{
|
||||
var inverted = Matrix.Invert(TransformationMatrix);
|
||||
var transformed = Vector2.Transform(new Vector2(e.X, e.Y), inverted);
|
||||
|
||||
|
||||
_selectedNode.SetPosition(transformed);
|
||||
|
||||
|
||||
}
|
||||
|
||||
_lastMousePosition = new Vector2(e.X, e.Y);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
private Graphics _currentGraphics;
|
||||
private Workflow.Datatypes.HawkeyeImage? _image;
|
||||
private Vector2 _mouseShift;
|
||||
private INode _selectedNode;
|
||||
|
||||
protected override void OnPaint(PaintEventArgs pe)
|
||||
{
|
||||
if (Image == null)
|
||||
{
|
||||
pe.Graphics.Clear(Color.Black);
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
using (Graphics g = Graphics.FromImage(_backBuffer))
|
||||
{
|
||||
_currentGraphics = g;
|
||||
|
||||
g.Clear(Color.Black);
|
||||
var img = Image.ImageData.ToBitmap();
|
||||
var pos = Vector2.Transform(new Vector2(0, 0), TransformationMatrix);
|
||||
var size = Vector2.Transform(new Vector2(img.Width, img.Height), TransformationMatrix);
|
||||
g.DrawImage(img, pos.X, pos.Y, size.X - pos.X, size.Y - pos.Y);
|
||||
|
||||
|
||||
foreach (IGraphicsElement element in GraphicsElements)
|
||||
{
|
||||
element.Draw(this);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
pe.Graphics.DrawImage(_backBuffer, 0, 0);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected override void OnPaintBackground(PaintEventArgs pevent)
|
||||
{
|
||||
//base.OnPaintBackground(pevent);
|
||||
}
|
||||
|
||||
protected override void OnResize(EventArgs e)
|
||||
{
|
||||
if (Width == 0) return;
|
||||
_backBuffer = new Bitmap(Width, Height);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void DrawNode(Vector2 location)
|
||||
{
|
||||
|
||||
var imageCoordSpace = Vector2.Transform(location, TransformationMatrix);
|
||||
var start = imageCoordSpace - new Vector2(NODE_SIZE/2, NODE_SIZE / 2);
|
||||
var end = (imageCoordSpace + new Vector2(NODE_SIZE / 2, NODE_SIZE / 2))-start;
|
||||
|
||||
|
||||
_currentGraphics.FillRectangle(Brushes.White,start.X,start.Y,end.X,end.Y);
|
||||
_currentGraphics.DrawRectangle(Pens.Black,start.X,start.Y,end.X,end.Y);
|
||||
|
||||
}
|
||||
|
||||
public void DrawArrow(Vector2 location, Vector2 direction)
|
||||
{
|
||||
var imageCoordSpaceLocation = Vector2.Transform(location, TransformationMatrix);
|
||||
var imageCoordSpaceSize = Vector2.Transform(location + direction, TransformationMatrix);
|
||||
var arrowPen = new Pen(Color.Aqua, 2);
|
||||
arrowPen.EndCap = LineCap.Custom;
|
||||
arrowPen.CustomEndCap = new AdjustableArrowCap(5,5,true);
|
||||
|
||||
_currentGraphics.DrawLine(arrowPen, imageCoordSpaceLocation.X, imageCoordSpaceLocation.Y, imageCoordSpaceSize.X, imageCoordSpaceSize.Y);
|
||||
}
|
||||
|
||||
|
||||
public void DrawRectangle(Vector2 start, Vector2 size, bool isGood)
|
||||
{
|
||||
var imageCoordSpaceLocation = Vector2.Transform(start, TransformationMatrix);
|
||||
var imageCoordSpaceSize = Vector2.Transform(start+size, TransformationMatrix)-imageCoordSpaceLocation;
|
||||
|
||||
var pen = new Pen(isGood ? Color.Green : Color.Red, 2);
|
||||
_currentGraphics.DrawRectangle(pen, imageCoordSpaceLocation.X, imageCoordSpaceLocation.Y, imageCoordSpaceSize.X, imageCoordSpaceSize.Y);
|
||||
}
|
||||
|
||||
public void DrawLine(Vector2 start, Vector2 end,LineType type)
|
||||
{
|
||||
var coordStart = Vector2.Transform(start, TransformationMatrix);
|
||||
var coordEnd = Vector2.Transform(end, TransformationMatrix);
|
||||
var pen = new Pen(type ==LineType.Good? Color.Green:(type==LineType.Bad? Color.Red:Color.Aqua),2);
|
||||
_currentGraphics.DrawLine(pen,coordStart.X,coordStart.Y,coordEnd.X,coordEnd.Y);
|
||||
}
|
||||
|
||||
public void DrawPoly(Vector2[] points, bool isGood)
|
||||
{
|
||||
var pen = new Pen(isGood ? Color.Green : Color.Red, 3);
|
||||
var coords = points.Select(x=> Vector2.Transform(x, TransformationMatrix)).Select(x => new PointF(x.X, x.Y)).ToArray();
|
||||
_currentGraphics.DrawPolygon(pen, coords);
|
||||
}
|
||||
|
||||
public void DrawCross(Vector2 location)
|
||||
{
|
||||
|
||||
var startH=Vector2.Transform(location-new Vector2(10,0),TransformationMatrix);
|
||||
var endH = Vector2.Transform(location+new Vector2(10,0), TransformationMatrix);
|
||||
var startV =Vector2.Transform(location-new Vector2(0,20), TransformationMatrix);
|
||||
var endV =Vector2.Transform(location+new Vector2(0,20), TransformationMatrix);
|
||||
var pen = new Pen(Color.Aqua, 1);
|
||||
_currentGraphics.DrawLine(pen, startH.X, startH.Y, endH.X, endH.Y);
|
||||
_currentGraphics.DrawLine(pen, startV.X, startV.Y, endV.X, endV.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user