LINUX环境下基于QT5.5 和OPENCV3.0的常用数字图像及视频处理算法演示系统的开发
一,基本的图像处理操作
1,本节主要内容
本节主要演示图像的腐蚀、膨胀、开运算、闭运算、顶帽、黑帽等算法的调用。
2,概要设计
2.1利用QT的按钮、滑动条、标签等实现界面的UI交互与图像的选择和展现;
2.2 利用自定义函数封装控制逻辑;
/**********************************************************
* 根据指定的参数进行图像的腐蚀、膨胀、开运算、闭运算、梯度、顶帽、黑帽等操作
* int erodeDilateMorphologyEx //运算类型 0-erode 1-dilate 2-morphologyEx
* int morphShapesTypes //
* MORPH_ERODE = 0,
MORPH_DILATE = 1,
MORPH_OPEN = 2,
MORPH_CLOSE = 3,
MORPH_GRADIENT = 4,
MORPH_TOPHAT = 5,
MORPH_BLACKHAT = 6
int kernel // ths size of kernel
* 刘波 1352865098@qq.com
* 2015-07-28
***********************************************************/
void AipadsMainWindow::ImageErosionDilateOP ( int erodeDilateMorphologyEx, int morphShapesTypes , int kernel) {
//Size dsize = Size(imgShare.cols ,imgShare.rows);//目标图像尺寸
Mat erosionDilationImg;
//Mat element = getStructuringElement(MORPH_RECT, Size(imgShare.cols*0.5 ,imgShare.rows*0.5));
Mat element = getStructuringElement(morphShapes, Size(kernel,kernel));
switch (erodeDilateMorphologyEx) {
case 0: erode( imgShare, erosionDilationImg, element );break;
case 1: dilate( imgShare, erosionDilationImg, element );break;
case 2: morphologyEx( imgShare, erosionDilationImg, morphShapesTypes, element );;break;
}
//imshow("This is Test",erosionImg);
ui->dstImageLabel->setPixmap(QPixmap::fromImage(Mat2QImage( erosionDilationImg )) );
}
///
void AipadsMainWindow::on_ErosionPushButton_clicked()
{
erodeDilateMorphologyEx = 0;//
ImageErosionDilateOP ( erodeDilateMorphologyEx, morphTypes , kernel);
}
void AipadsMainWindow::on_DilationPushButton_clicked()
{
erodeDilateMorphologyEx = 1;//
ImageErosionDilateOP ( erodeDilateMorphologyEx, morphTypes , kernel);
}
void AipadsMainWindow::on_morphologyExPushButton_clicked()
{
erodeDilateMorphologyEx = 2;//
ImageErosionDilateOP ( erodeDilateMorphologyEx, morphTypes , kernel);
}
///
void AipadsMainWindow::on_kernelSlider_sliderMoved(int position)
{
kernel = ( position + 10 ) / 10;
ui->kernelLabel->setText("Kernel("+QString("%1").arg(kernel)+")");
ImageErosionDilateOP ( erodeDilateMorphologyEx, morphTypes , kernel);
}
void AipadsMainWindow::on_ErosionSlider_sliderMoved(int position)
{
int tmp = position / 14 ;
switch ( tmp ) {
case 0: morphShapes = MORPH_RECT, morphTypes = MORPH_ERODE; ui->MorphShapesLabel->setText("MorphShape/Type:RECT/ERODE"); break;
case 1: morphShapes = MORPH_CROSS, morphTypes = MORPH_DILATE; ui->MorphShapesLabel->setText("MorphShape/Type:CROSS/DILATE"); break;
case 2: morphShapes = MORPH_ELLIPSE, morphTypes = MORPH_OPEN; ui->MorphShapesLabel->setText("MorphShape/Type:ELLIPSE/OPEN"); break;
///
case 3: morphTypes = MORPH_CLOSE; ui->MorphShapesLabel->setText("MorphShape/Type:ELLIPSE/CLOSE"); break;
case 4: morphTypes = MORPH_GRADIENT; ui->MorphShapesLabel->setText("MorphShape/Type:ELLIPSE/GRADIENT"); break;
case 5: morphTypes = MORPH_TOPHAT; ui->MorphShapesLabel->setText("MorphShape/Type:ELLIPSE/TOPHAT"); break;
case 6: morphTypes = MORPH_BLACKHAT; ui->MorphShapesLabel->setText("MorphShape/Type:ELLIPSE/BLACKHAT"); break;
}
ImageErosionDilateOP ( erodeDilateMorphologyEx, morphTypes , kernel);
}
2.3利用OPENCV3.0提供的函数实现图像的操作
void
erode(
InputArray
src,
OutputArray
dst,
InputArray
kernel,
Point
anchor=Point(-1,-1),
int
iterations=1,
int
borderType=BORDER_CONSTANT,
const
Scalar& borderValue=morphologyDefaultBorderValue()
);
void
dilate(
InputArray
src,
OutputArray
dst,
InputArray
kernel,
Point
anchor=Point(-1,-1),
int
iterations=1,
int
borderType=BORDER_CONSTANT,
const
Scalar& borderValue=morphologyDefaultBorderValue()
);
void
morphologyEx(
InputArray
src,
OutputArray
dst,
int
op,
InputArraykernel,
Pointanchor=Point(-1,-1),
intiterations=1,
intborderType=BORDER_CONSTANT,
constScalar&
borderValue=morphologyDefaultBorderValue() )
3,代码实现
以下是核心代码:
//头文件定义:
class AipadsMainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit AipadsMainWindow(QWidget *parent = 0);
~AipadsMainWindow();
///
void loadExposureSeq( String path , vector<Mat>&images, vector<float>×);
void Mat2QImage1(Mat image);
QImage Mat2QImage(const cv::Mat& InputMat);
//QList getFilesName(std::string filePath);
QFileInfoList getFileList(QString path);
void displayImage ( QLabel *imgLable, int imgPosition);
//void ImageErosionDilateOP ( bool isErode, int morphShapesTypes , int kernel);
void ImageErosionDilateOP ( int erodeDilateMorphologyEx, int morphShapesTypes , int kernel);
protected:
void paintEnvet(QPaintEvent *e);
private slots:
void on_openImage_clicked();
void on_imageScaleSlider_sliderMoved(int position);
void on_pre_clicked();
void on_next_clicked();
void on_ErosionPushButton_clicked();
void on_DilationPushButton_clicked();
void on_ErosionSlider_sliderMoved(int position);
void on_kernelSlider_sliderMoved(int position);
void on_morphologyExPushButton_clicked();
private:
Ui::AipadsMainWindow *ui;
CvCapture *capture;
IplImage *frame;//highgui.h Intel Image Processing Library(IPL)
IplImage *iplImg;
QImage *qImg;
QTimer *timer;
Mat imgShare;
QFileInfoList fileList;
int currentPosition = 0;
int morphShapes = 0;
int morphTypes = 0;
int kernel = 1;
bool isErode = true;
int erodeDilateMorphologyEx = 0;
};
//默认构造函数
void
AipadsMainWindow::on_openImage_clicked()
{
vector<Mat> images;
vector<float> times;
//QString img_name = QFileDialog::directory();//::open();//::getOpenFileName( this, tr("Open Image"), ".",tr("Image Files(*.png *.jpg *.jpeg *.bmp)"));
//QFileDialog *selectedFileDictoyDil = new QFileDialog();
QString filePath="";
QString img_name = QFileDialog::getOpenFileName( this, tr("Open Image"), ".",tr("Image Files(*.png *.jpg *.jpeg *.bmp)"));
QFileInfo fileInfo = QFileInfo(img_name);
filePath = fileInfo.path();//获取文件所在的目录
std::cout<<"img_name:"<<img_name.toStdString()<<" filesPath:"<<filePath.toStdString()<<std::endl;//输出当前参数值供调试
{// code block begin 2015-07-26 liubo
//QFileInfoList
fileList = getFileList( filePath );//获取同一个目录下的所有文件信息
int countTmp = 0;
foreach (QFileInfo qfi, fileList) {//查找当前选中的文件在整个文件列表中的位置,并将其值付给位置变量,为后面的图片前后遍历提供信息
if (img_name == qfi.filePath()) {
currentPosition = countTmp;
std::cout<<"img_names["<< countTmp<<"]"<<qfi.fileName().toStdString()<<" filesPath:"<<qfi.path().toStdString()<<std::endl;//输出当前参数值供调试
break;
} else {
countTmp ++;
}
}
}// code block end 2015-07-26 liubo
imgShare = imread( img_name.toStdString());
ui->imageLabel->setPixmap(QPixmap::fromImage(Mat2QImage( imgShare )) );
ui->pre->setEnabled(true);
ui->next->setEnabled(true);
ui->ErosionPushButton->setEnabled(true);
ui->DilationPushButton->setEnabled(true);
ui->morphologyExPushButton->setEnabled(true);
ui->ErosionSlider->setEnabled(true);
ui->kernelSlider->setEnabled(true);
}
//图像转换函数
/************************************
* 将OPENCV格式的图片文件转换为QT格式的图片文件
* 刘波 liubo@wasu.com 1352865098@qq.com
* 2015-06-05
*
*
*************************************/
QImage AipadsMainWindow::Mat2QImage(const cv::Mat& InputMat)
{
cv::Mat TmpMat;
// convert the color space to RGB
if (InputMat.channels() == 1){
cv::cvtColor(InputMat, TmpMat, CV_GRAY2RGB);
} else {
cv::cvtColor(InputMat, TmpMat, CV_BGR2RGB);
}
// construct the QImage using the data of the mat, while do not copy the data
QImage Result = QImage((const uchar*)(TmpMat.data), TmpMat.cols, TmpMat.rows, QImage::Format_RGB888);
// deep copy the data from mat to QImage
Result.bits();
return Result;
}
//文件列表获取函数
/*******************************
* QDir TempDir(localPath);
* TempDir.setFilter(QDir::Dirs);
* QFileInfoList fileList = TempDir.entryInfoList();
* 用如上方法获取到localPath中的所有文件夹名的fileList中 有一个.和一个..的路径名。
* 获取同一个目录下的所有文件名
* 刘波 liubo@wasu.com 1352865098@qq.com
* 2015-07-27
*
*
*
********************************/
QFileInfoList AipadsMainWindow::getFileList(QString path)
{
QDir dir(path);
QFileInfoList file_list = dir.entryInfoList(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
QFileInfoList folder_list = dir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoDot);
for(int i = 0; i != folder_list.size(); i++)
{
QString name = folder_list.at(i).absoluteFilePath();
QFileInfoList child_file_list = getFileList(name);
file_list.append(child_file_list);
}
return file_list;
}
//文件遍历以及操作事件函数
void AipadsMainWindow::on_pre_clicked()
{
if ( 0 == currentPosition ) {
currentPosition = fileList.count() - 1;
} else {
currentPosition --;
}
displayImage(ui->imageLabel, currentPosition);
}
void AipadsMainWindow::on_next_clicked()
{
if ( fileList.count() == currentPosition + 1 ) {
currentPosition = 0;
} else {
currentPosition ++;
}
displayImage(ui->imageLabel, currentPosition);
}
///
void AipadsMainWindow::on_ErosionPushButton_clicked()
{
erodeDilateMorphologyEx = 0;//
ImageErosionDilateOP ( erodeDilateMorphologyEx, morphTypes , kernel);
}
void AipadsMainWindow::on_DilationPushButton_clicked()
{
erodeDilateMorphologyEx = 1;//
ImageErosionDilateOP ( erodeDilateMorphologyEx, morphTypes , kernel);
}
void AipadsMainWindow::on_morphologyExPushButton_clicked()
{
erodeDilateMorphologyEx = 2;//
ImageErosionDilateOP ( erodeDilateMorphologyEx, morphTypes , kernel);
}
///
void AipadsMainWindow::on_kernelSlider_sliderMoved(int position)
{
kernel = ( position + 10 ) / 10;
ui->kernelLabel->setText("Kernel("+QString("%1").arg(kernel)+")");
ImageErosionDilateOP ( erodeDilateMorphologyEx, morphTypes , kernel);
}
void AipadsMainWindow::on_ErosionSlider_sliderMoved(int position)
{
int tmp = position / 14 ;
switch ( tmp ) {
case 0: morphShapes = MORPH_RECT, morphTypes = MORPH_ERODE; ui->MorphShapesLabel->setText("MorphShape/Type:RECT/ERODE"); break;
case 1: morphShapes = MORPH_CROSS, morphTypes = MORPH_DILATE; ui->MorphShapesLabel->setText("MorphShape/Type:CROSS/DILATE"); break;
case 2: morphShapes = MORPH_ELLIPSE, morphTypes = MORPH_OPEN; ui->MorphShapesLabel->setText("MorphShape/Type:ELLIPSE/OPEN"); break;
///
case 3: morphTypes = MORPH_CLOSE; ui->MorphShapesLabel->setText("MorphShape/Type:ELLIPSE/CLOSE"); break;
case 4: morphTypes = MORPH_GRADIENT; ui->MorphShapesLabel->setText("MorphShape/Type:ELLIPSE/GRADIENT"); break;
case 5: morphTypes = MORPH_TOPHAT; ui->MorphShapesLabel->setText("MorphShape/Type:ELLIPSE/TOPHAT"); break;
case 6: morphTypes = MORPH_BLACKHAT; ui->MorphShapesLabel->setText("MorphShape/Type:ELLIPSE/BLACKHAT"); break;
}
ImageErosionDilateOP ( erodeDilateMorphologyEx, morphTypes , kernel);
}
// 图像操作控制函数
/**********************************************************
* 根据指定的参数进行图像的腐蚀、膨胀、开运算、闭运算、梯度、顶帽、黑帽等操作
* int erodeDilateMorphologyEx //运算类型 0-erode 1-dilate 2-morphologyEx
* int morphShapesTypes //
* MORPH_ERODE = 0,
MORPH_DILATE = 1,
MORPH_OPEN = 2,
MORPH_CLOSE = 3,
MORPH_GRADIENT = 4,
MORPH_TOPHAT = 5,
MORPH_BLACKHAT = 6
int kernel // ths size of kernel
* 刘波 1352865098@qq.com
* 2015-07-28
***********************************************************/
void AipadsMainWindow::ImageErosionDilateOP ( int erodeDilateMorphologyEx, int morphShapesTypes , int kernel) {
//Size dsize = Size(imgShare.cols ,imgShare.rows);//目标图像尺寸
Mat erosionDilationImg;
//Mat element = getStructuringElement(MORPH_RECT, Size(imgShare.cols*0.5 ,imgShare.rows*0.5));
Mat element = getStructuringElement(morphShapes, Size(kernel,kernel));
switch (erodeDilateMorphologyEx) {
case 0: erode( imgShare, erosionDilationImg, element );break;
case 1: dilate( imgShare, erosionDilationImg, element );break;
case 2: morphologyEx( imgShare, erosionDilationImg, morphShapesTypes, element );;break;
}
//imshow("This is Test",erosionImg);
ui->dstImageLabel->setPixmap(QPixmap::fromImage(Mat2QImage( erosionDilationImg )) );
}
///
4,注意事项
4.1将界面的滑动条标值转换为选项值的时候注意数据类型的操作;
4.2在加载到系统文件夹下的图片之前,注意要将相关的界面按钮的使能状态置为false状态,在图片加载成功之后再置为true状态;
5,参考文章
感谢以下博客的作者,本人还参考其他文章但未全部列出,如果有读者发现这里参考的谋篇文章但这里没有列出,请留言。
文中的代码有部分来自互联网无私风险的前辈,再次一并谢过,如果本文代码有部分来自你的原创而又不适合公布,请及时联系我。
http://www.tuicool.com/articles/ua22Uf
http://www.tuicool.com/articles/j6namy
http://blog.csdn.net/robberm/article/details/8631640
http://blog.csdn.net/viewcode/article/details/7836286
http://blog.csdn.net/augusdi/article/details/9014781
...
5,运行结果