QT开发

由于项目需要,编写一个简单的图像标注软件。
在这篇文章的基础上做了一些修改,添加了标注者信息、记录标注信息,生成图片格式的groundtruth、生成的groundtruth与原图大小相同、能够自动加载文件夹下的下一幅图像等。
http://blog.csdn.net/lanbing510/article/details/48251311
都是一些比较简单的方法,简单说一下我的思路:

  1. 首先,创建自己的QT Application。
    *开发环境Qt5.4.2+opencv3.0+vs2013. 貌似可以直接用Qt Creator,不过我没用。安装和环境配置不再叙述,直接创建工程喽!
    QT开发_第1张图片
    选择Qt Application,然后输入工程名,点击确定就可以了。

  2. 配置工程环境。
    QT开发_第2张图片
    选择好自己的版本
    QT开发_第3张图片
    这里也一样。
    QT开发_第4张图片
    配置管理器也需要注意一下,选择64位还是32位根据自己的配置情况来定呦。
    如果你的QT是64位,貌似opencv也需要是64位的。我在这里出过错,开始opencv是32位,就是x86,debug时提示错误,后来改成x64就可以了。
    这时候,你可以点击“本地Windows调试器”旁边的绿色按钮运行一下,会出现一个简单的界面,说明你的配置没有问题。可以进行下一步了。

  3. 将已有的文件加载到自己的工程中。
    QT开发_第5张图片
    红色框中的是添加的现有文件,其余的是创建工程的时候自己生成的。
    那么如何避免加载imagelabel.ui,而加载mainwindow.ui?
    非常简单,只需要修改main.cpp就ok了。

#include "imagelabel.h"
#include "mainwindow.h"
#include "setparameterdialog.h"
#include 

//#include 
//Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin)

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //ImageLabel w;
    MainWindow w;
    w.show();
    return a.exec();
}

是不是很简单,现在如果你运行,就是mainwindow.ui所呈现的界面啦。

  1. 开始修改功能。

    4.1 ui界面修改
    Qt中的ui界面修改非常简单,你可以选择用代码来编辑,也可以使用可视化的界面,将一些元素拖拽到界面上,对属性做一些修改就可以了。
    QT开发_第6张图片
    是不是分分钟就可以搞定,哈哈哈~
    对setparameter进行差不多的操作:
    QT开发_第7张图片
    修改出你满意的界面之后,对界面的按钮进行响应。也就是要进行代码的修改喽!
    下面我只针对添加的功能,叙述我做出修改的部分,引用的代码当中有的:设置,打开图片,保存图片、连线,填充等不会详细描述呦

    4.2 添加标注者信息
    记录标注者信息的方式是创建文件夹,为不同的标注者创建不同的文件夹,保存时路径:输出路径\标注者\不同类型的标注\图像名。
    首先获取“标注者”文本框中的值:

       //获取文本框中的值
       //读取图片的路径
       QString imgPath=prSetDlg->getImagePath();
       //这里fileFormat为起始图片的文件名
       QString imgfileFormat=prSetDlg->getFileFormat();
       //输出路径
       QString outPath=prSetDlg->getOutputPath();
       //标注者
       QString markName=prSetDlg->getMarkerName();

然后将值赋给提前定义好的成员变量:

 if(imgPath==""||imgfileFormat==""||outPath==""||markName=="")
       {
           QMessageBox::information(NULL, "Information", "Please Set The Parematers",QMessageBox::Ok , QMessageBox::Ok);
       }
       else
       {
           fileFormat = imgfileFormat;
           markerName = markName;
       }

这样,在对图片处理完毕,进行保存的时候,利用QDir获取路径,如果不存在就创建:

outPath=outPath+"\\"+markerName;
imgOutputPath = outputPath +"\\"+ lesionName + "\\" + fileFormat;
imgOutputPath.sprintf(imgOutputPath.toStdString().c_str());
//判断路径是否存在,不存在就创建
QDir *temp = new QDir;
QString dir = outputPath +"\\"+ lesionName;
bool exist = temp->exists(outputPath);
if (!exist)
{
    if(temp->mkdir(outputPath))
        QMessageBox::information(NULL, tr("Create save path"), "Create makerName path ok!", QMessageBox::Ok);;
}
exist = temp->exists(dir);
if (!exist)
{
    if (temp->mkdir(dir))
        QMessageBox::information(NULL, tr("Create save path"), "Create lesionName path ok!", QMessageBox::Ok);;
}
if (!imwrite(imgOutputPath.toStdString(), img_mask_binary))
 {
    QMessageBox::information(NULL,"Save Error","Please Check Your Save Path!",QMessageBox::Ok);
 }

注意在前面包含头文件:

#include 

4.3 自动加载下一张图片
这里用的方法是获取文件夹下的所有图片,将信息保存在QFileInfoList 中。

QFileInfoList MainWindow::getFileInfoList(QString inputPath)
{
    QDir dir(inputPath);
    dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
    dir.setSorting(QDir::DirsFirst);
    QFileInfoList list = dir.entryInfoList();
    return list;
}

获取当前图片在list中的位置:

 imageNum = 0;
//获取要打开图像在文件夹中的序号
 list = getFileInfoList(inputPath);
 QFileInfo fileInfo;
 for (int i = 0; i < list.size(); i++)
 {
  fileInfo = list.at(i);
  if (fileInfo.fileName() == fileFormat)
  {
       imageNum = i;
       break;
  }
 }

读取下一张图片:

bool MainWindow::readNextImage()
{
    //先找到当前文件(第一幅图片)的序号
    int flag=imageNum+1;
    if (flag < list.size())
    {
        contour.clear();
        QFileInfo fileinfo = list.at(flag);
        fileFormat = fileinfo.fileName();
        //显示在状态栏
        ui->frameshowLabel->setText(fileFormat);
        imgInputPath = inputPath + fileFormat;
        imgInputPath.sprintf(imgInputPath.toStdString().c_str());//,frameIdx);
        img_cur = imread(imgInputPath.toStdString());
        if (!img_cur.empty())
        {
            img_cur.copyTo(img_pre);
            displayMat(img_cur);
            img_orignal = img_cur;
            // prSetDlg->setStartFrame(QString("%1").arg(frameIdx));

            mask.create(img_cur.size(), CV_8UC1);
            imageNum++;
            return true;
        }
        else
        {
        QMessageBox::information(NULL, "Read Failure", "Failed To Read " + imgInputPath, QMessageBox::Ok, QMessageBox::Ok);
        return false;
        }
    }
    else
    {
        QMessageBox::information(NULL, "Read Failure", "There is the last image!" , QMessageBox::Ok, QMessageBox::Ok);
        return false;
    }
}

4.4 记录不同的标注类型信息
意思是:对同一张图片,可能需要针对它不同的方面进行标注,我做的是对眼底图像病变的标注,一般有四种病变类型,切换函数如下:

void MainWindow::on_nextLesionPushButton_clicked()
{
    if (lesionFlag==1)
    {
        ui->nextLesionPushButton->setText("S***");
        lesionName = ui->nextLesionPushButton->text();
        readImage();
        lesionFlag = 2;
    }
    else if (lesionFlag==2)
    {
        ui->nextLesionPushButton->setText("He***");
        lesionName = ui->nextLesionPushButton->text();
        readImage();
        lesionFlag = 3;
    }
    else if (lesionFlag==3)
    {
        ui->nextLesionPushButton->setText("M***");
        lesionName = ui->nextLesionPushButton->text();
        readImage();
        lesionFlag = 4;
    }
    else if (lesionFlag==4)
    {
        ui->nextLesionPushButton->setText("H***");
        lesionName = ui->nextLesionPushButton->text();
        readImage();
        lesionFlag = 1;
    }
    else
    {
        //出错处理,debug的时候用
        QMessageBox::information(NULL, "Error", "Maybe your code have bugs!", QMessageBox::Ok);
    }
}

4.5 生成与原图大小相同的图片格式的groundtruth。
一般,可以根据图片的大小动态地改变窗口的大小:

 ui->label->setPixmap(QPixmap::fromImage(img));
 ui->label->resize(ui->label->pixmap()->size());
 ui->label->show();

在保存时,resize一下图像,使其与原始图像一样大:

Mat img_mask,img_mask_binary;
cv::resize(img_cur, img_cur, Size(img_orignal.cols, img_orignal.rows));
//计算img_orignal与img_cur的差
cv::subtract(img_orignal, img_cur, img_mask);
cvtColor(img_mask, img_mask_binary, CV_BGR2GRAY);

5 出现的bug
编译成功后,如果不是用的静态编译,很容易出现换一台电脑就不能用了。可以在.exe目录下放上一些需要的.dll文件。
QT开发_第8张图片
貌似如果你用的是x64,在32位的Windows系统上面不能运行呢,我也没有继续解决这一部分。

6 总结
这次主要是在别人代码的基础上做的一些功能的增减,但是对我了解Qt还是挺有帮助的。实现这些功能的方法也都比较简单。
第一次写技术博客,没有经验,搞的不好。希望以后可以更好,哈哈~

你可能感兴趣的:(QT)