/// <summary> /// Расчитывает матрицу перехода /// Взято здесь http://jepsonsblog.blogspot.ru/2012/11/rotation-in-3d-using-opencvs.html /// </summary> private void calculateTransformationMatrix(CoordinatesTransformer transformer) { // Матрица поворота 3x3 CvMat R3x3 = new CvMat(3, 3, MatrixType.F64C1); Cv.Rodrigues2(transformer.Rotation, R3x3); // Произведение матрицы поворота и матрицы переноса CvMat RxT = new CvMat(4, 4, MatrixType.F64C1, new double[, ] { { R3x3[0, 0], R3x3[0, 1], R3x3[0, 2], transformer.Translation[0, 0] }, { R3x3[1, 0], R3x3[1, 1], R3x3[1, 2], transformer.Translation[0, 1] }, { R3x3[2, 0], R3x3[2, 1], R3x3[2, 2], transformer.Translation[0, 2] }, { 0, 0, 0, 1 }, }); CvMat A1 = new CvMat(4, 3, MatrixType.F64C1, new double[, ] { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 0 }, { 0, 0, 1 } }); CvMat A2 = new CvMat(3, 4, MatrixType.F64C1, new double[, ] { { transformer.Intrinsic[0, 0], 0, transformer.Intrinsic[0, 2], 0 }, { 0, transformer.Intrinsic[1, 1], transformer.Intrinsic[1, 2], 0 }, { 0, 0, 1, 0 }, }); CvMat InvTransformationMatrix = (A2 * (RxT * A1)); InvTransformationMatrix.Invert(transformer.TransformationMatrix); }
/// <summary> /// Конструктор /// </summary> /// <param name="deviceId">ID камеры которая будет использоваться для получения изображения</param> /// <param name="frameSize">Размер изображения которое будет обрабатываться</param> public ImageProcessingRoutine(int deviceId, CvSize frameSize) { Camera = new WebCam(deviceId, frameSize); Calibrator = new CameraCalibrator(Camera.FrameSize); Finder = new ContoursFinder(Camera.FrameSize); Transformer = new CoordinatesTransformer(); routineThread = new Thread(routine); routineThread.IsBackground = true; routineThread.Start(); }
/// <summary> /// Пытается произвести калибровку камеры /// </summary> /// <returns>Результат калибровки</returns> public bool TryToCalibrate(out CoordinatesTransformer transformer) { CvPoint2D32f[] imageCornersArray; transformer = new CoordinatesTransformer(); // Пытаемся найти углы шахматной доски if (FindCorners(out imageCornersArray)) { // Преобразуем массивы точек в матрицы CvMat imageCorners = new CvMat(imageCornersArray.Length, 1, MatrixType.F32C2, imageCornersArray); CvMat numCorners = new CvMat(1, 1, MatrixType.S32C1, new CvScalar(imageCornersArray.Length)); // Определяем нужно-ли считать коэффициенты дисторсии CalibrationFlag flag = UseUndistort ? CalibrationFlag.RationalModel : CalibrationFlag.ZeroTangentDist | CalibrationFlag.FixK1 | CalibrationFlag.FixK2; // Производим калибровку Cv.CalibrateCamera2 ( generateCorners(), imageCorners, numCorners, chessBoard.Size, transformer.Intrinsic, transformer.Distortion, transformer.Rotation, transformer.Translation, flag ); // Определяем прямоугольник в котором произведена калибровка CalibratedZone[0] = imageCornersArray[0]; CalibratedZone[1] = imageCornersArray[CornersPattern.Width - 1]; CalibratedZone[2] = imageCornersArray.Last(); CalibratedZone[3] = imageCornersArray[CornersPattern.Width * (CornersPattern.Height - 1)]; // Расчитываем матрицу перехода calculateTransformationMatrix(transformer); return(true); } return(false); }
/// <summary> /// Расчитывает матрицу перехода /// Взято здесь http://jepsonsblog.blogspot.ru/2012/11/rotation-in-3d-using-opencvs.html /// </summary> private void calculateTransformationMatrix(CoordinatesTransformer transformer) { // Матрица поворота 3x3 CvMat R3x3 = new CvMat(3, 3, MatrixType.F64C1); Cv.Rodrigues2(transformer.Rotation, R3x3); // Произведение матрицы поворота и матрицы переноса CvMat RxT = new CvMat(4, 4, MatrixType.F64C1, new double[,] { {R3x3[0, 0], R3x3[0, 1], R3x3[0, 2], transformer.Translation[0, 0]}, {R3x3[1, 0], R3x3[1, 1], R3x3[1, 2], transformer.Translation[0, 1]}, {R3x3[2, 0], R3x3[2, 1], R3x3[2, 2], transformer.Translation[0, 2]}, {0, 0, 0, 1 }, }); CvMat A1 = new CvMat(4, 3, MatrixType.F64C1, new double[,] { {1, 0, 0}, {0, 1, 0}, {0, 0, 0}, {0, 0, 1} }); CvMat A2 = new CvMat(3, 4, MatrixType.F64C1, new double[,] { {transformer.Intrinsic[0, 0], 0, transformer.Intrinsic[0, 2], 0}, {0, transformer.Intrinsic[1, 1], transformer.Intrinsic[1, 2], 0}, {0, 0, 1, 0}, }); CvMat InvTransformationMatrix = (A2 * (RxT * A1)); InvTransformationMatrix.Invert(transformer.TransformationMatrix); }
/// <summary> /// Пытается произвести калибровку камеры /// </summary> /// <returns>Результат калибровки</returns> public bool TryToCalibrate(out CoordinatesTransformer transformer) { CvPoint2D32f[] imageCornersArray; transformer = new CoordinatesTransformer(); // Пытаемся найти углы шахматной доски if (FindCorners(out imageCornersArray)) { // Преобразуем массивы точек в матрицы CvMat imageCorners = new CvMat(imageCornersArray.Length, 1, MatrixType.F32C2, imageCornersArray); CvMat numCorners = new CvMat(1, 1, MatrixType.S32C1, new CvScalar(imageCornersArray.Length)); // Определяем нужно-ли считать коэффициенты дисторсии CalibrationFlag flag = UseUndistort ? CalibrationFlag.RationalModel : CalibrationFlag.ZeroTangentDist | CalibrationFlag.FixK1 | CalibrationFlag.FixK2; // Производим калибровку Cv.CalibrateCamera2 ( generateCorners(), imageCorners, numCorners, chessBoard.Size, transformer.Intrinsic, transformer.Distortion, transformer.Rotation, transformer.Translation, flag ); // Определяем прямоугольник в котором произведена калибровка CalibratedZone[0] = imageCornersArray[0]; CalibratedZone[1] = imageCornersArray[CornersPattern.Width - 1]; CalibratedZone[2] = imageCornersArray.Last(); CalibratedZone[3] = imageCornersArray[CornersPattern.Width * (CornersPattern.Height - 1)]; // Расчитываем матрицу перехода calculateTransformationMatrix(transformer); return true; } return false; }