OpenCV 4.5.1
C++20
Ubuntu 20.04 (示例程序代码有用到Linux系统调用,不可直接适用于其它系统)
组态档
CMakeLists.txt
# 设置用于构建该项目的最低cmake版本
cmake_minimum_required(VERSION 3.1)
# 设置项目名称和编程语言
project(opencv_demo CXX)
# 寻找opencv的头文件和库文件
find_package(OpenCV REQUIRED)
# opencv头文件路径
include_directories(${OpenCV_INCLUDE_DIRS})
# opencv库路径
link_directories(${OpenCV_LIBRARY_DIRS})
# 自定义头文件路径
include_directories(include)
# 设置二进制文件生成路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
# 获取源码的路径
aux_source_directory(src src)
# 设置编译标准和额外参数
add_compile_options(-std=c++20 -Wall -Werror -Wextra -pedantic -Wimplicit-fallthrough -Wsequence-point -Wswitch-default -Wswitch-unreachable -Wswitch-enum -Wstringop-truncation -Wbool-compare -Wtautological-compare -Wfloat-equal -Wshadow=global -Wpointer-arith -Wpointer-compare -Wcast-align -Wcast-qual -Wwrite-strings -Wdangling-else -Wlogical-op -Wconversion -Wno-pedantic-ms-format)
# 从源码构建二进制文件
add_executable(demo ${src})
# 链接opencv库到二进制文件
target_link_libraries(demo ${OpenCV_LIBRARIES})
素材
用于训练的素材 digits.png
(右键另存为图片,必须按要求命名文件,下同)
用于测试的素材
1.png
2.png
项目结构
蓝色的是文件夹
源码
knn.cpp
/**
* @file knn.cpp
* @author IYATT-yx 2514374431@qq.com
* @date 2021-3-13
* @brief 基于K近邻算法的手写数字识别 (OpenCV 4.5.1)
*/
#include <iostream>
#include <string>
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/ml.hpp"
#include "opencv2/imgproc.hpp"
extern "C"
{
#include <unistd.h>
}
void trainModel()
{
// 素材图片和运行程序的路径要一样 - 按灰度图读取
cv::Mat src = cv::imread("./resources/digits.png", cv::IMREAD_GRAYSCALE);
if (src.empty())
{
std::cout << "请检查素材 ./resources/digits.png 是否存在" << std::endl;
exit(EXIT_FAILURE);
}
// 创建盛放图像的矩阵 - 每个手写数字占1行20x20个元素,共5000行
cv::Mat images = cv::Mat::zeros(5000, 400, CV_8UC1);
// 每个手写数字对应的标签
cv::Mat labels = cv::Mat::zeros(5000, 1, CV_8UC1);
int index = 0;
// ROI
cv::Rect numberImg;
n