想使用cmake来组织代码工程,其中使用opencv与Qt,下面使用的CMakeLists.txt存档于此备忘。
opencv的使用例子
cmake_minimum_required(VERSION 3.15)
project(main)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
message(STATUS "编译OpenCV...")
# aux_source_directory(. SOURCES)
# add_executable(main ${SOURCES})
find_path(INCLUDES opencv2/opencv.hpp /usr/local/include/opencv4/)
message(STATUS ${INCLUDES})
find_library(LIB1 opencv_core)
find_library(LIB2 opencv_imgcodecs)
find_library(LIB3 opencv_imgproc)
find_library(LIB4 opencv_ml)
include_directories(${INCLUDES})
add_executable(main main.cpp)
target_link_libraries(main ${LIB1} ${LIB2} ${LIB3} ${LIB4})
Qt5的使用例子
cmake_minimum_required(VERSION 3.15)
project(main)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
SET(CMAKE_PREFIX_PATH /Users/yangqiang/Qt512/5.12.1/clang_64/lib/cmake)
find_package(Qt5Core REQUIRED)
FIND_PACKAGE(Qt5Widgets REQUIRED)
FIND_PACKAGE(Qt5Gui REQUIRED)
FIND_PACKAGE(Qt5Core REQUIRED)
SET(CMAKE_AUTOMOC ON)
SET(CMAKE_AUTOUIC ON)
qt5_wrap_ui(UI_FILES output.ui)
message(STATUS "编译Qt...")
aux_source_directory(. SOURCES)
add_executable(main ${SOURCES} ${UI_FILES})
include_directories(
/Users/yangqiang/Qt512/5.12.1/Src/qtbase/include
/Users/yangqiang/Qt512/5.12.1/Src/qtbase/include/QtWidgets
/Users/yangqiang/Qt512/5.12.1/Src/qtbase/include/QtCore
/Users/yangqiang/Qt512/5.12.1/Src/qtbase/include/GtGui
/Users/yangqiang/Qt512/5.12.1/Src/qtbase/include/QtWidgets
/Users/yangqiang/Qt512/5.12.1/Src/qtbase/include/QThread
)
find_library(FRAMEWORK1 QtCore /Users/yangqiang/Qt512/5.12.1/clang_64/lib)
find_library(FRAMEWORK2 QtGui /Users/yangqiang/Qt512/5.12.1/clang_64/lib)
find_library(FRAMEWORK3 QtWidgets /Users/yangqiang/Qt512/5.12.1/clang_64/lib)
target_link_libraries(main ${FRAMEWORK1} ${FRAMEWORK2} ${FRAMEWORK3})
-
项目截图
image.png
opencv代码
#include <opencv2/opencv.hpp>
#include <iostream>
void loadIrisFromTxt(cv::String filename, cv::Mat &data, cv::Mat &label){
int rows = 150;
int cols = 4;
data.create(rows, cols, CV_32FC1);
label.create(rows, 1, CV_32SC1);
// 打开文件
std::ifstream ifs(filename, std::ifstream::in);
char buf[256];
int row_id = 0;
while(! ifs.eof()){
bzero(buf, sizeof(buf));
ifs.getline(buf, sizeof(buf)-1);
std::istringstream istr(buf);
float a, b, c, d;
char buffer[256] = {0};
char _;
istr >> a >> _ >> b >> _ >> c >> _ >> d >> _ >> buffer;
cv::Mat row_one = (cv::Mat_<float>(1,4) << a, b, c, d);
row_one.copyTo(data.row(row_id));
if(strcmp(buffer, "Iris-setosa") == 0){
label.at<int>(row_id, 0) = 0;
}
else if (strcmp(buffer, "Iris-versicolor") == 0){
label.at<int>(row_id, 0) = 1;
}
else if (! strcmp(buffer, "Iris-virginica")){
label.at<int>(row_id, 0) = 2;
}
row_id ++;
}
// 关闭文件
ifs.close();
};
// 可视化分类器与数据集
void visual_classifier( cv::Mat data, // 可视化数据集,必须2两个特征
cv::Mat label, // 可视化标签,必须一个特征
cv::Mat &out, // 输出的可视化图
cv::Ptr<cv::ml::SVM> classifer = 0, // 需要可视化的分类器,可以为0
int w=512, // 默认可视化区域
int h=512){ // 默认可视化区域
// 可视化数据集与分类器,其中数据集需要方大到指定w与h,标签用来区分样本点的颜色
// out.create(h, w, CV_8UC3); // 初始化输出的图像
out = cv::Mat(h, w, CV_8UC3, cv::Scalar(255, 255, 255));
// 计算缩放比例
double scale_x, scale_y;
// 计算数据集的x,y最大最小值
double max_x, min_x;
double max_y, min_y;
cv::minMaxIdx(data.col(0), &min_x, &max_x);
cv::minMaxIdx(data.col(1), &min_y, &max_y);
// 扩边,避免点绘制在边界上
min_x -= 0.5;
max_x += 0.5;
min_y -= 0.5;
max_y += 0.5;
scale_x = w / (max_x - min_x);
scale_y = h / (max_y - min_y);
/////////////////绘制分类器的分类边界开始//////////////////
std::cout << "开始绘制分类区域!"<< std::endl;
// 定义绘制颜色
cv::Vec3b cr(0, 0, 128), cg(0, 128, 0), cb(128, 0, 0);
//对区域循环判别作为的类别
for(int y = 0; y < h; y++){
for(int x = 0; x < w; x++){
// 把x,y映射到样本区域;
// 先缩放
double a_x = x / scale_x;
double a_y = y / scale_y;
// 再平移
a_x += min_x;
a_y += min_y;
// 使用这个点预测
cv::Mat a_sample = (cv::Mat_<float>(1,2) << a_x, a_y);
double pre = classifer->predict(a_sample);
if(pre == 0) {
out.at<cv::Vec3b>(y, x) = cr;
}
else if(pre == 1 ){
out.at<cv::Vec3b>(y, x) = cg;
}else if(pre == 2 ){
out.at<cv::Vec3b>(y, x) = cb;
}
}
}
/////////////////绘制分类器的分类边界结束///////////////////
// 绘制支撑向量
/////////////////绘制支撑向量开始///////////////////
// 获取支撑向量
cv::Mat sv = classifer->getSupportVectors();
std::cout<< "支撑向量维度:" << sv.rows <<"," << sv.cols << std::endl;
for (int i = 0; i < sv.rows; i++){
const float* v = sv.ptr<float>(i);
double v_x = v[0];
double v_y = v[1];
// 平移
v_x -= min_x;
v_y -= min_y;
// 方大
v_x *= scale_x;
v_y *= scale_y;
// 绘制
circle(out, cv::Point( (int) v_x, (int) v_y), 3, cv::Scalar(255, 255, 255), 1);
}
/////////////////绘制支撑向量结束///////////////////
std::cout << "开始绘制数据集样本点!"<< std::endl;
// 定义绘制的颜色
cv::Vec3b r(0, 0, 255), g(0, 255, 0), b(255, 0, 0);
// 绘制样本点
for(int i = 0; i < data.rows; i++){
double d_x = data.at<float>(i, 0);
double d_y = data.at<float>(i, 1);
// 先平移到0点再放大
d_x -= min_x;
d_y -= min_y;
d_x *= scale_x;
d_y *= scale_y;
// 取整绘制
int lab = label.at<int>(i,0);
if(lab == 0){
circle(out, cv::Point( (int) d_x, (int) d_y ), 1, r, -1);
}
if(lab == 1){
circle(out, cv::Point( (int) d_x, (int) d_y ), 1, g, -1);
}
if(lab == 2){
circle(out, cv::Point( (int) d_x, (int) d_y ), 1, b, -1);
}
}
}
int main(int argc, const char** argv) {
cv::Mat data, label;
loadIrisFromTxt("iris.txt", data, label);
cv::Mat newData;
cv::hconcat(data.col(0), data.col(2), newData);
// 创建SVM对象
cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();
svm->setType(cv::ml::SVM::C_SVC); // 带正则化惩罚因子C的SVM
svm->setC(1000); // 设置C的值
svm->setGamma(0.001); // 设置gamma的值
svm->setKernel(cv::ml::SVM::SIGMOID); // 设置SVM的核
svm->setTermCriteria(cv::TermCriteria(cv::TermCriteria::MAX_ITER, (int)1e8, 1e-8)); // 设置训练终止条件
// 训练终止条件
svm->setTermCriteria(cv::TermCriteria(cv::TermCriteria(cv::TermCriteria::MAX_ITER, (int)1e8, 1e-8)));
// 开始训练
svm->train(newData,cv::ml::ROW_SAMPLE,label);
// 使用训练集预测
cv::Mat predict;
svm->predict(newData, predict); // 第三个参数取默认值,预测返回的结果是CV_32F类型
predict.convertTo(predict, CV_32SC1); // 需要转换为一致才能比较
// 统计准确率
cv::Mat result;
cv::compare(label, predict, result, cv::CMP_EQ); // 比较结果, 相等true,则设置为255,false设置为0
cv::Scalar mean = cv::mean(result / 255.0);
std::cout<<"识别准确率:";
std::cout << std::fixed << std::setprecision(2) << mean[0] * 100.0 <<"%"<< std::endl;
cv::Mat img;
visual_classifier(newData, label, img, svm);
imwrite("visual.png", img);
return 0;
}
-
输出图片
SVM对鸢尾花的分类可视化
网友评论