#include "pch.h" #include "mainwidget.h" #include "ui_mainwidget.h" #include #include #include #include #include #include "coutlinedetector.h" #include "ImageUtils.h" #include "ContourUtils.h" #include #include MainWidget::MainWidget(QWidget *parent) : QWidget(parent) , ui(new Ui::MainWidget) , m_pSurface(nullptr) , m_detector(nullptr) { ui->setupUi(this); InitWidget(); m_detector = new COutlineDetector; // 连接鼠标移动信号到槽函数 connect(ui->viewWidget, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(showMousePosition(QMouseEvent*))); } //初始化界面 void MainWidget::InitWidget(void) { setWindowTitle(tr("沉积相轮廓识别 Beta")); //ui->viewWidget->setStyleSheet("QWidget { border: 1px solid black; }"); ui->edit_zMin->setText("2000"); ui->edit_zMax->setText("10000"); ui->btnBlackWhite->setEnabled(false); ui->btnExecute->setEnabled(false); ui->btnOutputContours->setEnabled(false); ui->sliderZMin->setRange(0,2000); ui->sliderZMax->setRange(0,2000); ui->sliderZMax->setValue(2000); // ui->sliderDilateDist->setRange(0,100); // ui->sliderDilateDist->setValue(0); ui->labelDisp->setAlignment(Qt::AlignRight | Qt::AlignVCenter); InitButtons(); } void MainWidget::InitButtons(void) { ui->btnOrigin->setCheckable(true); ui->btnBlackWhite->setCheckable(true); ui->btnExecute->setCheckable(true); ui->btnOrigin->setChecked(true); QButtonGroup* btnGroup = new QButtonGroup(this); btnGroup->addButton(ui->btnOrigin,0); btnGroup->addButton(ui->btnBlackWhite,1); btnGroup->addButton(ui->btnExecute,2); btnGroup->setExclusive(true); } MainWidget::~MainWidget() { if(m_pSurface) delete m_pSurface; if(m_detector) delete m_detector; delete ui; } void MainWidget::showMousePosition(QMouseEvent *event) { // 获取鼠标在绘图区域的像素位置 QPoint pos = event->pos(); // 将像素位置转换为坐标值 double x = ui->viewWidget->xAxis->pixelToCoord(pos.x()); double y = ui->viewWidget->yAxis->pixelToCoord(pos.y()); double z = 1e31; if(nullptr != m_pSurface) { z = m_pSurface->Z(x,y); if(z > 1e20) z = 1e31; } QString xstr = QString::number(x,'g',8); QString ystr = QString::number(y,'g',8); QString zstr = QString::number(z,'g',8); // qDebug() << x << " " << y; // 在状态栏中显示坐标信息 if(z> 1e20) ui->labelDisp->setText(QString("x:%1, y:%2").arg(xstr).arg(ystr)); else ui->labelDisp->setText(QString("x:%1, y:%2\nz:%3").arg(xstr).arg(ystr).arg(zstr)); } void MainWidget::on_btnCancel_clicked() { qApp->quit(); } void MainWidget::on_btnDfg_clicked() { QString strFile = QFileDialog::getOpenFileName(this, tr("打开文件"),"",tr("Dfg files(*.dfg)")); if(strFile.isEmpty()) return; ui->editDfg->setText(strFile); if(!loadDfg(strFile)) { QMessageBox::warning(this,tr("警告"),tr("所选文件无法打开")); return; } ui->btnBlackWhite->setEnabled(true); ui->btnExecute->setEnabled(true); ui->btnOutputContours->setEnabled(false); } bool MainWidget::loadDfg(QString strDfg) { disconnect(ui->spinDilate,0,0,0); terminateConnection(ui->edit_zMax,ui->sliderZMax); terminateConnection(ui->edit_zMin,ui->sliderZMin); ui->viewWidget->resetAxisRect(); if(m_pSurface) delete m_pSurface; m_pSurface = new GSurface; QTextCodec *gbk = QTextCodec::codecForName("GBK"); QByteArray arr=gbk->fromUnicode(strDfg); qApp->setOverrideCursor(Qt::BusyCursor); if( !m_pSurface->ReadDfg(arr.data()) ) { delete m_pSurface; m_pSurface = nullptr; qApp->restoreOverrideCursor(); return false; } m_detector->clear(); m_detector->setSurface(m_pSurface); ui->viewWidget->resetColorScaleRange(); updateGridParas(); ui->viewWidget->m_bTransparentColormap = true; ui->viewWidget->setType(ViewWidget::colorfulmap); if(m_pSurface) ui->viewWidget->setGrid(m_pSurface,true); ui->viewWidget->m_bTransparentColormap = false; QTimer::singleShot(5,[this]{ if(m_pSurface) ui->viewWidget->setGrid(m_pSurface,true); }); qApp->restoreOverrideCursor(); return true; } bool MainWidget::writeContours(QString strFile) { QTextCodec *gbk = QTextCodec::codecForName("GBK"); QByteArray arr=gbk->fromUnicode(strFile); m_detector->setContourMinArea(ui->edit_minArea->text().toFloat()); m_detector->setContourSmoothTimes(ui->edit_smoothTimes->text().toUInt()); //生成沉积相轮廓 m_detector->CreateFaciesContours(); Contours dstvec; //m_detector->multiContourToRealCoords(m_detector->GetFaciesContours(), //dstvec, 0); return ContourUtils::WriteContours(dstvec,arr.data()); } //构建edit 和 slider的信号槽 void MainWidget::buildConnection(QLineEdit* edit, QSlider* slider) { connect(edit,&QLineEdit::editingFinished,[=]{ slider->setValue(qRound(edit->text().toFloat())); if(ui->btnExecute->isChecked()) on_btnExecute_clicked(); else if(ui->btnBlackWhite->isChecked()) on_btnBlackWhite_clicked(); } ); connect(slider,&QSlider::valueChanged,[=]{ float valedit = edit->text().toFloat(); float valslider = slider->value(); if(fabs(valedit-valslider) > 1) edit->setText(QString::number(valslider)); }); connect(slider,&QSlider::sliderReleased,[=]{ if(ui->btnExecute->isChecked()) on_btnExecute_clicked(); // else if(ui->btnBlackWhite->isChecked()) // on_btnBlackWhite_clicked(); }); connect(slider,&QSlider::sliderMoved, [=]{ if(ui->btnBlackWhite->isChecked()) on_btnBlackWhite_clicked(); }); } //解除信号槽 void MainWidget::terminateConnection(QLineEdit* edit, QSlider* slider) { disconnect(edit,0,0,0); disconnect(slider,0,0,0); } void MainWidget::updateGridParas(void) { disconnect(ui->spinDilate,0,0,0); disconnect(ui->edit_minArea,0,0,0); disconnect(ui->edit_smoothTimes,0,0,0); terminateConnection(ui->edit_zMax,ui->sliderZMax); terminateConnection(ui->edit_zMin,ui->sliderZMin); if(!m_pSurface) return; int xnum = m_pSurface->XNum(); int ynum = m_pSurface->YNum(); float deltx = m_pSurface->DeltX(); float delty = m_pSurface->DeltY(); double* range = m_pSurface->GetRange(); float zmin = range[0]; float zmax = range[1]; ui->sliderZMax->setRange(zmin,zmax); ui->sliderZMin->setRange(zmin,zmax); ui->sliderZMin->setValue(int(zmin+zmax)/2); ui->sliderZMax->setValue(zmax); ui->edit_zMin->setText(QString::number(int(zmin+zmax)/2)); ui->edit_zMax->setText(QString::number(int(zmax))); int dt = ceil(max(deltx, delty)); ui->spinDilate->setRange(0,min(xnum,ynum)/4); ui->spinDilate->setValue(2); ui->spinDilate->setSingleStep(1); ui->label_colNum->setText(QString::number( xnum)); ui->label_rowNum->setText(QString::number(ynum)); ui->label_deltX->setText(QString::number(deltx,'g',6)); ui->label_deltY->setText(QString::number(deltx,'g',6)); ui->label_zMin->setText(QString::number(zmin,'g',6)); ui->label_zMax->setText(QString::number(zmax,'g',6)); // ui->edit_dilateDist_2->setText(QString::number(std::max(deltx,delty)*2,'g',6) ); buildConnection(ui->edit_zMax,ui->sliderZMax); buildConnection(ui->edit_zMin,ui->sliderZMin); //buildConnection(ui->edit_dilateDist_2,ui->sliderDilateDist); //平滑次数信号槽 connect(ui->edit_smoothTimes, &QLineEdit::editingFinished,[this]{ if(ui->btnExecute->isChecked()) { // QTimer::singleShot(100,[this]{ on_btnExecute_clicked(); // }); } }); connect(ui->edit_minArea, &QLineEdit::editingFinished,[this]{ if(ui->btnExecute->isChecked()) { // QTimer::singleShot(100,[this]{ on_btnExecute_clicked(); // }); } }); //最小面积信号槽 connect(ui->spinDilate, QOverload::of(&QSpinBox::valueChanged),[this]{ if(ui->btnExecute->isChecked()) { QTimer::singleShot(100,[this]{ on_btnExecute_clicked(); }); } }); // connect(ui->spinDilate, &QSpinBox::editingFinished,[this]{ // if(ui->btnExecute->isChecked()) // on_btnExecute_clicked(); // }); } void MainWidget::on_btnBlackWhite_clicked() { ui->viewWidget->saveCurrentAxisRect(); cv::Mat mat; float zupper = ui->edit_zMax->text().toFloat(); float zlower = ui->edit_zMin->text().toFloat(); ImageUtils::convertSurfaceToMat(m_pSurface,zlower,zupper,mat); qApp->setOverrideCursor(Qt::BusyCursor); GSurface& surf =m_surfBlackWhite; if( nullptr == m_pSurface || ! ImageUtils::convertMatToSurface(mat,m_pSurface->X(0), m_pSurface->Y(0),m_pSurface->DeltX(),m_pSurface->DeltY(),&surf) ) { qApp->restoreOverrideCursor(); return; } ui->viewWidget->setType(ViewWidget::graymap); ui->viewWidget->setGrid(&surf,true); // QImage img; // if(! COutlineDetector::ConvertMatToQImage(mat,img) ) // return; // img = img.mirrored(false,true); // ui->viewWidget->setImage(img,true); qApp->restoreOverrideCursor(); } void MainWidget::on_btnExecute_clicked() { if(nullptr == m_pSurface) return; qApp->setOverrideCursor(Qt::WaitCursor); ui->viewWidget->saveCurrentAxisRect(); //形态学处理图像,生成初始等值线 ProcessImageAndCreateOriginalContours(); // //begin test // // //显示形态学处理后图像的黑白图,暂时不用 // cv::Mat mat = m_detector->getResultMat(); // cv::imshow("facies",mat); // //end test // //BEGIN TEST // qApp->restoreOverrideCursor(); // ui->btnOutputContours->setEnabled(true); // return; // //END TEST ShowOriginalContours(); // float zupper = ui->edit_zMax->text().toFloat(); // float zlower = ui->edit_zMin->text().toFloat(); // int nIters = ceil(ui->edit_dilateDist_2->text().toFloat() / std::min(m_pSurface->DeltX(),m_pSurface->DeltY())); // COutlineDetector* detector = m_detector; // detector->setSurface(m_pSurface,zlower,zupper,nIters); // m_detector->setContourMinArea(ui->edit_minArea->text().toFloat()); // m_detector->setContourSmoothTimes(ui->edit_smoothTimes->text().toUInt()); // detector->ProcessImage(); // cv::Mat mat = detector->getResultMat(); // GSurface surf; // if( nullptr == m_pSurface || ! COutlineDetector::convertMatToSurface(mat,m_pSurface->X(0), // m_pSurface->Y(0),m_pSurface->DeltX(),m_pSurface->DeltY(),&surf) ) // return; // ui->viewWidget->setType(ViewWidget::gray); // ui->viewWidget->setGrid(&surf); // ui->btnOutputContours->setEnabled(true); //// QImage img; //// if(! COutlineDetector::ConvertMatToQImage(mat,img) ) //// { //// qApp->restoreOverrideCursor(); //// return; //// } //// img = img.mirrored(false,true); // // ui->viewWidget->setImage(img,true); qApp->restoreOverrideCursor(); ui->btnOutputContours->setEnabled(true); } void MainWidget::on_btnOutputContours_clicked() { QString strFile = QFileDialog::getSaveFileName(this, tr("保存文件"),"",tr("Dfd files(*.dfd)")); if(strFile.isEmpty()) return; qApp->setOverrideCursor(Qt::WaitCursor); bool rst = writeContours(strFile); qApp->restoreOverrideCursor(); if(!rst) { QMessageBox::warning(this,"Warnning",tr("输出轮廓线失败!")); }else QMessageBox::warning(this,"Result",tr("输出轮廓线完成!")); } void MainWidget::on_btnOrigin_clicked() { ui->viewWidget->saveCurrentAxisRect(); if(m_pSurface) { ui->viewWidget->setType(ViewWidget::colorfulmap); ui->viewWidget->setGrid(m_pSurface,true); } } //绘制m_detector中的original轮廓线 void MainWidget::ShowOriginalContours(void) { ui->viewWidget->setType(ViewWidget::colorfulmap_contours); ui->viewWidget->setGrid(m_pSurface,false); float minArea = ui->edit_minArea->text().toFloat(); if(minArea < 1e-4) minArea = (float)1e-4; Contours tmpContours ;//= m_detector->GetOriginalContours(); m_detector->multiContourToRealCoords(m_detector->GetOriginalContours(),tmpContours,0); Contours drawingcontours; drawingcontours.reserve(tmpContours.size() ); for(auto& p:tmpContours) { if(contourArea(p) < minArea) continue; drawingcontours.push_back(p); } // vector> tmp2; // for(int i = 0; i < 1; i ++ ) // tmp2.push_back(tmpContours[i]); // tmpContours.assign(tmp2.begin(),tmp2.end() ); // m_detector->WriteContours(tmp2,"d:/tmp2.dfd"); ui->viewWidget->setContours(drawingcontours); ui->viewWidget->updateDraw(); } //进行形态学处理并生成初始轮廓线 void MainWidget::ProcessImageAndCreateOriginalContours() { float zupper = ui->edit_zMax->text().toFloat(); float zlower = ui->edit_zMin->text().toFloat(); // int nIters = ceil(ui->edit_dilateDist_2->text().toFloat() / std::min(m_pSurface->DeltX(),m_pSurface->DeltY())); int nIters = ui->spinDilate->value(); // qDebug() << "iters = " << nIters; COutlineDetector* detector = m_detector; detector->setSurface(m_pSurface,zlower,zupper,nIters); m_detector->setContourMinArea(ui->edit_minArea->text().toFloat()); m_detector->setContourSmoothTimes(ui->edit_smoothTimes->text().toUInt()); detector->ProcessImage(); // //显示形态学处理后图像的黑白图,暂时不用 // cv::Mat mat = detector->getResultMat(); // GSurface surf; // if( nullptr == m_pSurface || ! COutlineDetector::convertMatToSurface(mat,m_pSurface->X(0), // m_pSurface->Y(0),m_pSurface->DeltX(),m_pSurface->DeltY(),&surf) ) // return; // ui->viewWidget->setType(ViewWidget::graymap); // ui->viewWidget->setGrid(&surf,true); // ui->btnOutputContours->setEnabled(true); } void MainWidget::on_btnZoomAll_clicked() { ui->viewWidget->resetAxisRect(); ui->viewWidget->refreshAxis(); }