/// <summary> /// Обработка изображения выполняющаяся в отдельном потоке /// </summary> private void routine() { IplImage cam = new IplImage(Camera.FrameSize, BitDepth.U8, 3); CvPoint[] mostLengthHole = new CvPoint[0]; RoutineAction innerAction; bool innerIsRunOnce; while (isRunning) { // Копируем новое значение состояния innerAction = action; innerIsRunOnce = isRunOnce; // Определяем что будем делать в следующем цикле if (innerIsRunOnce) { action = RoutineAction.Pause; } // Если поток на паузе, то ничего не делаем if (innerAction == RoutineAction.Pause) { continue; } if (isRunning && BeforeProcessingEvent != null) { BeforeProcessingEvent(); } // Захватываем изображение с камеры Camera.GetIplImage(ref cam); if (innerAction == RoutineAction.FindContour || innerAction == RoutineAction.Measure) { mostLengthHole = Finder.FindMostLengthHole(cam); } if (innerAction == RoutineAction.DrawCorners || innerAction == RoutineAction.Calibrate) { Calibrator.SetImage(cam); } switch (innerAction) { case RoutineAction.GetImage: { if (isRunning && GetImageEvent != null) { GetImageEvent(cam.ToBitmap()); } break; } case RoutineAction.DrawCorners: { Calibrator.FindCorners(); if (isRunning && DrawCornersEvent != null) { DrawCornersEvent(cam.ToBitmap()); } break; } case RoutineAction.Calibrate: { bool result = Calibrator.TryToCalibrate(out Transformer); if (isRunning && CalibrateEvent != null) { CalibrateEvent(result); } break; } case RoutineAction.FindContour: { if (mostLengthHole.Length > 0) { cam.DrawPolyLine(new CvPoint[][] { mostLengthHole }, true, Cv.RGB(0, 255, 0), 2); } if (isRunning && FindContoursEvent != null) { FindContoursEvent(cam.ToBitmap()); } break; } case RoutineAction.Measure: { if (mostLengthHole.Length > 0) { CvPoint2D32f[] realPoints = Transformer.GetRealPoints(mostLengthHole); CvCircleSegment realCircle = CircleApproximator.Approximate(realPoints); CvCircleSegment imageCircle = CircleApproximator.Approximate(mostLengthHole); // Вносим поправки float ratio = imageCircle.Radius / realCircle.Radius; realCircle.Radius = realCircle.Radius * CorrectionMultiplier + CorrectionOffset; imageCircle.Radius = imageCircle.Radius * CorrectionMultiplier + CorrectionOffset * ratio; int circleRadius = (int)Math.Round(imageCircle.Radius); CvPoint circleCenter = new CvPoint ( (int)Math.Round(imageCircle.Center.X), (int)Math.Round(imageCircle.Center.Y) ); // Обводим внутреннюю границу кольца if (circleRadius > 0) { cam.DrawCircle(circleCenter, circleRadius, Cv.RGB(0, 0, 255), 2); } // Отмечаем откалиброванную зону cam.DrawPolyLine(new CvPoint[][] { Calibrator.CalibratedZone }, true, Cv.RGB(255, 255, 0), 2); if (isRunning && MeasureEvent != null) { MeasureEvent(cam.ToBitmap(), realCircle.Radius); } } break; } } } Camera.Close(); }