You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

622 lines
15 KiB
C++

1 month ago
#include "pch.h"
#include "mainwidget.h"
#include "ui_mainwidget.h"
#include <QFileDialog>
#include <QFile>
#include <QDebug>
#include <QMessageBox>
#include <QTextCodec>
#include "coutlinedetector.h"
#include "ImageUtils.h"
#include "ContourUtils.h"
#include <QButtonGroup>
#include <QSpinBox>
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<int>::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<vector<Point2f>> 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();
}