赞
踩
在图像识别领域中,当需要计算机能够识别图片场景中的新目标种类时,需要进行大量的目标物图片样本的采集,标注和训练。这其中,大批量图片样本的人工标注则是最繁琐也最容易出错的一个环节,因此,原始的jpg图片样本与标注后生成的xml文件是否能一一对应则显得尤为重要;
一、点击界面JPG按钮、XML按钮分别选择对应格式文件所在的文件夹,在“文件位置”下方Label中展示打开的文件夹位置,“初始数目”各自对应的文件数量,并建立“log”日志文件,记录操作过程,建立备份的“backup”文件夹,用于后续的删除文件备份;
二、点击开始按钮,在线程中对jpg文件夹与xml文件夹中文件进行比对和处理,显示处理进度,并保证最终两个文件夹下的内容一一对应;
三、点击记录查询按钮:在打开的新页面中展示文件的处理时间和处理过程;
一、头文件:
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include<QStringList> #include<QFileInfoList> #include "checkoutfilethread.h" #include"logrecord.h" namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); public: void setBackUpDir(); private slots: void on_JPGButton_clicked(); void on_XMLButton_clicked(); void on_startButton_clicked(); void on_recordQueryButton_clicked(); private: Ui::Widget *ui; CheckOutFileThread workThread; public: QString m_jpgFilePath; QString m_xmlFilePath; }; #endif // WIDGET_H
二、源文件
#include "widget.h" #include "ui_widget.h" #include <QDir> #include <QFile> #include <QFileDialog> #include <QDateTime> #include <QByteArray> #include <QTextCodec> const int CUT_SIZE = 4; Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); this->setWindowTitle(tr("JPG&XML")); this->setWindowIcon(QIcon(":/new/images/xml.ico")); connect(&workThread, &CheckOutFileThread::sendProcessValueRange, this, [&](int maxlVal) { ui->progressBar->setRange(0, maxlVal); }); connect(&workThread, &CheckOutFileThread::sendProgressSignal, this, [&](int value) { if(value == 0) { ui->dealShowLabel->setText(tr("源文件与目标文件完整对应,未作处理")); } else { ui->progressBar->setValue(value); ui->dealShowLabel->setText(tr("处理完毕,源文件与目标文件完整对应")); } }); connect(&workThread, &CheckOutFileThread::sendResaultCount, this, [&](int jpgNum, int xmlNum) { ui->finalJpgNumLabel->setText(QString("%1").arg(jpgNum)); ui->finalXmlNumLabel->setText(QString("%1").arg(xmlNum)); }); connect(&workThread, &CheckOutFileThread::sendLogFileCreat, this, [&](QString txt){ ui->logShowLabel->setText(txt); }); } Widget::~Widget() { if (workThread.isRunning()) { workThread.killTimer(0); } delete ui; } void Widget::setBackUpDir() { QDir recoverDir("./"); // 也可设置为QCoreApplication::applicationDirPath() if (!recoverDir.exists("backup")) { recoverDir.mkdir("backup"); ui->dealShowLabel->setText("备份文件夹建立成功!"); } } void Widget::on_JPGButton_clicked() { QString jpgFileDir = QFileDialog::getExistingDirectory(this, "JPG文件目录", "/"); if (jpgFileDir.isEmpty()) { ui->dealShowLabel->setText(tr("文件夹路径获取失败!")); return; } ui->locationJpgLabel->setText(jpgFileDir); // 记录对文件的操作时间,在exe目录下新建文件夹,用于备份删除过的源文件,并记录操作log日志; setBackUpDir(); QFile JpgXmlLog("log.txt"); bool openSucceed = JpgXmlLog.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append); openSucceed ? ui->logShowLabel->setText(tr("日志文件创建成功")) : ui->logShowLabel->setText(tr("日志文件创建失败")); QByteArray JpgFileOp = QTextCodec::codecForName("UTF-8")->fromUnicode("JPG目录冗余文件删除时间: "); JpgXmlLog.write(JpgFileOp); JpgXmlLog.write((QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") + "\n").toLatin1().data()); // 遍历目录文件,移动所有非jpg格式图片至备份的backup目录中 int delCount = 0; QDir JpgDir(jpgFileDir); QStringList moveOfJpg = JpgDir.entryList(); foreach (QString delOther, moveOfJpg) { if (QString::compare(delOther.right(CUT_SIZE), ".jpg") != 0) { // CUT_SIZE = 4 QString srcDirFile = jpgFileDir + "/" + delOther; QString backupDirFile = QString("backup") + "/" + delOther; // QString backupDirFile = QCoreApplication::applicationDirPath() + "/" + "backup" + "/" + delOther; QFile::copy(srcDirFile, backupDirFile); JpgXmlLog.write((delOther + "\n").toLatin1().data()); JpgDir.remove(delOther); delCount++; } } JpgXmlLog.close(); ui->initJpgNumLabel->setText(QString::number(JpgDir.count() - delCount)); m_jpgFilePath = jpgFileDir; } void Widget::on_XMLButton_clicked() { QString xmlFileDir=QFileDialog::getExistingDirectory(this,"XML文件目录","/"); if (xmlFileDir.isEmpty()) { ui->dealShowLabel->setText(tr("文件夹路径获取失败!")); return; } ui->locationXmlLabel->setText(xmlFileDir); QFile JpgXmlLog("log.txt"); bool openSucceed = JpgXmlLog.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append); openSucceed ? ui->logShowLabel->setText(tr("日志文件创建成功")) : ui->logShowLabel->setText(tr("日志文件创建失败")); QByteArray XmlFileOp=QTextCodec::codecForName("UTF-8")->fromUnicode("XML目录冗余文件删除时间:"); JpgXmlLog.write(XmlFileOp); JpgXmlLog.write((QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")+"\n").toLatin1().data()); int delCount=0; QDir XmlDir(xmlFileDir); QStringList delOutOfXml=XmlDir.entryList(); foreach (QString delOther, delOutOfXml) { if(QString::compare(delOther.right(CUT_SIZE), ".xml") != 0) { QString srcDirFile = xmlFileDir + "/" + delOther; QString backupDirFile = QString("backup") + "/" + delOther; // QString backupDirFile = QCoreApplication::applicationDirPath() + "/" + "backup" + "/" + delOther; QFile::copy(srcDirFile, backupDirFile); JpgXmlLog.write((delOther + "\n").toLatin1().data()); XmlDir.remove(delOther); delCount++; } } JpgXmlLog.close(); ui->initXmlNumLabel->setText(QString::number(XmlDir.count() - delCount)); m_xmlFilePath = xmlFileDir; } void Widget::on_startButton_clicked() { if(m_jpgFilePath.isEmpty() || m_xmlFilePath.isEmpty() || workThread.isRunning()) { ui->logShowLabel->setText("路径异常或正在处理,请重试..."); return; } workThread.setParent(this); workThread.InitFilePath(m_jpgFilePath, m_xmlFilePath); workThread.start(); } void Widget::on_recordQueryButton_clicked() { LogRecord RecordShow; RecordShow.exec(); }
三、界面文件
一、头文件
#ifndef CHECKOUTFILETHREAD_H #define CHECKOUTFILETHREAD_H #include <QThread> #include <QFileInfoList> class CheckOutFileThread : public QThread { Q_OBJECT public: CheckOutFileThread() {}; protected: virtual void run(); signals: void sendLogFileCreat(QString txt); void sendProgressSignal(int value); void sendProcessValueRange(int max); void sendResaultCount(int jpgNum, int xmlNum); private: QFileInfoList m_jpgs; QFileInfoList m_xmls; QString m_jpgPath; QString m_xmlPath; public: void InitFilePath(QString jpgsDir, QString xmlsDir); }; #endif // CHECKOUTFILETHREAD_H
二、源文件
#include "checkoutfilethread.h" #include <QFile> #include <QFileInfo> #include <QDir> #include <QDateTime> #include <QCoreApplication> #include <QTextCodec> #include <QByteArray> void CheckOutFileThread::run() { QDir jpgDir(m_jpgPath, "*.jpg"); QDir xmlDir(m_xmlPath, "*.xml"); QStringList jpgFiles = jpgDir.entryList(); QStringList xmlFiles = xmlDir.entryList(); // 打开日志文件记录操作,在exe目录下的backup文件夹中将删除后的文件备份 QFile JpgXmlLog("log.txt"); bool openSucceed = JpgXmlLog.open(QIODevice::WriteOnly | QIODevice::Text |QIODevice::Append); openSucceed ? emit sendLogFileCreat(tr("日志文件在线程中打开成功")) : emit sendLogFileCreat(tr("日志文件在线程中打开失败")); QByteArray threadFileOp = QTextCodec::codecForName("UTF-8")->fromUnicode("线程操作删除文件时间: "); JpgXmlLog.write(threadFileOp); JpgXmlLog.write((QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") + "\n").toLatin1().data()); // xml目录中若不包含同名对应的jpg文件,则备份后并将其加入删除列表中,在xml文件夹中将其删除 int index = 0; QStringList deleteFiles; foreach(QString jpg, jpgFiles) { QString tempJpg = jpg; int jpgPosition = tempJpg.lastIndexOf(".jpg"); QString fileName = tempJpg.replace(jpgPosition, 4, ".xml"); if (!xmlFiles.contains(fileName)) { QString srcDirFile = m_jpgPath + "/" + jpg; QString backupDirFile = QString("backup") + "/" +jpg; // QString backupDirFile = QCoreApplication::applicationDirPath() + "/" + "backup"+ "/" +jpg; QFile::copy(srcDirFile, backupDirFile); deleteFiles.append(m_jpgPath + "/" + jpg ); QString logRecord = m_jpgPath + "/" + jpg + "\n"; JpgXmlLog.write(logRecord.toLatin1().data()); } } // 同理,jpg目录中若不包含同名对应的xml文件,则备份该xml文件,并将其加入删除列表中 foreach(QString xml, xmlFiles) { QString tempxml = xml; int xmlPosition = tempxml.lastIndexOf(".xml"); QString fileName = tempxml.replace(xmlPosition, 4, ".jpg"); if (!jpgFiles.contains(fileName)) { QString srcDirFile = m_xmlPath + "/" + xml; QString backupDirFile = QString("backup") + "/" + xml; // QString backupDirFile = QCoreApplication::applicationDirPath() + "/" + "backup" + "/" + xml; QFile::copy(srcDirFile, backupDirFile); deleteFiles.append(m_xmlPath + "/" + xml); QString logRecord = m_xmlPath + "/" + xml + "\n"; JpgXmlLog.write(logRecord.toLatin1().data()); } } JpgXmlLog.close(); // 不对应文件删除 if (deleteFiles.isEmpty()) { emit sendProgressSignal(0); } else { emit sendProcessValueRange(deleteFiles.count()); foreach (QString deleteFile , deleteFiles) { if(jpgDir.exists(deleteFile)) { jpgDir.remove(deleteFile); } if(xmlDir.exists(deleteFile)) { xmlDir.remove(deleteFile); } emit sendProgressSignal(++index); } } // 处理结束后,获取jpg与xml文件夹下文件数量 QDir jpgDirResult(m_jpgPath, "*.jpg"); QDir xmlDirResult(m_xmlPath, "*.xml"); emit sendResaultCount(jpgDirResult.count(), xmlDirResult.count()); } void CheckOutFileThread::InitFilePath(QString jpgsDir, QString xmlsDir) { m_jpgPath = jpgsDir; m_xmlPath = xmlsDir; }
一、头文件
#ifndef LOGRECORD_H #define LOGRECORD_H #include <QDialog> namespace Ui { class LogRecord; } class LogRecord : public QDialog { Q_OBJECT public: explicit LogRecord(QWidget *parent = 0); ~LogRecord(); private: Ui::LogRecord *ui; }; #endif // LOGRECORD_H
二、源文件
#include "logrecord.h" #include "ui_logrecord.h" #include <QFile> #include <QTextStream> LogRecord::LogRecord(QWidget *parent) : QDialog(parent), ui(new Ui::LogRecord) { ui->setupUi(this); this->setWindowTitle(tr("操作日志")); QFile readLog("log.txt"); if (!readLog.open(QIODevice::ReadOnly | QIODevice::Text)) { ui->plainTextEdit->appendPlainText("log.txt文件打开失败!"); } QTextStream readTxt(&readLog); ui->plainTextEdit->setPlainText(readTxt.readAll()); readLog.close(); } LogRecord::~LogRecord() { delete ui; }
三、界面文件
完整代码链接
https://download.csdn.net/download/qq_44896246/87265004
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。