前言
本科期间学习过C语言,拿到了计算机二级证书,此外主要自学MATLAB和Python进行深度学习相关的编程。一直以为C++和C#与C语言大同小异,没有重视,在学校的项目需要用C++进行编程,并且甲方点名界面要用Qt做,觉得MFC太难看。也罢,近乎于从0开始,趁着新肺,在家自学C++与Qt,借此记录,欢迎大家交流。
一、开发环境
1、Windows 10 64位;
2、Qt 5.8.0(MINGW编译器,利用Qt Creator而不是宇宙最强IDE——vs);
3、OpenCV 3.2.0
二、环境配置
参考的是:拜小白教你Qt5.8.0+OpenCV3.2.0配置教程(详细版)
虽然作者讲的很详细,但是还是一直失败失败失败,让我接近崩溃边缘,教训分享一下,安装的时候有两点需要注意:
1、如果电脑里之前安装有python,编译OpenCV的时候需要在cmake中把python的支持前面的勾去掉,不然make的时候会报错(python下安装opencv就是一句话的事,怎么会用cmake呢)
2、会出现下载的OpenCV下缺少文件的情况,然后cmake的时候现场下载,因为墙的原因,会下载失败。(例如opencv_ffmpeg_64.dll)
解决方法可以参考:CMake opencv时Download: opencv_ffmpeg.dll、ippicv等失败的解决方法
三、编程开始
1、建立Qt项目
打开我们安装的Qt Creator 4.2.1(Qt版本是5.8,但是自带的IDE——Qt Creator版本是4.2.1,虽然版本更新,但是和2012年的vs比还是差一点)
选择Qt Widgets Application,然后取个名字,选择路径,一直下一步下一步就好。
2、添加OpenCV依赖项
这部分也是参考环境配置的作者,在左侧pro左侧添加你的opencv的安装路径以及编译好的buildOpencv的路径,比如我的是:
INCLUDEPATH+=D:\DiyProgram\opencv\build\include
D:\DiyProgram\opencv\build\include\opencv
D:\DiyProgram\opencv\build\include\opencv2
LIBS += D:\DiyProgram\buildOpencv\lib\libopencv_*.a
注意这部分每一次在Qt中建立OpenCV项目都需要写,建议复制保存。
3、开始编程
首先建立我的框架界面:
右下角是两个按钮,上面两个框是两个Label,用来显示图片。需要实现的功能是,首先点击左边的按钮,读取原图,显示在左边的框,然后点击右边的按钮,将经过canny边缘提取的图片显示在右边的框。
我的项目下的文件列表如下:
首先编写头文件mainwindow.h,将一些include可以写进去,然后申明两个按钮的点击函数:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <stdio.h>
#include <iostream>
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
using namespace std;
using namespace cv;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
main.cpp不用管,保持默认即可:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp包括图像处理的程序与按钮点击的槽函数等等:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void Gaussian_kernel(int kernel_size, int sigma, Mat &kernel)
{
const double PI = 3.1415926;
int m = kernel_size / 2;
kernel = Mat(kernel_size, kernel_size, CV_32FC1);
float s = 2 * sigma*sigma;
for (int i = 0; i < kernel_size; i++)
{
for (int j = 0; j < kernel_size; j++)
{
int x = i - m;
int y = j - m;
kernel.at<float>(i, j) = exp(-(x*x + y*y) / s) / (PI*s);
}
}
}
/*
计算梯度值和方向
imageSource 原始灰度图
imageX X方向梯度图像
imageY Y方向梯度图像
gradXY 该点的梯度幅值
pointDirection 梯度方向角度
*/
void GradDirection(const Mat imageSource, Mat &imageX, Mat &imageY,Mat &gradXY, Mat &theta)
{
imageX = Mat::zeros(imageSource.size(), CV_32SC1);
imageY = Mat::zeros(imageSource.size(), CV_32SC1);
gradXY = Mat::zeros(imageSource.size(), CV_32SC1