private Bitmap DrawRectanglesFunct(Bitmap image, VideoProcessing vp) { var rects = VideoDetection.FindRectangles(vp, image); if (rects.Count == 0) { return(image); } var rect2 = VideoDetection.GetSmallestCenteredRectangle(rects); try { using (Image <Bgr, Byte> img = new Image <Bgr, byte>(image)) { foreach (var rect in rects) { img.DrawPolyline(PointFToPoint(ToRotatedRectangle(rect)), true, new Bgr(Color.Red), 2); } if (rect2 != null) { img.DrawPolyline(PointFToPoint(ToRotatedRectangle(rect2)), true, new Bgr(Color.Green), 5); img.Draw(new Cross2DF(rect2.ToPartLocation().ToPointF(), 20, 20), new Bgr(Color.Blue), 2); } image = img.ToBitmap(); } } catch { } return(image); }
// ========================================================= private void DrawFiducialFunct(ref Bitmap image, VideoProcessing vp) { MarkA.Clear(); var fids = VideoDetection.FindTemplates(vp, image); foreach (var f in fids) { f.ToScreenResolution(); } MarkA.AddRange(fids.Select(x => x.ToPartLocation().ToPointF()).ToArray()); }
public bool Calibrate(double Tolerance) { //setup camera MainForm.cameraView.UpCameraReset(); MainForm.cameraView.SetUpCameraFunctionSet("Needle"); MainForm.cameraView.downSettings.FindCircles = true; // we are already @ upcamera position MainForm.Cnc.Zup(); Global.GoTo("Up Camera"); MainForm.Cnc.Zdown(Settings.Default.focus_height, true); //1 mm above PCB CalibrationPoints.Clear(); // Presumably user changed the needle, and calibration is void no matter if we succeed here Calibrated = false; for (int i = 0; i <= 3600; i = i + 225) { NeedlePoint Point = new NeedlePoint(); Point.A = i / 10.0; if (!MainForm.Cnc.CNC_A(Point.A)) { return(false); } //detect average of 3 measurements var circle = VideoDetection.GetClosestAverageCircle(MainForm.cameraView.upVideoProcessing, Tolerance, 3); if (circle == null) { MainForm.ShowSimpleMessageBox("Needle Calibration: Can't see needle at angle " + Point.A + " - aborting"); return(false); } circle.ToMMResolution(); Point.X = circle.X; Point.Y = circle.Y; // display point var pt = circle.Clone().ToScreenResolution().ToPartLocation().ToPointF(); MainForm.DisplayText("circle @ " + circle + "\tx @ " + pt.X + "," + pt.Y); MainForm.cameraView.upVideoProcessing.MarkA.Add(pt); CalibrationPoints.Add(Point); } Calibrated = true; MainForm.Cnc.Zup(); MainForm.cameraView.SetUpCameraDefaults(); return(true); }
// ========================================================= private void DrawCirclesFunct(Bitmap bitmap, VideoProcessing vp) { List <Shapes.Circle> Circles = VideoDetection.FindCircles(vp, bitmap); using (Graphics g = Graphics.FromImage(bitmap)) using (Pen pen = new Pen(Color.DarkOrange, 2)) for (int i = 0, n = Circles.Count; i < n; i++) { Circles[i].ToRawResolution(); g.DrawEllipse(pen, (float)(Circles[i].X - Circles[i].Radius), (float)(Circles[i].Y - Circles[i].Radius), (float)(Circles[i].Radius * 2), (float)(Circles[i].Radius * 2)); } }
public static void DoNeedleErrorMeasurement(VideoProcessing vp) { var cnc = Global.Instance.cnc; var originalLocation = cnc.XYALocation; PartLocation testLocation = Global.GoTo("Up Camera"); cnc.Zdown(Properties.Settings.Default.focus_height, true); // setup camera vp.SetFunctionsList("Needle"); vp.s.FindCircles = true; vp.s.Draw1mmGrid = true; var Needle = Global.Instance.needle; List <PartLocation> offsetError = new List <PartLocation>(); for (int i = 0; i <= 360; i += 45) { testLocation.A = i; var pp = testLocation - Needle.NeedleOffset; Needle.Move_m(pp); // move to target // mark erro var circle = VideoDetection.GetClosestCircle(vp, 10); if (circle != null) { vp.MarkA.Add(circle.ToScreenResolution().ToPartLocation().ToPointF()); circle.ToMMResolution(); offsetError.Add(circle.ToPartLocation()); } Thread.Sleep(500); //wait 1 second } Global.Instance.mainForm.ShowSimpleMessageBox("Upcamera offset Error is " + PartLocation.Average(offsetError) + "\nMax Error is " + PartLocation.MaxValues(offsetError)); cnc.Zup(); cnc.CNC_XYA(originalLocation); //revert to previous state vp.Reset(); }
public bool PopulateAvailableParts(TapeObj x) { if (x.FirstHole == null) { return(false); // currently only handling hole-calibrated harts } if (x.TemplateFilename == null || !File.Exists(x.TemplateFilename)) { return(false); } MainForm.Cnc.SlackCompensation = false; SetCurrentTapeMeasurement(x.TapeType); //find out the max number of parts int i = 0; while (true) { if (!MainForm.Cnc.CNC_XY(x.GetHoleLocation(i))) { MainForm.Cnc.SlackCompensation = true; return(false); } var thing = VideoDetection.FindClosest(MainForm.cameraView.downVideoProcessing, Shapes.ShapeTypes.Circle, 1, 3); if (thing == null) { break; } if (Cnc.AbortPlacement) { MainForm.Cnc.SlackCompensation = true; return(false); } i++; } MainForm.cameraView.SetDownCameraFunctionSet("ComponentPhoto"); double len = i * x.HolePitch; double max_components = len / x.PartPitch + 2; var list = x.AvailableParts; list.Clear(); if (!MainForm.Cnc.CNC_XY(x.GetPartLocation(0))) { MainForm.Cnc.SlackCompensation = true; return(false); } //start off with first part for (i = 0; i < max_components; i++) { if (Cnc.AbortPlacement) { MainForm.Cnc.SlackCompensation = true; return(false); } var location = MainForm.FindPositionAndMoveToClosest(Shapes.ShapeTypes.Fiducial, 1, .1, x.TemplateFilename, .5); if (location != null) { list.Add(new NamedLocation(location, i.ToString())); if (!MainForm.Cnc.CNC_XY(location + new PartLocation(x.PartPitch, 0).Rotate(x.TapeAngle * Math.PI / 180))) { MainForm.Cnc.SlackCompensation = true; return(false); } } else { if (!MainForm.Cnc.CNC_XY(Cnc.XYLocation + new PartLocation(x.PartPitch, 0).Rotate(x.TapeAngle * Math.PI / 180))) { MainForm.Cnc.SlackCompensation = true; return(false); } } } Global.Instance.mainForm.DisplayText("Detected " + list.Count + " parts for " + x.ID + " (" + String.Join(" ", list) + ")"); MainForm.Cnc.SlackCompensation = true; return(true); }
private static PartLocation DoCameraCalibration(VideoProcessing vp, PartLocation movement) { var cnc = Global.Instance.cnc; var distance = new List <PartLocation>(); var pixels = new List <PartLocation>(); // turn on slack compensation var savedSlackCompensation = cnc.SlackCompensation; cnc.SlackCompensation = true; var startingPos = cnc.XYLocation; startingPos.A = 0; vp.MarkA.Clear(); for (int i = -4; i < 5; i++) { //move var newLocation = startingPos + (i * movement); if (!cnc.CNC_XYA(newLocation)) { return(null); } //try 5 times to find a circle List <Shapes.Circle> circles = new List <Shapes.Circle>(); for (int tries = 5; tries > 0 && circles.Count == 0; tries--) { circles = VideoDetection.FindCircles(vp); } if (circles.Count == 0) { continue; //not found, move and try again } //find largest circle of the bunch var circle = circles.Aggregate((c, d) => c.Radius > d.Radius ? c : d); //find largest circle if we have multiple // var circlePL = (1 / zoom) * circle.ToPartLocation(); //compensate for zoom circle.ToScreenUnzoomedResolution(); distance.Add(newLocation); pixels.Add(circle.ToPartLocation()); vp.MarkA.Add(circle.Clone().ToScreenResolution().ToPartLocation().ToPointF()); //DisplayText(String.Format("Actual Loc = {0}\t Measured Loc = {1}", newLocation, UpCamera.PixelsToActualLocation(circlePL)), Color.Blue); } double XmmPerPixel = 0, YmmPerPixel = 0; if (pixels.Count < 2) { Global.Instance.mainForm.ShowMessageBox("Unable To Detect Circles", "Try to adjust upcamera processing to see circles, and ensure upcamera needle position is correctly configured", MessageBoxButtons.OK); } else { // Do regression on X and Y var Xs = pixels.Select(xx => xx.X).ToArray(); var Ys = distance.Select(xx => xx.X).ToArray(); var result = SimpleRegression.Fit(Xs, Ys); XmmPerPixel = result.Item2; Xs = pixels.Select(xx => xx.Y).ToArray(); Ys = distance.Select(xx => xx.Y).ToArray(); result = SimpleRegression.Fit(Xs, Ys); YmmPerPixel = result.Item2; Global.Instance.DisplayText(String.Format("{0} Xmm/pixel {1} Ymm/pixel", XmmPerPixel, YmmPerPixel), Color.Purple); // Now move to the center /* need to get gotolocation upcamera working still * double X, Y; //error offset * GotoUpCamPosition_button_Click(null, null); * for (int tries = 5; tries > 0; tries--) { * if (GoToLocation_m(UpCamera, Shapes.ShapeTypes.Circle, 1.8, 0.5, out X, out Y)) { * Properties.Settings.Default.UpCam_PositionX = Cnc.CurrentX + X; * Properties.Settings.Default.UpCam_PositionY = Cnc.CurrentY - Y; * UpcamPositionX_textBox.Text = Properties.Settings.Default.UpCam_PositionX.ToString("0.00", CultureInfo.InvariantCulture); * UpcamPositionY_textBox.Text = Properties.Settings.Default.UpCam_PositionY.ToString("0.00", CultureInfo.InvariantCulture); * * } * } */ } //restore settings cnc.SlackCompensation = savedSlackCompensation; vp.MarkA.Clear(); //return value return((pixels.Count < 2) ? null : new PartLocation(Math.Abs(XmmPerPixel), Math.Abs(YmmPerPixel))); }
private Bitmap DrawComponentsFunct(Bitmap bitmap, VideoProcessing vp) { List <Shapes.Component> Components = VideoDetection.FindComponents(vp, bitmap); Graphics g = Graphics.FromImage(bitmap); Pen OrangePen = new Pen(Color.DarkOrange, 1); Pen RedPen = new Pen(Color.DarkRed, 2); Pen BluePen = new Pen(Color.Blue, 2); Shapes.Component Component; Point p1 = new Point(); Point p2 = new Point(); for (int i = 0, n = Components.Count; i < n; i++) { Component = Components[i]; // move Component.Longest start to ComponentCenter, draw it float dx = Component.Center.X - Component.Longest.Start.X; float dy = Component.Center.Y - Component.Longest.Start.Y; p1.X = (int)Math.Round(Component.Longest.Start.X + dx); p1.Y = (int)Math.Round(Component.Longest.Start.Y + dy); p2.X = (int)Math.Round(Component.Longest.End.X + dx); p2.Y = (int)Math.Round(Component.Longest.End.Y + dy); g.DrawLine(RedPen, p1, p2); // move Component.Longest end to ComponentCenter, draw Component.Longest dx = Component.Center.X - Component.Longest.End.X; dy = Component.Center.Y - Component.Longest.End.Y; p1.X = (int)Math.Round(Component.Longest.Start.X + dx); p1.Y = (int)Math.Round(Component.Longest.Start.Y + dy); p2.X = (int)Math.Round(Component.Longest.End.X + dx); p2.Y = (int)Math.Round(Component.Longest.End.Y + dy); g.DrawLine(RedPen, p1, p2); // move Normal start to ComponentCenter, draw it dx = Component.Center.X - Component.NormalStart.X; dy = Component.Center.Y - Component.NormalStart.Y; p1.X = (int)Math.Round(Component.NormalStart.X + dx); p1.Y = (int)Math.Round(Component.NormalStart.Y + dy); p2.X = (int)Math.Round(Component.NormalEnd.X + dx); p2.Y = (int)Math.Round(Component.NormalEnd.Y + dy); g.DrawLine(RedPen, p1, p2); // move Component.Normal end to ComponentCenter, draw it dx = Component.Center.X - Component.NormalEnd.X; dy = Component.Center.Y - Component.NormalEnd.Y; p1.X = (int)Math.Round(Component.NormalStart.X + dx); p1.Y = (int)Math.Round(Component.NormalStart.Y + dy); p2.X = (int)Math.Round(Component.NormalEnd.X + dx); p2.Y = (int)Math.Round(Component.NormalEnd.Y + dy); g.DrawLine(RedPen, p1, p2); // draw outline g.DrawPolygon(OrangePen, ToPointsArray(Component.Outline)); // draw Component.Longest p1.X = (int)Math.Round(Component.Longest.Start.X); p1.Y = (int)Math.Round(Component.Longest.Start.Y); p2.X = (int)Math.Round(Component.Longest.End.X); p2.Y = (int)Math.Round(Component.Longest.End.Y); g.DrawLine(BluePen, p1, p2); } return(bitmap); }