#include"mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QDir>
#include <QMessageBox>
#include <QGraphicsScene>
#include <QGraphicsPixmapItem>
#include <QSettings>
#include <QTextStream>
#include<QDebug>
#include <QWheelEvent>
#include <QMouseEvent>
#include <QScrollBar>
#include <QGraphicsLineItem>
//#include <opencv2/opencv.hpp>
#include <QString>
#include <QDebug>
#include <QDesktopServices>
#include <QUrl>
#include <QFileSystemModel>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
// 初始化参数
toothParams.Init();//矫正参数
laserParams.Init();//激光参数
currentPixmapItem = nullptr;
currentLineItem = nullptr;
currentScale = 1.0;
isDragging = false;
// 设置树形视图
//ui->treeWidget->setHeaderLabel("文件夹结构");
//qDebug() << "Original:" << "文件" << "UTF-8:" ;
// 设置图形视图的属性
//ui->graphicsView->setDragMode(QGraphicsView::ScrollHandDrag);
ui->graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
ui->graphicsView->setResizeAnchor(QGraphicsView::AnchorUnderMouse);//设置视图组件本身大小改变时的锚点
ui->graphicsView->setRenderHint(QPainter::Antialiasing);
ui->graphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
// 连接信号槽
connect(ui->treeWidget,&QTreeWidget::itemClicked,this,&MainWindow::on_treeWidget_itemClicked);
}
MainWindow::~MainWindow()
{
delete ui;
}
// void listCameras() {
// for (int i = 0;; ++i) {
// cv::VideoCapture cap(i);
// if (!cap.isOpened()) {
// break;
// }
// qDebug() << "Found camera:" << i;
// cap.release();
// }
// }
void MainWindow::on_browseButton_clicked()
{
QString folderPath = QFileDialog::getExistingDirectory(this, "选择标定文件夹");
if (!folderPath.isEmpty()) {
currentFolderPath = folderPath;
ui->folderPathEdit->setText(folderPath);
updateTreeView(folderPath);
}
}
void MainWindow::on_calibrateButton_clicked()
{
/* ---------- 1. 基础检查 ---------- */
if (currentFolderPath.isEmpty())
{
QMessageBox::warning(this, QString::fromUtf8("警告"),
QString::fromUtf8("请先选择标定文件夹"));
return;
}
if (ui->cameraNameEdit->text().trimmed().isEmpty())
{
QMessageBox::warning(this, QString::fromUtf8("警告"),
QString::fromUtf8("请输入相机名称"));
return;
}
updateParametersFromUI();
/* ---------- 2. 参数合法性检查 ---------- */
if (laserParams.CameraWidth <= 0 || laserParams.CameraHeight <= 0 ||
laserParams.CameraFocal <= 0)
{
QMessageBox::warning(this, QString::fromUtf8("警告"),
QString::fromUtf8("相机宽度、高度或焦距不能为 0"));
return;
}
calibrationPoints.clear();
int validDirCount = 0;
/* ---------- 3. 主循环 ---------- */
for (int disIndex = 60; disIndex < 400; disIndex += 10)
{
QString currDir = QDir(currentFolderPath).filePath(QString("%1_0").arg(disIndex));
QDir dir(currDir);
if (!dir.exists())
{
qDebug() << "跳过不存在的目录:" << currDir;
continue;
}
QFileInfoList imgs = dir.entryInfoList(QStringList() << "*.bmp" << "*.jpg" << "*.png",
QDir::Files);
if (imgs.isEmpty())
{
qDebug() << "目录无图像:" << currDir;
continue;
}
++validDirCount;
QByteArray dirBA = currDir.toLocal8Bit();
char dirChar[512] = {0};
strncpy_s(dirChar, sizeof(dirChar) - 1,
dirBA.constData(), _TRUNCATE);
qDebug() << "DLL 输入路径:" << dirChar
<< "图像数量:" << imgs.size();
std::vector<ToothCalibPoint> vLineCaliPoint;
bool ok = GetToothPositionModeOne(dirChar, toothParams, vLineCaliPoint);
qDebug() << "GetToothPositionModeOne 返回:" << ok
<< "点数:" << vLineCaliPoint.size();
if (!ok || vLineCaliPoint.empty())
continue;
double left = 0, right = 0;
for (const auto &p : vLineCaliPoint)
{
if (p.PointMode == 1) left = p.CameraW;
if (p.PointMode == 2) right = p.CameraW;
}
if (left > 0 && right > 0)
toothParams.CenterPos = (left + right) / 2.0;
QVector<ToothCalibPoint> qv;
qv.reserve(int(vLineCaliPoint.size()));
for (const auto &p : vLineCaliPoint) qv.append(p);
calibrationPoints.append(qv);
}
/* ---------- 4. 检查有效目录 ---------- */
if (validDirCount == 0 || calibrationPoints.isEmpty())
{
QMessageBox::warning(this, QString::fromUtf8("警告"),
QString::fromUtf8("未找到任何有效标定目录或标定点,请检查数据"));
return;
}
/* ---------- 5. 保存 tooth.txt ---------- */
QString saveTxt = QDir(currentFolderPath).filePath("tooth.txt");
QFile file(saveTxt);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
QMessageBox::warning(this, QString::fromUtf8("错误"),
QString::fromUtf8("无法创建标定文件"));
return;
}
QTextStream out(&file);
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
out.setCodec("UTF-8");
#else
out.setEncoding(QStringConverter::Utf8);
#endif
int total = 0;
for (const auto &vec : calibrationPoints)
for (const auto &p : vec)
{
out << QString::number(p.CameraW, 'f', 3) << ','
<< QString::number(p.CameraH, 'f', 3) << ','
<< QString::number(p.WorldX, 'f', 3) << ','
<< QString::number(p.WorldZ, 'f', 3) << ','
<< p.FileName << ";\n";
++total;
}
file.close();
qDebug() << "已保存" << total << "点到" << saveTxt;
/* ---------- 6. 激光线标定 ---------- */
LaserLineModelResult res;
res.Init();
// 设置输出目录为当前选择的文件夹下的"生成的标注结果"子文件夹
QString outputDir = QDir(currentFolderPath).filePath("生成的标注结果");
QDir().mkpath(outputDir); // 确保输出目录存在
QString cameraName = ui->cameraNameEdit->text().trimmed();
if (cameraName.isEmpty()) {
cameraName = "default_camera";
}
// 设置输出文件路径
QString dllPath = QDir(outputDir).filePath(cameraName + "-deep3.dll");
QString pcImagePath = QDir(outputDir).filePath(cameraName + "-pc.jpg");
QString rcImagePath = QDir(outputDir).filePath(cameraName + "-rc.jpg");
QString xImagePath = QDir(outputDir).filePath(cameraName + "-X.png");
QString zImagePath = QDir(outputDir).filePath(cameraName + "-Z.png");
qDebug()<<dllPath;
QByteArray txtBA = saveTxt.toUtf8();
QByteArray nameBA = cameraName.toUtf8();
QByteArray dllDirBA = outputDir.toUtf8();
strncpy_s(laserParams.CalibPointFileName,
sizeof(laserParams.CalibPointFileName) - 1,
txtBA.constData(), _TRUNCATE);
strncpy_s(laserParams.CameraName,
sizeof(laserParams.CameraName) - 1,
nameBA.constData(), _TRUNCATE);
strncpy_s(res.CalibResultDir,
sizeof(res.CalibResultDir) - 1,
dllDirBA.constData(), _TRUNCATE);
laserParams.MeasurePrecision = ui->precisionSpinBox->value();
// 调用标定函数
bool calibrationSuccess = GetLaserLineCalibUseLcModeThree(laserParams, res);
if (calibrationSuccess) {
/* ---------- 7. 重命名和移动生成的文件 ---------- */
QString defaultDllPath = QDir(outputDir).filePath("deep3.dll");
QString defaultPcPath = QDir(outputDir).filePath("pc.jpg");
QString defaultRcPath = QDir(outputDir).filePath("rc.jpg");
QString defaultXPath = QDir(outputDir).filePath("X.png");
QString defaultZPath = QDir(outputDir).filePath("Z.png");
// 重命名文件
if (QFile::exists(defaultDllPath)) {
QFile::rename(defaultDllPath, dllPath);
}
if (QFile::exists(defaultPcPath)) {
QFile::rename(defaultPcPath, pcImagePath);
}
if (QFile::exists(defaultRcPath)) {
QFile::rename(defaultRcPath, rcImagePath);
}
if (QFile::exists(defaultXPath)) {
QFile::rename(defaultXPath, xImagePath);
}
if (QFile::exists(defaultZPath)) {
QFile::rename(defaultZPath, zImagePath);
}
/* ---------- 8. 验证文件生成 ---------- */
bool allFilesGenerated = true;
QStringList missingFiles;
if (!QFile::exists(dllPath)) {
allFilesGenerated = false;
missingFiles << "DLL文件";
}
if (!QFile::exists(pcImagePath)) {
allFilesGenerated = false;
missingFiles << "pc.jpg";
}
if (!QFile::exists(rcImagePath)) {
allFilesGenerated = false;
missingFiles << "rc.jpg";
}
if (!QFile::exists(xImagePath)) {
allFilesGenerated = false;
missingFiles << "X.png";
}
if (!QFile::exists(zImagePath)) {
allFilesGenerated = false;
missingFiles << "Z.png";
}
if (allFilesGenerated) {
QMessageBox::information(this, QStringLiteral("完成"),
QString::fromUtf8("标定完成!文件已生成在:%1").arg(outputDir));
// 可选:打开生成的文件夹
QDesktopServices::openUrl(QUrl::fromLocalFile(outputDir));
} else {
QMessageBox::warning(this, QStringLiteral("部分完成"),
QString::fromUtf8("标定完成,但缺少以下文件:%1\n请检查DLL输出路径。")
.arg(missingFiles.join(", ")));
}
} else {
QMessageBox::critical(this, QStringLiteral("错误"),
QString::fromUtf8("标定失败!请检查输入参数和数据。"));
}
}
void MainWindow::updateTreeView(const QString &folderPath)
{
ui->treeWidget->clear();
QDir dir(folderPath);
if (!dir.exists()) return;
// 添加文件夹和子文件夹
QTreeWidgetItem *rootItem = new QTreeWidgetItem(ui->treeWidget);
rootItem->setText(0, dir.dirName());
rootItem->setData(0, Qt::UserRole, folderPath);
// 遍历子文件夹
QFileInfoList folders = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
foreach (const QFileInfo &folderInfo, folders)
{
QTreeWidgetItem *folderItem = new QTreeWidgetItem(rootItem);
folderItem->setText(0, folderInfo.fileName());
folderItem->setData(0, Qt::UserRole, folderInfo.absoluteFilePath());
// 添加图片文件
QDir subDir(folderInfo.absoluteFilePath());
QFileInfoList images = subDir.entryInfoList(QStringList() << "*.bmp" << "*.jpg" << "*.png",
QDir::Files);
foreach (const QFileInfo &imageInfo, images) {
QTreeWidgetItem *imageItem = new QTreeWidgetItem(folderItem);
imageItem->setText(0, imageInfo.fileName());
imageItem->setData(0, Qt::UserRole, imageInfo.absoluteFilePath());
}
}
ui->treeWidget->expandAll(); // 将文件夹和图片全部展示出
}
// void MainWindow::on_calibrateButton_clicked()
// {
// if (currentFolderPath.isEmpty())
// {
// QMessageBox::warning(this, QString::fromUtf8("警告"), QString::fromUtf8("请先选择文件夹"));
// return;
// }
// // 更新参数
// updateParametersFromUI();
// // 执行标定过程
// calibrationPoints.clear();
// for (int disIndex = 60; disIndex < 400; disIndex += 10) {
// std::vector<ToothCalibPoint> vLineCaliPoint;
// // 使用一致的路径分隔符
// //QString currSingleFileDir = currentFolderPath + "/" + QString::number(disIndex) + "_0";
// std::string currSingleFileDir = currentFolderPath.toStdString() + "\\" + std::to_string(disIndex) + "_0";
// //qDebug() << "Current Single File Directory:" << currSingleFileDir;
// // 检查目录是否存在
// /*QDir dir(currSingleFileDir);
// if (!dir.exists()) {
// qDebug() << "Directory does not exist:" << currSingleFileDir;
// continue;
// }*/
// // 检查目录中是否有图像文件
// /*QStringList images = dir.entryList(QStringList() << "*.bmp" << "*.jpg" << "*.png", QDir::Files);
// if (images.isEmpty()) {
// qDebug() << "No images found in directory:" << currSingleFileDir;
// continue;
// }*/
// //qDebug() << "Found" << images.size() << "images in directory";
// char currSingleFileDir_char[512]; // 假设 512 足够
// strcpy_s(currSingleFileDir_char, sizeof(currSingleFileDir_char), currSingleFileDir.c_str());
// // 转换为本地编码(确保与外部库兼容)
// //QByteArray ba = currSingleFileDir.toLocal8Bit();
// //char currSingleFileDir_char[512];
// //strncpy_s(currSingleFileDir_char, sizeof(currSingleFileDir_char), ba.constData(), _TRUNCATE);
// qDebug() << "Calling GetToothPositionModeOne with path:" << currSingleFileDir_char;
// // 调用标定函数
// bool success = GetToothPositionModeOne(currSingleFileDir_char, toothParams, vLineCaliPoint);
// qDebug() << "GetToothPositionModeOne result:" << success;
// qDebug() << "vLineCaliPoint size:" << vLineCaliPoint.size();
// if (!vLineCaliPoint.empty()) {
// double leftPos = 0;
// double rightPos = 0;
// for (auto& p : vLineCaliPoint) {
// qDebug() << "Point mode:" << p.PointMode << "CameraW:" << p.CameraW;
// if (p.PointMode == 1) leftPos = p.CameraW;
// if (p.PointMode == 2) rightPos = p.CameraW;
// }
// if (leftPos > 0 && rightPos > 0) {
// toothParams.CenterPos = (leftPos + rightPos) / 2.0;
// qDebug() << "Calculated center position:" << toothParams.CenterPos;
// }
// QVector<ToothCalibPoint> qVector;
// for (const auto& point : vLineCaliPoint) {
// qVector.append(point);
// }
// calibrationPoints.append(qVector);
// } else {
// qDebug() << "No calibration points found for distance:" << disIndex;
// }
// }
// // 保存标定文件
// QString saveTxtName = currentFolderPath + "/tooth.txt";
// QFile file(saveTxtName);
// if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
// QTextStream out(&file);
// // 设置编码为 UTF-8
// #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
// out.setCodec("UTF-8");
// #else
// out.setEncoding(QStringConverter::Utf8);
// #endif
// int pointCount = 0;
// for (const auto& points : calibrationPoints) {
// for (const auto& pt : points) {
// out << QString::number(pt.CameraW, 'f', 3) << ","
// << QString::number(pt.CameraH, 'f', 3) << ","
// << QString::number(pt.WorldX, 'f', 3) << ","
// << QString::number(pt.WorldZ, 'f', 3) << ","
// << pt.FileName << ";\n";
// pointCount++;
// }
// }
// file.close();
// qDebug() << "Saved" << pointCount << "calibration points to" << saveTxtName;
// if (pointCount == 0) {
// QMessageBox::warning(this, QString::fromUtf8("警告"), QString::fromUtf8("未找到任何标定点,请检查输入数据和参数设置"));
// return;
// }
// } else {
// qDebug() << "Failed to open file for writing:" << saveTxtName;
// QMessageBox::warning(this, QString::fromUtf8("错误"), QString::fromUtf8("无法创建标定文件"));
// return;
// }
// // 执行激光线标定
// LaserLineModelResult currResultOut;
// currResultOut.Init();
// QByteArray ba1 = saveTxtName.toUtf8();
// strncpy_s(laserParams.CalibPointFileName, ba1.constData(), sizeof(laserParams.CalibPointFileName));
// QByteArray ba2 = ui->cameraNameEdit->text().toUtf8();
// strncpy_s(laserParams.CameraName, ba2.constData(), sizeof(laserParams.CameraName));
// QString cameraSaveDir = QApplication::applicationDirPath() + "/Calibrate/" +
// ui->cameraNameEdit->text() + "_dll";
// QDir().mkpath(cameraSaveDir);
// QByteArray ba3 = cameraSaveDir.toUtf8();
// strncpy_s(currResultOut.CalibResultDir, ba3.constData(), sizeof(currResultOut.CalibResultDir));
// currResultOut.MeasurePrecision = ui->precisionSpinBox->value();
// GetLaserLineCalibUseLcModeThree(laserParams, currResultOut);
// QMessageBox::information(this, QStringLiteral("完成"), QString::fromLocal8Bit("标定完成!"));
// }
// void MainWindow::on_calibrateButton_clicked()
// {
// /* ---------- 1. 基础检查 ---------- */
// if (currentFolderPath.isEmpty())
// {
// QMessageBox::warning(this, QString::fromUtf8("警告"),
// QString::fromUtf8("请先选择标定文件夹"));
// return;
// }
// if (ui->cameraNameEdit->text().trimmed().isEmpty())
// {
// QMessageBox::warning(this, QString::fromUtf8("警告"),
// QString::fromUtf8("请输入相机名称"));
// return;
// }
// updateParametersFromUI(); // 把 UI 值读到 toothParams / laserParams
// /* ---------- 2. 参数合法性检查 ---------- */
// if (laserParams.CameraWidth <= 0 || laserParams.CameraHeight <= 0 ||
// laserParams.CameraFocal <= 0)
// {
// QMessageBox::warning(this, QString::fromUtf8("警告"),
// QString::fromUtf8("相机宽度、高度或焦距不能为 0"));
// return;
// }
// calibrationPoints.clear(); // 清空旧数据
// int validDirCount = 0; // 统计有效目录数
// /* ---------- 3. 主循环 ---------- */
// for (int disIndex = 60; disIndex < 400; disIndex += 10)
// {
// QString currDir = QDir(currentFolderPath).filePath(QString("%1_0").arg(disIndex));
// // QString currDir = currentFolderPath.toStdString() + "\\" + std::to_string(disIndex);
// QDir dir(currDir);
// /* 3.1 目录是否存在 */
// if (!dir.exists())
// {
// qDebug() << "跳过不存在的目录:" << currDir;
// continue;
// }
// /* 3.2 是否有图像 */
// QFileInfoList imgs = dir.entryInfoList(QStringList() << "*.bmp" << "*.jpg" << "*.png",
// QDir::Files);
// if (imgs.isEmpty())
// {
// qDebug() << "目录无图像:" << currDir;
// continue;
// }
// ++validDirCount;
// /* 3.3 准备 char* 路径 */
// QByteArray dirBA = currDir.toLocal8Bit(); // 本地编码,兼容 DLL
// char dirChar[512] = {0};
// strncpy_s(dirChar, sizeof(dirChar) - 1,
// dirBA.constData(), _TRUNCATE);
// qDebug() << "DLL 输入路径:" << dirChar
// << "图像数量:" << imgs.size();
// /* 3.4 调用 DLL */
// std::vector<ToothCalibPoint> vLineCaliPoint;
// bool ok = GetToothPositionModeOne(dirChar, toothParams, vLineCaliPoint);
// qDebug() << "GetToothPositionModeOne 返回:" << ok
// << "点数:" << vLineCaliPoint.size();
// if (!ok || vLineCaliPoint.empty())
// continue;
// /* 3.5 计算中心 & 转 Qt 容器 */
// double left = 0, right = 0;
// for (const auto &p : vLineCaliPoint)
// {
// if (p.PointMode == 1) left = p.CameraW;
// if (p.PointMode == 2) right = p.CameraW;
// }
// if (left > 0 && right > 0)
// toothParams.CenterPos = (left + right) / 2.0;
// QVector<ToothCalibPoint> qv;
// qv.reserve(int(vLineCaliPoint.size()));
// for (const auto &p : vLineCaliPoint) qv.append(p);
// calibrationPoints.append(qv);
// }
// /* ---------- 4. 一个有效目录都没跑 ---------- */
// if (validDirCount == 0 || calibrationPoints.isEmpty())
// {
// QMessageBox::warning(this, QString::fromUtf8("警告"),
// QString::fromUtf8("未找到任何有效标定目录或标定点,请检查数据"));
// return;
// }
// /* ---------- 5. 保存 tooth.txt ---------- */
// //QString saveTxt = QApplication::applicationDirPath() + "/resources/tooth.txt";
// QString saveTxt = QDir(currentFolderPath).filePath("tooth.txt");
// QFile file(saveTxt);
// if (!file.open(QIODevice::ReadWrite | QIODevice::Text))
// {
// QMessageBox::warning(this, QString::fromUtf8("错误"),
// QString::fromUtf8("无法创建标定文件"));
// return;
// }
// QTextStream out(&file);
// #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
// out.setCodec("UTF-8");
// #else
// out.setEncoding(QStringConverter::Utf8);
// #endif
// int total = 0;
// for (const auto &vec : calibrationPoints)
// for (const auto &p : vec)
// {
// out << QString::number(p.CameraW, 'f', 3) << ','
// << QString::number(p.CameraH, 'f', 3) << ','
// << QString::number(p.WorldX, 'f', 3) << ','
// << QString::number(p.WorldZ, 'f', 3) << ','
// << p.FileName << ";\n";
// ++total;
// }
// file.close();
// qDebug() << "已保存" << total << "点到" << saveTxt;
// /* ---------- 6. 激光线标定 ---------- */
// LaserLineModelResult res;
// res.Init();
// /* 6.1 填充激光参数 & 输出路径 */
// QByteArray txtBA = saveTxt.toUtf8();
// QByteArray nameBA = ui->cameraNameEdit->text().toUtf8();
// QByteArray dirBA = (QApplication::applicationDirPath()
// + "/Calibrate/"
// + ui->cameraNameEdit->text() + "_dll").toUtf8();
// strncpy_s(laserParams.CalibPointFileName,
// sizeof(laserParams.CalibPointFileName) - 1,
// txtBA.constData(), _TRUNCATE);
// strncpy_s(laserParams.CameraName,
// sizeof(laserParams.CameraName) - 1,
// nameBA.constData(), _TRUNCATE);
// strncpy_s(res.CalibResultDir,
// sizeof(res.CalibResultDir) - 1,
// dirBA.constData(), _TRUNCATE);
// laserParams.MeasurePrecision = ui->precisionSpinBox->value();
// QDir().mkpath(QString::fromUtf8(dirBA)); // 确保输出目录存在
// GetLaserLineCalibUseLcModeThree(laserParams, res);
// QMessageBox::information(this, QStringLiteral("完成"),
// QString::fromUtf8("标定完成!"));
// }
//当树形控件中的某个项目被点击时触发,用于加载或显示被选中的内容
void MainWindow::on_treeWidget_itemClicked(QTreeWidgetItem *item, int column)
{
Q_UNUSED(column);
QString filePath = item->data(0, Qt::UserRole).toString();
if (QFileInfo(filePath).isFile())
{
// 查找对应的x坐标
QString fileName = QFileInfo(filePath).fileName();
QString distanceStr = QFileInfo(filePath).dir().dirName();
bool flag;
double distance = distanceStr.split("_").first().toDouble(&flag);
if (flag) {
double xPosition = 0;
// 在标定数据中查找对应的x坐标
for (const auto& points : calibrationPoints) {
for (const auto& pt : points) {
if (qAbs(pt.WorldZ - distance) < 0.1) {
xPosition = pt.CameraW + pt.WorldX;
break;
}
}
}
displayImage(filePath, xPosition);
}
}
}
void MainWindow::displayImage(const QString &imagePath, double xPosition)
{
// 清除现有场景
if (ui->graphicsView->scene()) {
delete ui->graphicsView->scene();
}
QGraphicsScene *scene = new QGraphicsScene(this);
QPixmap pixmap(imagePath);
if (!pixmap.isNull())
{
// 添加图像到场景
currentPixmapItem = scene->addPixmap(pixmap);
scene->setSceneRect(pixmap.rect());
// 添加竖线
if (xPosition > 0)
{
QPen redPen(Qt::red);
redPen.setWidth(2);
currentLineItem = scene->addLine(xPosition, 0, xPosition, pixmap.height(), redPen);
}
else
{
currentLineItem = nullptr;
}
ui->graphicsView->setScene(scene);
// 初始适应视图
ui->graphicsView->fitInView(scene->sceneRect(), Qt::KeepAspectRatio);
currentScale = 1.0;
// 启用缩放和平移
ui->graphicsView->setDragMode(QGraphicsView::ScrollHandDrag);
ui->graphicsView->setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
ui->graphicsView->setResizeAnchor(QGraphicsView::AnchorUnderMouse);
// 显示图像信息
QString info = QString("图像尺寸: %1 x %2\n文件路径: %3")
.arg(pixmap.width())
.arg(pixmap.height())
.arg(imagePath);
QGraphicsTextItem *textItem = scene->addText(info);
textItem->setPos(10, 10);
textItem->setDefaultTextColor(Qt::red);
textItem->setZValue(1); // 确保文本显示在最上层
}
}
// 添加鼠标滚轮事件处理以实现缩放
void MainWindow::wheelEvent(QWheelEvent *event)
{
if (ui->graphicsView->underMouse()) {
double scaleFactor = 1.15;
if (event->angleDelta().y() > 0) {
// 放大
ui->graphicsView->scale(scaleFactor, scaleFactor);
currentScale *= scaleFactor;
} else {
// 缩小
ui->graphicsView->scale(1.0 / scaleFactor, 1.0 / scaleFactor);
currentScale /= scaleFactor;
}
event->accept();
} else {
QMainWindow::wheelEvent(event);
}
}
// 添加鼠标按下事件处理以实现自定义拖拽
void MainWindow::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton && ui->graphicsView->underMouse()) {
lastMousePos = event->pos();
setCursor(Qt::ClosedHandCursor);
event->accept();
} else {
QMainWindow::mousePressEvent(event);
}
}
// 添加鼠标移动事件处理以实现自定义拖拽
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton && ui->graphicsView->underMouse()) {
QPoint delta = event->pos() - lastMousePos;
lastMousePos = event->pos();
// 移动视图
QScrollBar *hBar = ui->graphicsView->horizontalScrollBar();
QScrollBar *vBar = ui->graphicsView->verticalScrollBar();
hBar->setValue(hBar->value() - delta.x());
vBar->setValue(vBar->value() - delta.y());
event->accept();
} else {
QMainWindow::mouseMoveEvent(event);
}
}
// 添加鼠标释放事件处理
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
setCursor(Qt::ArrowCursor);
event->accept();
} else {
QMainWindow::mouseReleaseEvent(event);
}
}
// 添加重置视图的槽函数
void MainWindow::onResetView()
{
if (ui->graphicsView->scene()) {
ui->graphicsView->fitInView(ui->graphicsView->scene()->sceneRect(), Qt::KeepAspectRatio);
currentScale = 1.0;
}
}
// 添加绘制红线的函数
void MainWindow::drawRedLine(double xPosition)
{
if (ui->graphicsView->scene() && currentPixmapItem) {
// 移除现有的红线
if (currentLineItem) {
ui->graphicsView->scene()->removeItem(currentLineItem);
delete currentLineItem;
}
// 创建新红线
QPen redPen(Qt::red);
redPen.setWidth(2);
QPixmap pixmap = currentPixmapItem->pixmap();
currentLineItem = ui->graphicsView->scene()->addLine(
xPosition, 0, xPosition, pixmap.height(), redPen);
}
}
void MainWindow::updateParametersFromUI()
{
toothParams.CenterDis = ui->centerDisSpinBox->value();
toothParams.SideDis = ui->sideDisSpinBox->value();
toothParams.ToothNum = ui->toothNumSpinBox->value();
toothParams.DeepThresh = ui->deepThreshSpinBox->value();
toothParams.DeepStep = ui->deepStepSpinBox->value();
toothParams.CenterPos = ui->centerPosSpinBox->value();
laserParams.CameraWidth = ui->cameraWidthSpinBox->value();
laserParams.CameraHeight = ui->cameraHeightSpinBox->value();
laserParams.CameraOffsetYCalib = ui->offsetYCalibSpinBox->value();
laserParams.CameraOffsetYMap = ui->offsetYMapSpinBox->value();
laserParams.CameraMapHeight = ui->mapHeightSpinBox->value();
laserParams.RealXOffset = ui->realXOffsetSpinBox->value();
laserParams.RealZOffset = ui->realZOffsetSpinBox->value();
laserParams.CameraPiexSize = ui->pixelSizeSpinBox->value();
laserParams.CameraFocal = ui->focalSpinBox->value();
}
void MainWindow::updateUIfromParameters()
{
ui->centerDisSpinBox->setValue(toothParams.CenterDis);
ui->sideDisSpinBox->setValue(toothParams.SideDis);
ui->toothNumSpinBox->setValue(toothParams.ToothNum);
ui->deepThreshSpinBox->setValue(toothParams.DeepThresh);
ui->deepStepSpinBox->setValue(toothParams.DeepStep);
ui->centerPosSpinBox->setValue(toothParams.CenterPos);
ui->cameraWidthSpinBox->setValue(laserParams.CameraWidth);
ui->cameraHeightSpinBox->setValue(laserParams.CameraHeight);
ui->offsetYCalibSpinBox->setValue(laserParams.CameraOffsetYCalib);
ui->offsetYMapSpinBox->setValue(laserParams.CameraOffsetYMap);
ui->mapHeightSpinBox->setValue(laserParams.CameraMapHeight);
ui->realXOffsetSpinBox->setValue(laserParams.RealXOffset);
ui->realZOffsetSpinBox->setValue(laserParams.RealZOffset);
ui->pixelSizeSpinBox->setValue(laserParams.CameraPiexSize);
ui->focalSpinBox->setValue(laserParams.CameraFocal);
}
void MainWindow::on_saveParamsButton_clicked()
{
QString fileName = QFileDialog::getSaveFileName(this, "保存参数", "", "配置文件 (*.ini)");
if (!fileName.isEmpty()) {
QSettings settings(fileName, QSettings::IniFormat);
settings.beginGroup("ToothParameters");
settings.setValue("CenterDis", toothParams.CenterDis);
settings.setValue("SideDis", toothParams.SideDis);
settings.setValue("ToothNum", toothParams.ToothNum);
settings.setValue("DeepThresh", toothParams.DeepThresh);
settings.setValue("DeepStep", toothParams.DeepStep);
settings.setValue("CenterPos", toothParams.CenterPos);
settings.endGroup();
settings.beginGroup("LaserParameters");
settings.setValue("CameraWidth", laserParams.CameraWidth);
settings.setValue("CameraHeight", laserParams.CameraHeight);
settings.setValue("CameraOffsetYCalib", laserParams.CameraOffsetYCalib);
settings.setValue("CameraOffsetYMap", laserParams.CameraOffsetYMap);
settings.setValue("CameraMapHeight", laserParams.CameraMapHeight);
settings.setValue("RealXOffset", laserParams.RealXOffset);
settings.setValue("RealZOffset", laserParams.RealZOffset);
settings.setValue("CameraPiexSize", laserParams.CameraPiexSize);
settings.setValue("CameraFocal", laserParams.CameraFocal);
settings.setValue("CameraName", QString(laserParams.CameraName));
settings.endGroup();
}
}
void MainWindow::on_loadParamsButton_clicked()
{
QString fileName = QFileDialog::getOpenFileName(this, "加载参数", "", "配置文件 (*.txt)");
if (!fileName.isEmpty()) {
QSettings settings(fileName, QSettings::IniFormat);
settings.beginGroup("ToothParameters");
toothParams.CenterDis = settings.value("CenterDis", 0).toDouble();
toothParams.SideDis = settings.value("SideDis", 0).toDouble();
toothParams.ToothNum = settings.value("ToothNum", 50).toInt();
toothParams.DeepThresh = settings.value("DeepThresh", 30).toInt();
toothParams.DeepStep = settings.value("DeepStep", 16).toInt();
toothParams.CenterPos = settings.value("CenterPos", 0).toInt();
settings.endGroup();
settings.beginGroup("LaserParameters");
laserParams.CameraWidth = settings.value("CameraWidth", 0).toInt();
laserParams.CameraHeight = settings.value("CameraHeight", 0).toInt();
laserParams.CameraOffsetYCalib = settings.value("CameraOffsetYCalib", 0).toInt();
laserParams.CameraOffsetYMap = settings.value("CameraOffsetYMap", 0).toInt();
laserParams.CameraMapHeight = settings.value("CameraMapHeight", 0).toInt();
laserParams.RealXOffset = settings.value("RealXOffset", 0).toDouble();
laserParams.RealZOffset = settings.value("RealZOffset", 0).toDouble();
laserParams.CameraPiexSize = settings.value("CameraPiexSize", 0).toDouble();
laserParams.CameraFocal = settings.value("CameraFocal", 0).toDouble();
QString cameraName = settings.value("CameraName", "").toString();
strncpy_s(laserParams.CameraName, cameraName.toUtf8().data(), sizeof(laserParams.CameraName));
settings.endGroup();
updateUIfromParameters();
}
}
结合我的代码来实现
最新发布