/
klischa
/
AstraScanner2
Обзор
Документация
Войти
/
klischa
/
AstraScanner2
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/calibration/CameraCalibrator.cpp
159 строк
6 KB
klischa
fix: 12 багов — сборка, deadlock, прогресс, сигналы, дефолты
19 июн 2026, 23:54
19 июн 2026, 23:54
cbd5dc3
Код
Авторство
О чём код?
#include "CameraCalibrator.h" #include <QDebug> #include <opencv2/calib3d.hpp> #include <opencv2/imgproc.hpp> #include <filesystem> CameraCalibrator::CameraCalibrator(QObject *parent) : QObject(parent) {} bool CameraCalibrator::addFrame(const cv::Mat &image) { if (image.empty()) return false; cv::Mat gray; if (image.channels() == 1) { gray = image; } else if (image.channels() == 4) { cv::cvtColor(image, gray, cv::COLOR_BGRA2GRAY); } else { cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY); } std::vector<cv::Point2f> corners; // Попытка с более надежным детектором bool found = cv::findChessboardCorners(gray, m_boardSize, corners, cv::CALIB_CB_FAST_CHECK); if (!found) { // Попытка с более медленным, но надежным алгоритмом found = cv::findChessboardCorners(gray, m_boardSize, corners, cv::CALIB_CB_ADAPTIVE_THRESH | cv::CALIB_CB_NORMALIZE_IMAGE); } if (found) { cv::cornerSubPix(gray, corners, cv::Size(11, 11), cv::Size(-1, -1), cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 30, 0.1)); m_imagePoints.push_back(corners); if (m_imageSize.empty()) { m_imageSize = image.size(); } emit frameAdded(static_cast<int>(m_imagePoints.size())); emit statusChanged(QString("Кадр %1 добавлен").arg(m_imagePoints.size())); return true; } else { emit statusChanged("Шахматная доска не найдена"); return false; } } bool CameraCalibrator::addFrameWithCorners(const std::vector<cv::Point2f>& corners, const cv::Size& imageSize) { if (corners.size() != static_cast<size_t>(m_boardSize.width * m_boardSize.height)) { emit statusChanged("Неверное количество углов"); return false; } m_imagePoints.push_back(corners); if (m_imageSize.empty()) { m_imageSize = imageSize; } emit frameAdded(static_cast<int>(m_imagePoints.size())); emit statusChanged(QString("Кадр %1 добавлен").arg(m_imagePoints.size())); return true; } bool CameraCalibrator::calibrate() { if (m_imagePoints.size() < 5) { emit statusChanged("Нужно минимум 5 кадров"); return false; } emit statusChanged("Калибровка, подождите..."); std::vector<std::vector<cv::Point3f>> objectPoints(1); for (int i = 0; i < m_boardSize.height; ++i) { for (int j = 0; j < m_boardSize.width; ++j) { objectPoints[0].push_back(cv::Point3f(j * m_squareSize / 1000.0f, i * m_squareSize / 1000.0f, 0.0f)); } } objectPoints.resize(m_imagePoints.size(), objectPoints[0]); m_cameraMatrix = cv::Mat::eye(3, 3, CV_64F); m_distCoeffs = cv::Mat::zeros(8, 1, CV_64F); std::vector<cv::Mat> rvecs, tvecs; double rms = cv::calibrateCamera(objectPoints, m_imagePoints, m_imageSize, m_cameraMatrix, m_distCoeffs, rvecs, tvecs, cv::CALIB_FIX_K4 | cv::CALIB_FIX_K5); m_lastRms = rms; m_calibrated = true; emit statusChanged(QString("Калибровка завершена. Ошибка RMS: %1").arg(rms, 0, 'f', 3)); return true; } bool CameraCalibrator::saveToFile(const std::string &filename) { namespace fs = std::filesystem; fs::path filePath(filename); auto parentPath = filePath.parent_path(); if (!parentPath.empty()) { // Проверяем, существует ли родительская директория std::error_code ec; if (!fs::exists(parentPath, ec)) { emit statusChanged(QString("Родительская директория не существует: %1").arg(QString::fromStdString(parentPath.string()))); return false; } // Исправление #2: добавляем право записи, не удаляя другие права std::filesystem::permissions(parentPath, std::filesystem::perms::owner_write, std::filesystem::perm_options::add, ec); if (ec) { emit statusChanged(QString("Нет прав на запись в директорию: %1").arg(QString::fromStdString(parentPath.string()))); return false; } } cv::FileStorage fsStorage(filename, cv::FileStorage::WRITE); if (!fsStorage.isOpened()) { emit statusChanged(QString("Ошибка открытия файла %1 для записи").arg(QString::fromStdString(filename))); return false; } fsStorage << "camera_matrix" << m_cameraMatrix; fsStorage << "distortion_coefficients" << m_distCoeffs; fsStorage << "image_size" << m_imageSize; fsStorage << "reprojection_error" << m_lastRms; fsStorage.release(); emit statusChanged(QString("Калибровка сохранена в %1").arg(QString::fromStdString(fs::absolute(filePath).string()))); return true; } bool CameraCalibrator::loadFromFile(const std::string &filename) { cv::FileStorage fsStorage(filename, cv::FileStorage::READ); if (!fsStorage.isOpened()) return false; fsStorage["camera_matrix"] >> m_cameraMatrix; fsStorage["distortion_coefficients"] >> m_distCoeffs; fsStorage["image_size"] >> m_imageSize; if (!fsStorage["reprojection_error"].empty()) { fsStorage["reprojection_error"] >> m_lastRms; } m_calibrated = true; fsStorage.release(); return true; } void CameraCalibrator::reset() { m_imagePoints.clear(); m_calibrated = false; m_cameraMatrix.release(); m_distCoeffs.release(); m_lastRms = 0.0; emit statusChanged("Сброшено"); }