一、環境介紹
操作系統:windows10 X64位
QT版本: 12.6
二、軟件設計需求說明
最近經常使用OpenCV等算法處理識別圖像,需要準備很多正負樣本圖片,就編寫了這個小工具,方便在處理樣本數據時方便一點。軟件支持灰度圖像輸出、支持指定的寬度、高度輸出,支持保持縱橫比輸出。
三、效果圖
四、核心代碼
4.1 xxx.pro文件代碼
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
RC_ICONS=log.ico
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
widget.cpp
HEADERS += \
widget.h
FORMS += \
widget.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
win32
{
message('運行win32版本')
#添加opencv頭文件的路徑,需要根據自己的頭文件路徑進行修改
INCLUDEPATH+=C:/OpenCV_3.4.7/OpenCV-MinGW-Build-OpenCV-3.4.7/include \
C:/OpenCV_3.4.7/OpenCV-MinGW-Build-OpenCV-3.4.7/include/opencv \
C:/OpenCV_3.4.7/OpenCV-MinGW-Build-OpenCV-3.4.7/include/opencv2
LIBS+=C:/OpenCV_3.4.7/OpenCV-MinGW-Build-OpenCV-3.4.7/x86/mingw/bin/libopencv_*.dll
}
4.2 xxx.cpp代碼
#include "widget.h"
#include "ui_widget.h"
class IMAGE_CONFIG image_config;
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->setWindowTitle("圖片格式與尺寸轉換");
/*初始化賦值*/
dir_name="C:/"; //默認打開C盤
save_dir_name="C:/";//默認保存到C盤
ui->lineEdit_out_addr->setText("C:/");
//圖片的格式名字
Format_Name="*.bmp *.jpg *.png *.ico *.JPEG *.PNG *.BMP *.ICO *.SVG *.PSD";
ui->plainTextEdit_log->setReadOnly(true);
ui->spinBox_high->setMaximum(2000);
ui->spinBox_width->setMaximum(2000);
ui->spinBox_high->setMinimum(5);
ui->spinBox_width->setMinimum(5);
ui->spinBox_high->setValue(480);
ui->spinBox_width->setValue(640);
ui->checkBox_scale->setChecked(true); //設置 縱橫比默認選中
QStringList list;
list<<"bmp"<<"jpg"<<"png"<<"ico"<<"jpeg";
ui->comboBox_format->addItems(list);
//關聯圖片轉換線程
connect(&scale_out_image,SIGNAL(LogSend(QString)),this,SLOT(Image_Log_Display(QString)));
}
Widget::~Widget()
{
delete ui;
}
void Widget::Image_Log_Display(QString text)
{
Log_Text_Display(ui->plainTextEdit_log,text);
}
/*日誌顯示*/
void Widget::Log_Text_Display(QPlainTextEdit *plainTextEdit_log,QString text)
{
//設置光標到文本末尾
plainTextEdit_log->moveCursor(QTextCursor::End, QTextCursor::MoveAnchor);
//當文本數量超出一定範圍就清除
if(plainTextEdit_log->toPlainText().size()>4096)
{
plainTextEdit_log->clear();
}
plainTextEdit_log->insertPlainText(text);
//移動滾動條到底部
QScrollBar *scrollbar = plainTextEdit_log->verticalScrollBar();
if(scrollbar)
{
scrollbar->setSliderPosition(scrollbar->maximum());
}
}
//選擇圖片
void Widget::on_pushButton_select_clicked()
{
image_config.filenamelist=QFileDialog::getOpenFileNames(this,"選擇打開的文件",dir_name,Format_Name);
if(image_config.filenamelist.count()<=0)
{
Image_Log_Display("未選擇任何圖片.\n");
return;
}
else
{
Image_Log_Display(tr("當前選擇了%1 張圖片,可以點擊按鈕開始轉換.\n").arg(image_config.filenamelist.count()));
QFileInfo fileinfo=QFileInfo(image_config.filenamelist.at(0)); //得到文件信息
dir_name=fileinfo.absolutePath(); //取出絕對路徑--方便下次打開
}
}
//選擇圖片輸出的路徑
void Widget::on_pushButton_select_out_addr_clicked()
{
save_dir_name=QFileDialog::getExistingDirectory(this,"選擇目錄",save_dir_name,QFileDialog::ShowDirsOnly| QFileDialog::DontResolveSymlinks);
if(save_dir_name==nullptr)
{
Image_Log_Display("未選擇正確路徑.\n");
ui->lineEdit_out_addr->setText("C:/");
}
else
{
ui->lineEdit_out_addr->setText(save_dir_name);
}
}
//開始轉換
void Widget::on_pushButton_Start_clicked()
{
image_config.run_flag=1;
image_config.high=ui->spinBox_high->value();
image_config.width=ui->spinBox_width->value();
image_config.isChecked=ui->checkBox_scale->isChecked();
image_config.image_Attributes=ui->checkBox_image_Attributes->isChecked();
image_config.comboBox_format=ui->comboBox_format->currentText();
image_config.lineEdit_out_addr=ui->lineEdit_out_addr->text();
//開始轉換
scale_out_image.start();
}
void Widget::on_pushButton_stop_clicked()
{
image_config.run_flag=0;
scale_out_image.close();
}
//關閉線程
void ScaleOutImage::close()
{
image_config.run_flag=0;
this->quit();
this->wait();
}
//線程執行函數
void ScaleOutImage::run()
{
int cnt=0;
QString out_name;
Mat src_frame;
Mat dst_frame;
for(int i=0;i<image_config.filenamelist.count();i++)
{
//加載圖片
QImage image(image_config.filenamelist.at(i));
if(image.isNull())
{
LogSend(tr("%1 圖片加載失敗.\n").arg(image_config.filenamelist.at(i)));
continue;
}
if(image_config.isChecked)
{
image=image.scaled(image_config.width,image_config.high,Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
else
{
image=image.scaled(image_config.width,image_config.high);
}
//灰度圖像
if(image_config.image_Attributes)
{
// image is the input color image, img is output grey image
for(int i = 0; i < image.width(); ++i) {
for (int j = 0; j < image.height(); ++j) {
int gray = qGray(image.pixel(i, j));
image.setPixel(i, j, QColor(gray, gray, gray).rgb());
}
}
}
out_name=tr("%1/%2.%3").arg(image_config.lineEdit_out_addr).arg(cnt++).arg(image_config.comboBox_format);
//判斷是否轉換成功
if(image.save(out_name))
{
LogSend(tr("[%1] %2-->%3->成功\n").arg(i+1).arg(image_config.filenamelist.at(i)).arg(out_name));
}
else
{
LogSend(tr("[%1] %2-->%3->失敗\n").arg(i+1).arg(image_config.filenamelist.at(i)).arg(out_name));
}
if(image_config.run_flag==0)
{
break;
}
}
}
Mat ScaleOutImage::QImage2cvMat(QImage image)
{
Mat mat;
switch(image.format())
{
case QImage::Format_ARGB32:
case QImage::Format_RGB32:
case QImage::Format_ARGB32_Premultiplied:
mat = Mat(image.height(), image.width(), CV_8UC4, (void*)image.constBits(), image.bytesPerLine());
break;
case QImage::Format_RGB888:
mat = Mat(image.height(), image.width(), CV_8UC3, (void*)image.constBits(), image.bytesPerLine());
cvtColor(mat, mat, CV_BGR2RGB);
break;
case QImage::Format_Indexed8:
mat = Mat(image.height(), image.width(), CV_8UC1, (void*)image.constBits(), image.bytesPerLine());
break;
}
return mat;
}
QImage ScaleOutImage::Mat2QImage(const Mat& mat)
{
// 8-bits unsigned, NO. OF CHANNELS = 1
if(mat.type() == CV_8UC1)
{
QImage image(mat.cols, mat.rows, QImage::Format_Indexed8);
// Set the color table (used to translate colour indexes to qRgb values)
image.setColorCount(256);
for(int i = 0; i < 256; i++)
{
image.setColor(i, qRgb(i, i, i));
}
// Copy input Mat
uchar *pSrc = mat.data;
for(int row = 0; row < mat.rows; row ++)
{
uchar *pDest = image.scanLine(row);
memcpy(pDest, pSrc, mat.cols);
pSrc += mat.step;
}
return image;
}
// 8-bits unsigned, NO. OF CHANNELS = 3
else if(mat.type() == CV_8UC3)
{
// Copy input Mat
const uchar *pSrc = (const uchar*)mat.data;
// Create QImage with same dimensions as input Mat
QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
return image.rgbSwapped();
}
else if(mat.type() == CV_8UC4)
{
// Copy input Mat
const uchar *pSrc = (const uchar*)mat.data;
// Create QImage with same dimensions as input Mat
QImage image(pSrc, mat.cols, mat.rows, mat.step, QImage::Format_ARGB32);
return image.copy();
}
else
{
return QImage();
}
}
4.3 xxx.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QPlainTextEdit>
#include <QScrollBar>
#include <QFileDialog>
#include <QDebug>
#include <QFileInfo>
#include <QThread>
#include "opencv2/core/core.hpp"
#include "opencv2/core/core_c.h"
#include "opencv2/objdetect.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
using namespace cv;
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
//圖片轉換
class ScaleOutImage:public QThread
{
Q_OBJECT
public:
void close();
Mat QImage2cvMat(QImage image);
QImage Mat2QImage(const Mat& mat);
protected:
void run();
signals:
void LogSend(QString text);
};
//全局配置
class IMAGE_CONFIG
{
public:
bool isChecked; //縱橫比
bool image_Attributes; //灰度圖像
QStringList filenamelist;
int width;
int high;
QString lineEdit_out_addr;
QString comboBox_format;
bool run_flag;
};
extern class IMAGE_CONFIG image_config;
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void Log_Text_Display(QPlainTextEdit *plainTextEdit_log,QString text);
QString Format_Name; //圖片格式名字
ScaleOutImage scale_out_image;
QString dir_name; //保持當前的目錄名稱
QString save_dir_name; //保存輸出目錄的名稱
private slots:
void Image_Log_Display(QString text);
void on_pushButton_select_clicked();
void on_pushButton_select_out_addr_clicked();
void on_pushButton_Start_clicked();
void on_pushButton_stop_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H