一、环境配置

较之前采用cppan进行编译的方式,vcpkg的方式已经发生了许多变化,带来的最大不同就是便捷。

对于在NuGet中能够找到的Vcpkg的export,真的实现了开箱即用

这样的话对于普通用户来说就购了;而复杂的问题就交给专家来解决。

 二、代码编写和结果展示

// ConsoleOCRDEMO.cpp : 基于vcpkg+nuget快速解决环境配置问题
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <leptonica/allheaders.h>
#include <tesseract/baseapi.h>
#include <tesseract/publictypes.h>
using namespace cv;
using namespace cv::dnn;
using namespace std;
//对east的结果进行解码
void decode(const Mat& scores, const Mat& geometry, float scoreThresh,
    std::vector<RotatedRect>& detections, std::vector<float>& confidences)
{
    detections.clear();
    CV_Assert(scores.dims == 4); CV_Assert(geometry.dims == 4); CV_Assert(scores.size[0] == 1);
    CV_Assert(geometry.size[0] == 1); CV_Assert(scores.size[1] == 1); CV_Assert(geometry.size[1] == 5);
    CV_Assert(scores.size[2] == geometry.size[2]); CV_Assert(scores.size[3] == geometry.size[3]);
    const int height = scores.size[2];
    const int width = scores.size[3];
    for (int y = 0; y < height; ++y)
    {
        const float* scoresData = scores.ptr<float>(0, 0, y);
        const float* x0_data = geometry.ptr<float>(0, 0, y);
        const float* x1_data = geometry.ptr<float>(0, 1, y);
        const float* x2_data = geometry.ptr<float>(0, 2, y);
        const float* x3_data = geometry.ptr<float>(0, 3, y);
        const float* anglesData = geometry.ptr<float>(0, 4, y);
        for (int x = 0; x < width; ++x)
        {
            float score = scoresData[x];
            if (score < scoreThresh)
                continue;
            // Decode a prediction.
            // Multiple by 4 because feature maps are 4 time less than input image.
            float offsetX = x * 4.0f, offsetY = y * 4.0f;
            float angle = anglesData[x];
            float cosA = std::cos(angle);
            float sinA = std::sin(angle);
            float h = x0_data[x] + x2_data[x];
            float w = x1_data[x] + x3_data[x];
            Point2f offset(offsetX + cosA * x1_data[x] + sinA * x2_data[x],
                offsetY - sinA * x1_data[x] + cosA * x2_data[x]);
            Point2f p1 = Point2f(-sinA * h, -cosA * h) + offset;
            Point2f p3 = Point2f(-cosA * w, sinA * w) + offset;
            RotatedRect r(0.5f * (p1 + p3), Size2f(w, h), -angle * 180.0f / (float)CV_PI);
            detections.push_back(r);
            confidences.push_back(score);
        }
    }
}
int main()
{
    //参数和常量准备
    String model = "F:/未来项目/GOCVHelper455/GOCVHelper455/GOCVHelper455/model/frozen_east_text_detection.pb";
    std::vector<Mat> outs;
    std::vector<String> outNames(2);
    outNames[0] = "feature_fusion/Conv_7/Sigmoid";
    outNames[1] = "feature_fusion/concat_3";
    Mat  blob;
    std::vector<RotatedRect> boxes;
    std::vector<float> confidences;
    std::vector<int> indices;
    char cbuf[255];
    // 引入EAST model
    Net net = readNet(model);
    //对tesseract进行初始化操作
    tesseract::TessBaseAPI tess;
    if (tess.Init("C:/Program Files/Tesseract-OCR/tessdata", "eng"))
    {
        std::cout << "OCRTesseract: Could not initialize tesseract." << std::endl;
        return 1;
    }
    tess.SetVariable("tessedit_char_whitelist", "0123456789");
    Mat src = imread("F:/未来项目/OCR2023/2.jpg");
    Mat board = src.clone();//用于显示图片
    blobFromImage(src, blob, 1.0, Size(1280, 1280), Scalar(), true, false);//Scalar采用默认是设置
    net.setInput(blob);
    net.forward(outs, outNames);
    Mat scores = outs[0];
    Mat geometry = outs[1];
    decode(scores, geometry, 0.5, boxes, confidences);//注意0.5是超参数
    NMSBoxes(boxes, confidences, 0.5, 0.4, indices);
    Point2f ratio((float)src.cols / 1280, (float)src.rows / 1280);//缩放比例
    //获得最终框选结果
    for (size_t i = 0; i < indices.size(); ++i)
    {
        RotatedRect& box = boxes[indices[i]];
        Point2f vertices[4];
        box.points(vertices);
        for (int j = 0; j < 4; ++j)
        {
            vertices[j].x *= ratio.x;
            vertices[j].y *= ratio.y;
        }
        Point2f* lastItemPointer = (vertices + sizeof vertices / sizeof vertices[0]);
        vector<Point2f> contour(vertices, lastItemPointer);
        Rect boundRect = boundingRect(Mat(contour));
        //对rect适当进行扩充
        boundRect = cv::Rect(boundRect.tl().x - 5, boundRect.tl().y, boundRect.width + 10, boundRect.height);
        if (boundRect.y < src.rows)
        {
            Mat roi = src(boundRect);
            //绘制外接边线
            for (int j = 0; j < 4; ++j)
                line(board, vertices[j], vertices[(j + 1) % 4], Scalar(0, 255, 0), 1);
            rectangle(board, boundRect, Scalar(0, 0, 255));//绘制外接最小矩形
            //打印数据
            sprintf_s(cbuf, "F:/未来项目/OCR2023//roi/%d.jpg", i);//打印出来
            imwrite(cbuf, roi);
            ////将切割出来的图片输入tesseract中
            auto pixs = pixRead(cbuf);
            if (!pixs)
            {
                std::cout << "Cannot open input file: " << std::endl;
                return 1;
            }
            // recognize
            tess.SetImage(pixs);
            tess.Recognize(0);
            // get result and delete[] returned char* string
            std::cout << std::unique_ptr<char[]>(tess.GetUTF8Text()).get() << std::endl;
            string strOut = tess.GetUTF8Text();
            putText(board, std::unique_ptr<char[]>(tess.GetUTF8Text()).get(), boundRect.tl(), 1, 1.0f, Scalar(0, 255, 0));
            // cleanup
            tess.Clear();
            pixDestroy(&pixs);
        }
    }
    imshow("board", board);
    imwrite("F:/未来项目/OCR2023/roi/result.jpg", board);
    cv::waitKey();
    getchar();
    return 0;
}

 三、代码编写和结果展示

这种环境配置方法以数量级的方式降低了环境配置的难度,而且“正好”有这样的一个可以使用的环境。其中:。

1、VCPKG是什么

VCPKG是微软 C++ 团队开发的适用于 C 和 C++ 库的跨平台开源软件包管理器,它大大简化了 Windows、Linux 和 macOS 上第三方库相关的下载和配置操作,目前已有超过1600个第三方库可以通过vcpkg来安装。

自动下载开源库源代码。一键安装第三方库。源码包的缓存管理和版本管理,可以依需求安装指定的版本。

自动检查库的依赖关系并安装其依赖项。

无缝集成Visual Studio,不用手动设置任何的库相关的路径。

Visual Studio全平台支持,不仅支持Debug/Release、x86/x64编译,还支持UWP、ARM平台的编译。

2、nuget

Nuget是一个.NET平台下的开源的项目,它是Visual Studio的扩展。在使用Visual Studio 或.NET CLI开发基于.NET 或.NET Framework的应用时,Nuget能把在项目中添加、移除和更新引用的工作变得更加快捷方便。

3、vcpkg导出NuGet

vcpkg export --nuget [options] <package>...

在 <output-dir>/<nuget-id>.<nuget-version>.nupkg创建 NuGet 包。

包含 标准集成文件 以及其他 MSBuild 集成,以支持通过 NuGet 包管理器 (.vcxproj) 包含在 MSBuild C++ 项目中。 请注意,不能将生成的 export 多个 NuGet 包混合在一起 -- 仅使用其中一个包。 若要添加其他库,必须创建包含完整依赖项集的新导出。

Tesseract5+OpenCV4(VS2017+win10)实现OCR识别的更多相关文章

  1. Python&selenium&tesseract自动化测试随机码、验证码(Captcha)的OCR识别解决方案参考

    在自动化测试或者安全渗透测试中,Captcha验证码的问题经常困扰我们,还好现在OCR和AI逐渐发展起来,在这块解决上越来越支撑到位. 我推荐的几种方式,一种是对于简单的验证码,用开源的一些OCR图片 ...

  2. 基于百度云的OCR识别(Python)

    2019年7月3日早上,在百度AI开发者大会上,一个来自山西的青年,将一瓶矿泉水浇在了同样来自山西的李彦宏身上. 可以回顾一下 https://b23.tv/av57665929/p1 ,着实让人一惊 ...

  3. python3使用OCR识别图片

    放假三天,闲来无事,想学下python爬虫.本想跟着网上教程操作一遍,奈何安装使用过程中出现一堆问题,并且在网上搜了一堆复制黏贴的答案,关键都不能起作用,最后终于找到一篇生效,为了以后不至于再经历这种 ...

  4. Atitit  ocr识别原理 与概论 attilax总结

    Atitit  ocr识别原理 与概论 attilax总结 1.1. Ocr的过程与流程1 1.2. OCR不同技术细分略有不同,但大概原理是一样的. 即主要技术过程是:二值化(又叫归一化)----- ...

  5. 基于Python实现对PDF文件的OCR识别

    http://www.jb51.net/article/89955.htm https://pythontips.com/2016/02/25/ocr-on-pdf-files-using-pytho ...

  6. OCR识别-python版(一)

    需求:识别图片中的文字信息环境:windows系统 开发语言:python 使用工具类:1.pyocr 2.PIL 3.tesseract-ocr 步骤: 1.pyocr 网络通直接使用命令:pip ...

  7. 汽车Vin码识别——可以嵌入到手机里的新OCR识别技术

              汽车Vin码识别(车架号识别),顾名思义,就是识别汽车的Vin码(车架号),汽车Vin码识别(车架号识别)利用的是OCR识别技术,支持视频流获取图像,自动触发识别,另外汽车Vin码 ...

  8. 汽车Vin码识别—— 一款二手车行业值得拥有的OCR识别软件

    一.汽车Vin码识别产品描述 汽车Vin码识别系统,主要应用在智能手机IOS与Android两个平台中.前端扫描查询模式,无需联网,只需扫描汽车前挡风玻璃右下角的Vin码(车架号),即可轻松识别出车辆 ...

  9. 发票OCR识别/票据OCR自动识别

    对于一些大的集团公司来说,分散式财务管理模式管理效率不高,管理成本相对较高,同时也制约了集团企业发展战略的实施,因而需要建设财务共享中心.一个企业想建造财务共享中心,面临的难题是大量的数据采集和信息处 ...

  10. 采用OCR识别自动识别财务报表

    一.         财务报表有什么作用 财务报表又叫会计报表,包含:资产负债表.损益表.现金流量表三表.财务报表对企业经营状况有重要的参考意义: n  全面系统地揭示企业一定时期的财务状况.经营成果 ...

随机推荐

  1. 在Windows系统上安装和配置Jenkins自动发布

    一.安装jenkins的流程转载于: https://www.jianshu.com/p/de9c4f5ae7fa 二.在window中执行批处理文件bat或者powershell可以成功,但是Jen ...

  2. 合并B站video.m4s和audio.m4s

    ffmpeg -i D:\a\video.m4s -i D:\a\audio.m4s -codec copy D:\a\a.mp4

  3. 【RTOS】《基于嵌入式实时操作系统的程序设计技术》——任务的划分与封装

    任务的划分与封装 关键任务的划分处理 对于某些对于系统的正常运作至关重要,少执行一次会对系统产生较大影响的功能,我们倾向于将它从原有任务中剥离出来,称为关键任务,用一个独立任务或者ISR(如外部中断) ...

  4. gitee提交过程

    https://gitee.com/ 一个线上代码云端软件开发协作平台 首先注册一个账号 然后添加新的仓库 仓库名称和路径是必填项 然后创建项目 选择  克隆存储数据库 存储库位置是网站获取的git位 ...

  5. Centos7编译Nginx1.19.0笔记

    下载Nginx安装包 官网下载页:http://nginx.org/en/download.html 终端输入: # 安装依赖yum -y install wget gcc gcc-c++ autoc ...

  6. 我的第二次JAVA作业

    1. Java包含哪两大类数据类型?其中基本类型的每种类型的取值范围和默认值分别是多少?请编程验证. Java 的两大数据类型: 基本类型 引用类 基本数据类型: 整数类型: byte: byte 数 ...

  7. linux缓冲区溢出尝试

    #include <stdio.h>#include <string.h>char Lbuffer[] = "01234567890123456789======== ...

  8. docker登录mysql

    一.查看mysql是否已启动 二.登录mysql 三.假如需要重启mysql 查看docker中运行的容器docker ps,再重新启动mysql,docker restart 9299415df7f ...

  9. 汇编debug工具Dosbox使用

    汇编debug工具DOSBOX使用说明 首先新建文件,更改后缀名为asm,然后写入一段汇编程序 之后打开DosBox    输入masm + 文件名(加不加文件名后缀都可以)但如果要加的话,应该加上. ...

  10. python+selenium实现自动识别验证码并登录

    最近学习python+selenium实现网站的自动登录,但是遇到需要输入验证码的问题,经过查询百度收获了几种破解验证码的方式. 方式一)从万能的网友那收获了一个小众但非常实用的第3方库ddddocr ...