opencv3/C++ 机器学习-最邻近算法KNN识别字符

2023-11-15

如图,有如下字母表;
这里写图片描述
现尝试采用最邻近算法KNN,取前10列字符作为训练数据,然后识别字母表中的字符。

创建训练数据

首先通过获取前10列字符的轮廓外接矩形,将字符裁剪出作为训练样本建立图库。

#include <string>
#include <iostream>
#include <opencv2\opencv.hpp>
#include<numeric>
using namespace cv;


int main()
{
    Mat src, dst;
    src = imread("E:/image/image/letters.png");
    if (src.empty())
    {
        std::cout<<"can not load image \n"<<std::endl;
        return -1;
    }
    imshow("input", src);
    dst = src.clone();
    cvtColor(src, src, COLOR_BGR2GRAY); 
    Mat bin = src.clone();
    //创建感兴趣区域,选取左侧10列作为训练数据
    Mat ROI = src(Rect(0,0,400,src.size().height));
    blur(ROI, ROI, Size(9,9));
    threshold(ROI, ROI, 210, 255, THRESH_BINARY);
    Canny(ROI, ROI, 20, 80, 3, false);
    std::vector<std::vector<Point>> contours;
    std::vector<Vec4i>hierarchy;
    findContours(ROI, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0,0));
    RNG rng(0);
    std::vector<RotatedRect> minRects(contours.size());
    std::vector<float> height, width;
    for (int i = 0; i < contours.size(); i++)
    {
        Scalar color = Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255));
        Rect rect = boundingRect(contours[i]);
        height.push_back(rect.height);
        width.push_back(rect.width);
    }
    //获取字符外接矩形宽高的最大值
    std::vector<float>::iterator h = std::max_element(std::begin(height), std::end(height));
    std::vector<float>::iterator w = std::max_element(std::begin(width), std::end(width));
    //获得轮廓的外接矩形
    std::vector<Rect>rects;
    //将轮廓外接矩形按纵坐标排序
    std::vector<float>sequence;
    for (int i = 0; i < contours.size(); i++)
    {
        Scalar color = Scalar(0, rng.uniform(0,255), rng.uniform(0,255));
        Rect rect = boundingRect(contours[i]);
        Rect reRect = Rect(Point(rect.x + rect.width/2.0 - *w/2.0,rect.y + rect.height/2.0 - *h/2.0 + 2), Point(rect.x + rect.width/2.0 + *w/2.0, rect.y + rect.height/2.0 + *h/2.0 - 2));
        rectangle(dst, reRect, color, 2);   
        rects.push_back(reRect);
        sequence.push_back(reRect.y);
    }
    //按纵坐标排序
    sort(sequence.begin(), sequence.end());

    threshold(bin, bin, 0, 255, CV_THRESH_BINARY|CV_THRESH_OTSU);
    int n = 0;
    for (int i = 0; i < rects.size(); i++)
    {
        for (int j = 0; j < 26; j++)
        {
            std::string outPath = "E:/image/letters/";
            char label = 'a';
            char temp[256];
            if ((rects[i].y > sequence[j*10]-*h/2.0) && (rects[i].y < sequence[j*10]+*h/2.0))
            {
                label = label + j;
                sprintf_s(temp, "%d", n);
                outPath = outPath + label + "/" + temp + ".jpg";
                //std::cout<<outPath<<std::endl;
                imwrite(outPath,bin(rects[i]));
                n++;
            }
        }
    }

    imshow("output", dst);
    waitKey();

    return 0;
}

被选中的字符:
这里写图片描述
裁剪后得到的图库:
这里写图片描述

利用KNN识别字符

利用KNN识别出图中的字符,并将识别结果显示在图中对应的字符旁边。(同种字符用同一种颜色显示)

#include <io.h>
#include <string>
#include <iostream>
#include <opencv2\opencv.hpp>
#include <opencv2\ml.hpp>
#include<numeric>
using namespace cv;
using namespace ml;

int main()
{
    ===============================读取训练数据===============================
    //图片共有10类
    const int classSum = 26;
    //每类共50张图片
    const int imagesSum = 10;
    //图片尺寸
    const int imageRows = 33;
    const int imageCols = 26;
    //每一行一个训练图片
    float trainingData[classSum*imagesSum][imageRows*imageCols] = {{0}};
    //训练样本标签
    float labels[classSum*imagesSum]={0};

    for (int i = 0; i < classSum; i++)
    {
        //目标文件夹路径
        std::string inPath = "E:\\image\\letters\\";
        char label = 'a';
        int k = 0;
        label = label + i;
        inPath = inPath + label + "\\*.jpg";
        //用于查找的句柄
        long handle;
        struct _finddata_t fileinfo;
        //第一次查找
        handle = _findfirst(inPath.c_str(),&fileinfo);
        if(handle == -1)
            return -1;
        do
        {
            //找到的文件的文件名
            std::string imgname = "E:/image/letters/";
            imgname = imgname + label + "/" + fileinfo.name;
            //std::cout<<imgname<<std::endl;
            Mat src = imread(imgname, 0);
            if (src.empty())
            {
                std::cout<<"can not load image \n"<<std::endl;
                return -1;
            }
            //序列化后放入作为样本矩阵的一行
            for(int j = 0; j<imageRows*imageCols; j++)
            {
                trainingData[i*imagesSum + k][j] = (float)src.data[j];
            }
            // 设置样本标签
            labels[i*imagesSum + k] = label;
            k++;

        } while (!_findnext(handle, &fileinfo));
        _findclose(handle);
    }
    //训练样本数据及对应标签
    Mat trainingDataMat(classSum*imagesSum, imageRows*imageCols, CV_32FC1, trainingData);
    Mat labelsMat(classSum*imagesSum, 1, CV_32FC1, labels);
    //std::cout<<trainingDataMat<<std::endl;
    //std::cout<<labelsMat<<std::endl;

    ===============================创建KNN模型===============================
    Ptr<KNearest>model = KNearest::create();
    model->setDefaultK(classSum);
    model->setIsClassifier(true);
    Ptr<TrainData>trainData = TrainData::create(trainingDataMat, ROW_SAMPLE, labelsMat);
    model->train(trainData);

    //model->save("E:/image/KNearestModel.xml"); 
    ===============================预测部分===============================

    Mat src, dst;
    src = imread("E:/image/image/letters.png");
    if (src.empty())
    {
        std::cout<<"can not load image \n"<<std::endl;
        return -1;
    }
    dst = src.clone();
    //创建感兴趣区域,选取右侧10列作为预测数据
    cvtColor(src, src, COLOR_BGR2GRAY);

    blur(src, src, Size(9,9));
    threshold(src, src, 210, 255, THRESH_BINARY);
    Canny(src, src, 20, 80, 3, false);
    std::vector<std::vector<Point>> contours;
    std::vector<Vec4i>hierarchy;
    findContours(src, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0,0));

    for (int i = 0; i < contours.size(); i++)
    {
        Rect rect = boundingRect(contours[i]);
        //以矩形中心及指定的宽高作为字符区域
        Rect reRect = Rect(Point(rect.x + rect.width/2.0 - imageCols/2.0,rect.y + rect.height/2.0 - imageRows/2.0), Point(rect.x + rect.width/2.0 + imageCols/2.0, rect.y + rect.height/2.0 + imageRows/2.0));
        Mat sampleImg;
        cvtColor(dst, sampleImg, COLOR_BGR2GRAY);
        threshold(sampleImg, sampleImg, 0, 255, CV_THRESH_BINARY|CV_THRESH_OTSU);
        Mat sample = Mat::zeros(Size(imageCols,imageRows), sampleImg.type());

        float sampleData[imageRows*imageCols];
        int nub = 0;
        for (int r = 0; r < imageRows; r++)
        {
            for (int c = 0; c < imageCols; c++)
            {
                sampleData[nub] = sampleImg.at<uchar>(reRect.y+r,reRect.x+c);
                nub++;
            }
        }

        Mat sampleDataMat(1, imageRows*imageCols, CV_32FC1, sampleData);
        char f;
        f = model->predict(sampleDataMat);
        char temp[256];
        sprintf_s(temp, "%c", f);
        std::cout<<temp<<"\n"<<std::endl;
        std::string text(temp);
        RNG rng(f);
        Scalar color = Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255));
        putText(dst, text, Point(reRect.x,reRect.y + reRect.height),1,1.5,color,2);
    }
    imshow("output",dst);
    waitKey();
    return 0;
}

显示识别结果:

这里写图片描述


相关链接:

图片及代码下载

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

opencv3/C++ 机器学习-最邻近算法KNN识别字符 的相关文章

  • 来自 OpenCV 的外部参数

    我正在使用 OpenCV 来校准立体相机对 我拍摄了各种校准照片 并且使用 cv2 calibrateCamera 对内在参数进行了令人满意的拟合 然而 目前尚不清楚如何获取外部参数 该函数仅返回cameraMatrix 尽管它很有用 但实
  • 如何设置K-means openCV c++的初始中心

    我正在尝试使用 OpenCv 和 Kmeans 对图像进行分割 我刚刚实现的代码如下 include opencv2 objdetect objdetect hpp include opencv2 highgui highgui hpp i
  • OpenCV的拼接模块可以拼接平行运动相机拍摄的图像吗?

    我想知道是否缝合 http docs opencv org modules stitching doc stitching html http docs opencv org modules stitching doc stitching
  • 在加载“cv2”二进制扩展期间检测到递归

    我有一个小程序 在 pyinstaller 编译后返回 opencv 错误 但无需编译即可工作 我在 Windows 10 上使用 Python 3 8 10 Program 导入 pyautogui将 numpy 导入为 np导入CV2
  • 在 QtCreator 中将 OpenCV 2.3 与 Qt 结合使用

    随着 OpenCV 2 3 版本终于发布 我想在我的系统上编译并安装这个最新版本 由于我经常使用 Qt 和 QtCreator 我当然希望能够在我的 Qt 项目中使用它 我已经尝试了几种方法几个小时 但总是出现错误 第一次尝试 使用WITH
  • OpenCV 错误:使用 COLOR_BGR2GRAY 函数时断言失败

    我在使用 opencv 时遇到了一个奇怪的问题 我在 jupyter 笔记本中工作时没有任何问题 但在尝试运行此 Sublime 时却出现问题 错误是 OpenCV错误 cvtColor中断言失败 深度 CV 8U 深度 CV 16U 深度
  • 曲线/路径骨架二值图像处理

    我正在尝试开发一个可以处理图像骨架的路径 曲线的代码 我想要一个来自两点之间骨架的点向量 该代码在添加一些点后结束 我没有找到解决方案 include opencv2 highgui highgui hpp include opencv2
  • 多视图几何

    我从相距一定距离的两台相同品牌的相机捕获了两张图像 捕获了相同的场景 我想计算两个相机之间的现实世界旋转和平移 为了实现这一点 我首先提取了两张图像的 SIFT 特征并进行匹配 我现在有基本矩阵也单应性矩阵 然而无法进一步进行 有很多混乱
  • OpenCV Visual Studio ntdll.dll

    我尝试在 Visual Studio 2013 上使用 OpenCV 2 4 10 创建一个项目 但由于以下异常 到目前为止我运气不佳 请建议帮助 TIA letstryitonemoretime exe Win32 Loaded C Us
  • OpenCV 2.3 与 VS 2008 - 鼠标事件

    强制性 我是新手 有一份涉及编程的工作 并且我一边工作一边自学 不用说 作为一名老师 我经常犯彻底的错误 我现在所处的位置 我创建了 Graph 类 它 令人惊讶的是 制作了图表 但现在我想通过单击鼠标来修改图形 但我似乎无法让鼠标处理程序
  • 仅获取图像中的外部轮廓

    我有这段代码 可以在图像中绘制轮廓 但我只需要外部轮廓 import cv2 import numpy as np camino C Users Usuario Documents Deteccion de Objetos 123 jpg
  • 为什么我无法在 Mac 12.0.1 (Monterey) 上使用 pip 安装 OpenCV? [复制]

    这个问题在这里已经有答案了 当我尝试使用 python pip 安装 OpenCV 时 它显示了以下内容 Remainder of file ignored Requirement already satisfied pip in Libr
  • 如何使用 Python 裁剪图像中的矩形

    谁能给我关于如何裁剪两个矩形框并保存它的建议 我已经尝试过这段代码 但效果不佳 import cv2 import numpy as np Run the code with the image name keep pressing spa
  • 如何确定与视频中物体的距离?

    我有一个从行驶中的车辆前面录制的视频文件 我将使用 OpenCV 进行对象检测和识别 但我停留在一方面 如何确定距已识别物体的距离 我可以知道我当前的速度和现实世界的 GPS 位置 但仅此而已 我无法对我正在跟踪的对象做出任何假设 我计划用
  • 2d 图像点和 3d 网格之间的交点

    Given 网格 源相机 我有内在和外在参数 图像坐标 2d Output 3D 点 是从相机中心发出的光线穿过图像平面上的 2d 点与网格的交点 我试图找到网格上的 3d 点 This is the process From Multip
  • 是否可以在 PyScript 中使用 OpenCV 模块?

    我想使用 opencv 模块 但无法导入 OpenCV 那么我该如何解决这个问题呢 顺便说一句 Pyodide 支持 OpenCV 示例代码 https i stack imgur com ahwex jpg 尚不支持 OpenCV 此时O
  • VideoCapture.read() 返回过去的图像

    我在跑python3 6 with openCV on the Raspberry pi OS is Raspbian 代码的大致结构如下 The image以时间间隔 3 5 分钟 捕获 被捕获image在函数中处理并返回度量 精度的种类
  • 图像梯度角计算

    我实际上是按照论文的说明进行操作的 输入应该是二进制 边缘 图像 输出应该是一个新图像 并根据论文中的说明进行了修改 我对指令的理解是 获取边缘图像的梯度图像并对其进行修改 并使用修改后的梯度创建一个新图像 因此 在 MATLAB Open
  • Python:Urllib2 和 OpenCV

    我有一个程序 可以将图像保存在本地目录中 然后从该目录中读取图像 但我不想保存图像 我想直接从url读取它 这是我的代码 import cv2 cv as cv import urllib2 url http cache2 allposte
  • 将 OpenCV Mat 转换为数组(可能是 NSArray)

    我的 C C 技能很生疏 OpenCV 的文档也相当晦涩难懂 有没有办法获得cv Mat data属性转换为数组 NSArray 我想将其序列化为 JSON 我知道我可以使用 FileStorage 实用程序转换为 YAML XML 但这不

随机推荐

  • mkdocs

    mkdocs简单使用 官网 一 安装 查看 python 版本 python version Python 2 7 2 查看 pip 版本 pip version pip 1 5 2 更新 pip pip install upgrade p
  • ubuntu 安装rtorrent 下载

    apt get install rtorrent 在根目录下 建立 rtorrent rc 最小允许peer数 min peers 3 最大允许peer数 max peers 500 最大同时上传用户数 max uploads 10 最大下
  • 数据结构7/23—链表实现简单的学生信息管理系统

    目录 定义结构体存储学生信息 姓名 成绩 功能实现 各种功能函数如下 菜单函数 创建链表函数 判断是否为空的判空函数 插入函数 头插方式实现 遍历链表函数 排序输出 升序 输出最高分学生信息 以名字查找该学生的前驱节点 通过名字删除学生信息
  • Flutter Cocoon 已达到 SLSA 2 级标准的要求

    文 Jesse Seales Dart 和 Flutter 安全工作组工程师 今年年初 我们发布了 Flutter 2022 产品路线图 其中 基础设施建设 这部分提到 2022 年 Flutter 团队将增加对供应链的安全的投入 目的是达
  • PHP启动warning:PHP Startup: Unable to load dynamic library 'curl.so'

    高通ar9531上面 openwrt1806这个版本 通过opkg安装了官方的php及其扩展 但新的板子php启动的时候报了warning 没有太仔细看 但是后面运行cgi程序时 发现了问题 回头看warning日志 PHP Warning
  • Android Socket 简单介绍

    文章目录 前言 一 Socket是什么 百度百科的解释 我自己的理解 二 简单示例 1 服务端 2 客户端 3 布局 4 实现 参考 总结 前言 最近需求需要使用Socket进行通讯 我在工作后的安卓开发中没有接触过 所以有了这篇文章 写的
  • 《每日一题》NO.41:FPGA内部资源有哪些?

    芯司机 每日一题 会每天更新一道IC面试笔试题 其中有些题目已经被很多企业参考采用了哦 聪明的你快来挑战一下吧 今天是第41题 FPGA设计工程师也是一个比较热门的职位 FPGA中都包括哪些资源呢 今天的题就是这样啦 开始解题吧 公布答案
  • 内窥镜胶囊(胶囊内镜)硬件方案

    内窥镜胶囊 胶囊内镜 胶囊内窥镜 硬件方案 前言 说明 该方案为作者2018年上半年完成的第一版 后来搁置了一段时间 才重启这个项目 目前 2020 07 第二版已经快要完成 联系v 1 7 6 3 3 3 5 0 8 7 0 先给一下第一
  • Visual Studio Code结合Git与GitHub的完整步骤

    一 Visual Studio Code安装 官网下载地址 https code visualstudio com Visual Studio Code是一个精简版的迷你Visual Studio 并且可以跨平台 Windows Mac L
  • centos7.6安装mysql

    卸载mariadb 解决安装mysql与mariadb冲突问题 卸载干净mariadb 何妨徐行的博客 CSDN博客 安装rpm包前可能需要的命令 yum install openssl devel用于管理rpm包的工具 yum insta
  • 雪崩 计算机组成原理,计算机组成原理复习资料(学习课件整理版可自学使用).doc...

    一 本课程在计算机系统中的位置 一 课程目标 1 结构与原理掌握 建立计算机系统的整机概念 掌握计算机各部件的组成原理与技术 了解计算机系统组成与结构的新技术 2 分析与计算能力 掌握对组成与结构进行性能分析的方法 通过量化计算 加深对组成
  • 李沐动手学深度学习V2-目标检测SSD

    一 目标检测SSD 单发多框检测 1 介绍 SSD模型主要由基础网络组成 其后是几个多尺度特征块 基本网络用于从输入图像中提取特征 因此它可以使用深度卷积神经网络 单发多框检测论文中选用了在分类层之前截断的VGG 现在也常用ResNet替代
  • css中hover变大效果

    html代码 div img src img 11 jpg alt div css代码
  • 轻试Nginx的负载均衡

    看到网上的负载均衡 一直都没有怎么看过 也不理解 今天从网上学着点在windows下用Nginx来试试 我的os是windows xp 用的web服务器时IIS5 1 用了两台同在一个局域网的电脑 分别装有IIS 作为web服务器 地址为1
  • Linux如何查找杀死僵死进程

    最近工作过程中 发现好几台服务器出现僵死进程 如图 用下面的命令找出僵死进程 ps A o stat ppid pid cmd grep e Zz 命令注解 A 参数列出所有进程 o 自定义输出字段 我们设定显示字段为 stat 状态 pp
  • 数组随机排序的两种实现方法

    1 利用数组中的sort 方法 arr arr sort gt Math random 0 5 2 Fisher Yates Shuffle 复杂度为O n 从后向前遍历 不断将当前元素与随机位置的元素 除去已遍历的部分 进行交换 func
  • 海尔对话 Unity:作为数字转型的高阶形态,数字孪生发展前景不可逆

    来源 数字化企业 作为信息化发展到一定程度的必然结果 数字孪生正成为人类解构 描述和认识真实世界和虚拟世界的新型工具 从发展态势来看 数字孪生不仅是全新信息技术发展的新焦点 也是各国实现数字化转型的新抓手 还是众多工业企业业务布局的新方向
  • 第4章 微服务框架主体搭建

    mini商城第4章 微服务框架主体搭建 一 课题 框架搭建 二 回顾 1 整体业务功能分析 2 根据业务需求设计表结构及字段 三 目标 1 版本控制器的搭建使用 2 能独立自主的搭建微服务框架 3 学会考虑一些公共的工具组件 4 网关模块的
  • 树莓派初始使用相关问题及解决方法

    1 SSH连接 网线连接电脑 在无线图标上右键 打开 网络和internet设置 更改适配器设置 在WLAN上面右键 选择属性 共享 勾上 在cmd里面 可以输入 ping raspberrypi local 若显示不是ip 则ping 4
  • opencv3/C++ 机器学习-最邻近算法KNN识别字符

    如图 有如下字母表 现尝试采用最邻近算法KNN 取前10列字符作为训练数据 然后识别字母表中的字符 创建训练数据 首先通过获取前10列字符的轮廓外接矩形 将字符裁剪出作为训练样本建立图库 include