opencv数字识别(python/c++)

这篇具有很好参考价值的文章主要介绍了opencv数字识别(python/c++)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

使用轮廓模板匹配进行简单数字识别

大体思想就是准备好一个数字模板,查找到每个数字的轮廓后通过每个轮廓x坐标值来确保模板轮廓与数字相对应,测试图片同理,循环匹配来获得识别结果

因为模板与测试图片都是白底黑字只包含数字,所以没有过多图像处理,如果测试图片较复杂,需考虑先将待识别区域分隔开,此处不做过多介绍文章来源地址https://www.toymoban.com/news/detail-813559.html

python代码

import cv2
import os
import numpy as np
from PIL import Image

def sort_contours(cnts):  # 排序
    boundingBoxes =[cv2.boundingRect(c) for c in cnts]
    (cnts,boundingBoxes) = zip(*sorted(zip(cnts,boundingBoxes),key=lambda b: b[1][i],reverse=False))
    return cnts

# 模板
tempimg = cv2.imread('./numbertemp.png')
refimg = cv2.cvtColor(tempimg, cv2.COLOR_BGR2GRAY)
refimg = cv2.threshold(refimg, 10, 255, cv2.THRESH_OTSU)[1]
refimg = cv2.bitwise_not(refimg)
contours, hierarchy = cv2.findContours(refimg.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# cv2.drawContours(tempimg, contours, -1, (0, 0, 255), 3)
# cv2.imshow('tempimg', tempimg)
# cv2.waitKey(0)
contours = sort_contours(contours)
digits = {}  #模板
for (i, c) in enumerate(contours):
    (x, y, w, h) = cv2.boundingRect(c)
    roi = refimg[y:y + h, x:x + w]
    roi = cv2.resize(roi,(57,88))
    # cv2.imshow('temproi', roi)
    # cv2.waitKey(0)
    digits[i] = roi  # 对应模板


# 测试
testimg = cv2.imread('./test2.jpg')
trefimg = cv2.cvtColor(testimg, cv2.COLOR_BGR2GRAY)
trefimg = cv2.threshold(trefimg, 10, 255, cv2.THRESH_OTSU)[1]
trefimg = cv2.bitwise_not(trefimg)
testcontours, testhierarchy = cv2.findContours(trefimg.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# cv2.drawContours(testimg, testcontours, -1, (0, 0, 255), 3)
# cv2.imshow('testimg', testimg)
# cv2.waitKey(0)
testcontours = sort_contours(testcontours)
groupOutput = []
for c in testcontours:
    (x, y, w, h) = cv2.boundingRect(c)
    roi = trefimg[y:y + h, x:x + w]

	# 判断是否为‘-’或‘.’
    # 统计白色像素点的个数
    white_pixels = np.count_nonzero(roi == 255)
    # 计算白色区域的占比
    white_ratio = white_pixels / (roi.shape[0] * roi.shape[1])
    if white_ratio > 0.8:
            if roi.shape[1]/roi.shape[0] >= 2:
                groupOutput.append('-')
            else:
                groupOutput.append('.')
            continue

    roi = cv2.resize(roi,(57,88))
    scores = []
    for (digit, digitROI) in digits.items():
        result = cv2.matchTemplate(roi, digitROI, cv2.TM_CCOEFF)
        (_, score, _, _) = cv2.minMaxLoc(result)
        scores.append(score)
    groupOutput.append(str(np.argmax(scores)))  # 得到数字

# 输出结果
s = ''.join(groupOutput)  # 将列表拼接为字符串
result = float(s)
formatted_result = format(result, '.3f')  # 格式化结果,保留三位小数
print(formatted_result)

C++代码

///Test 轮廓排序
std::vector<std::vector<Point>> sortContours(std::vector<std::vector<Point>> cnts)
{
    std::vector<cv::Rect> boundingBoxes;
    for (const auto c : cnts)
    {
        boundingBoxes.push_back(cv::boundingRect(c));
    }
    std::sort(
            std::begin(cnts),
            std::end(cnts),
            [boundingBoxes, cnts](const std::vector<cv::Point> a, const std::vector<cv::Point> b) {
                return boundingBoxes[std::distance(std::begin(cnts), std::find(std::begin(cnts), std::end(cnts), a))].x <
                       boundingBoxes[std::distance(std::begin(cnts), std::find(std::begin(cnts), std::end(cnts), b))].x;
            }
    );
    return cnts;
}


///Test 数字识别
float OpenCVDataUtils::digitalrecognition(cv::Mat imgIn)
{
	// 模板
    cv::Mat tempimg = cv::imread("/home/numbertemp.png");
    cv::Mat refimg;
    cv::cvtColor(tempimg, refimg, cv::COLOR_BGR2GRAY);
    cv::threshold(refimg, refimg, 10, 255, cv::THRESH_OTSU);
    bitwise_not(refimg, refimg);
    std::vector<std::vector<Point>> tempcontours; //轮廓列表
    cv::findContours(refimg, tempcontours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
    std::vector<std::vector<Point>> sortedContours = sortContours(tempcontours);
    std::map<int, cv::Mat> digits;
    for (uint i = 0; i < sortedContours.size(); i++)
    {
        cv::Rect rect = cv::boundingRect(sortedContours[i]);
        int x = rect.x;
        int y = rect.y;
        int w = rect.width;
        int h = rect.height;
        cv::Mat roi = refimg(cv::Rect(x, y, w, h));
        cv::resize(roi, roi, cv::Size(57, 88)); // 调整大小
        digits[i] = roi;
    }

	// 测试
    cv::Mat trefimg;
    cv::cvtColor(imgIn, trefimg, cv::COLOR_BGR2GRAY);
    cv::threshold(trefimg, trefimg, 10, 255, cv::THRESH_OTSU);
    bitwise_not(trefimg, trefimg);
    std::vector<std::vector<Point>> tcontours; //轮廓列表
    cv::findContours(trefimg, tcontours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
    std::vector<std::vector<Point>> tsortedContours = sortContours(tcontours);
    std::vector<std::string> groupOutput;
    for (const auto c : tsortedContours) {
        cv::Rect rect = cv::boundingRect(c);
        int x = rect.x;
        int y = rect.y;
        int w = rect.width;
        int h = rect.height;
        cv::Mat roi = trefimg(cv::Rect(x, y, w, h));
        int whitePixels = cv::countNonZero(roi == 255);
        double whiteRatio = static_cast<double>(whitePixels) / (roi.rows * roi.cols);
        if (whiteRatio > 0.8) {
            if (static_cast<double>(roi.cols) / roi.rows >= 2) {
                groupOutput.push_back("-");
            } else {
                groupOutput.push_back(".");
            }
            continue;
        }
        cv::resize(roi, roi, cv::Size(57, 88));
        std::vector<double> scores;
        for (const auto digit : digits) {
            cv::Mat digitROI = digit.second;
            cv::Mat result;
            cv::matchTemplate(roi, digitROI, result, cv::TM_CCOEFF);
            cv::Point minLoc, maxLoc;
            double score;
            cv::minMaxLoc(result, nullptr, &score, nullptr, &maxLoc);
            scores.push_back(score);
        }
        int maxIndex = std::distance(scores.begin(), std::max_element(scores.begin(), scores.end()));
        groupOutput.push_back(std::to_string(maxIndex));
    }
    // 将向量拼接为字符串
    std::string s;
    for (const auto str : groupOutput) {
       s += str;
    }
     qDebug() << QString::fromStdString(s);
    // 将字符串转换为浮点数
    float result = std::stof(s);
    return result;
}

到了这里,关于opencv数字识别(python/c++)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Opencv实战——数字识别

    经过一段时间的python-opencv的学习,对opencv在图像处理方面的一些基本用法,既然学了,那就应该学以致用,就像着用现在学到的知识去实战一下,在网上看到了用opencv去实现银行卡的号码识别,但是因为讲解过于简略,所以就仿照着号码识别的基本思路一步一步的实现数字识

    2024年02月15日
    浏览(77)
  • OpenCV实例(四)手写数字识别

    作者:Xiou 使用模板匹配的方式实现手写数字识别,其基本实现原理如图所示。 使用模板匹配的方式实现手写数字识别,主要包含流程如下。 Step 1:数据准备。读取待识别图像和模板库。 Step 2:计算匹配值。计算待识别图像与所有模板的匹配值。需要注意的是,匹配值的计

    2024年02月05日
    浏览(29)
  • opencv-进阶05 手写数字识别原理及示例

    前面我们仅仅取了两个特征维度进行说明。在实际应用中,可能存在着更多特征维度需要计算。 下面以手写数字识别为例进行简单的介绍。 假设我们要让程序识别图 20-2 中上方的数字(当然,你一眼就知道是“8”,但是现在要让计算机识别出来)。识别的方式是,依次计算

    2024年02月12日
    浏览(40)
  • opencv+CNN算法实现实时数字识别(完整教程)

     完整代码在文末。 数字识别是计算机视觉领域中的一个重要任务,它涉及将输入的手写数字图像分类为特定的数字。实时数字识别具有广泛的应用,包括手写数字识别、自动识别信用卡号码等。本教程将介绍如何使用 OpenCV(Open Source Computer Vision Library)和卷积神经网络(

    2024年04月28日
    浏览(32)
  • opencv-信用卡数字识别-模板匹配ocr

    2024年02月11日
    浏览(47)
  • 实战 | 使用CNN和OpenCV实现数字识别项目(步骤 + 源码)

    导  读     本文主要介绍使用CNN和OpenCV实现数字识别项目,含详细步骤和源码。     前 言     在当今世界,深度学习和图像处理技术正在各个应用领域得到利用。在这篇博文中,我们将使用卷积神经网络 (CNN) 和 OpenCV 库完成数字识别项目。我们将逐步掌握该项目如何执

    2024年02月20日
    浏览(46)
  • opencv进阶06-基于K邻近算法识别手写数字示例

    在 OpenCV 中,不需要自己编写复杂的函数实现 K 近邻算法,直接调用其自带的模块函数即可。本节通过一个简单的例子介绍如何使用 OpenCV 自带的 K 近邻模块。 本例中有两组位于不同位置的用于训练的数据集,如图 20-14 所示。两组数据集中,一组位于左下角;另一组位于右上

    2024年02月12日
    浏览(34)
  • 深度学习图像处理基础工具——opencv 实战信用卡数字识别

    任务 信用卡数字识别 穿插之前学的知识点  形态学操作 模板匹配 等 总体流程与方法 1.有一个模板 2 用轮廓检测把模板中数字拿出来 外接矩形(模板和输入图像的大小要一致 )3 一系列预处理操作 问题的解决思路 1.分析准备:准备模板,读取文件——转化为灰度图——转化

    2024年04月15日
    浏览(55)
  • 图像识别技术OpenCV | C++版本

    图像与信号 图像 图像是人对视觉感知的物质再现。图像可以由光学设备获取,也可以人为创作。随着数字采集技术和信号处理理论的发展,越来越多的图像以数字形式存储。因而,有些情况下”图像“一词实际上是指数字图像。图像相关的话题包括图像采集、图像制作、图

    2024年02月05日
    浏览(36)
  • opencv实现人脸识别(c++实现)

    本文章基于opencv + VS2015 实现人脸检测 可以直接打开摄像头对人脸进行识别,这些标识框也会跟随你的人脸移动。隐私问题,我这里对图片进行了识别。 opencv中文文档 官方文档说明 功能 :用于从视频文件、图像序列或摄像机捕获视频的类 3.1.1 open bool cv::VideoCapture::open(int i

    2024年02月07日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包