Tesseract-OCR 3.04在Windows7 vs2013上编译过程
从https://github.com/tesseract-ocr/tesseract下载最新源码,commit id: 86acff5, 2016.06.07. 里面有个vs2010目录,用vs2013打开tesseract.sln。Tesseract依赖图像库Leptonica,Leptonica的编译过程可以参考http://blog.csdn.net/fengbingchun/article/details/44275233,它的源码在https://github.com/fengbingchun/Liblept_Test,将Leptonica静态库及头文件加入到libtesseract304工程属性配置中。修改tesseract中equationdetect.cpp文件,将
static const STRING kCharsToEx[] = {"'", "`", "\"", "\\", ",", ".","〈", "〉", "《", "》", "」", "「", ""};
修改为
static const STRING kCharsToEx[] = { "'", "`", "\"", "\\", ",", ".","<", ">", "<<", ">>", "" };
分别在LIB_Debug和LIB_Release下编译libtesseract304工程,便能生成tesseract静态库。仿照libtesseract304工程,编译tesseract工程,将静态库zlib、tiff、lept和tesseract加入到工程属性中即可。
新建Tesseract-OCR_Test控制台工程,将相应头文件和静态库加入到此工程中,测试代码来自于src/api/tesseractmain.cpp,如下:
#include <iostream>#include "allheaders.h"
#include "baseapi.h"
#include "basedir.h"
#include "renderer.h"
#include "strngs.h"
#include "tprintf.h"
#include "openclwrapper.h"
#include "osdetect.h"void PrintVersionInfo() {char *versionStrP;printf("tesseract %s\n", tesseract::TessBaseAPI::Version());versionStrP = getLeptonicaVersion();printf(" %s\n", versionStrP);lept_free(versionStrP);versionStrP = getImagelibVersions();printf(" %s\n", versionStrP);lept_free(versionStrP);
}void PrintUsage(const char* program) {printf("Usage:\n"" %s --help | --help-psm | --version\n"" %s --list-langs [--tessdata-dir PATH]\n"" %s --print-parameters [options...] [configfile...]\n"" %s imagename|stdin outputbase|stdout [options...] [configfile...]\n",program, program, program, program);
}void PrintHelpForPSM() {const char* msg ="Page segmentation modes:\n"" 0 Orientation and script detection (OSD) only.\n"" 1 Automatic page segmentation with OSD.\n"" 2 Automatic page segmentation, but no OSD, or OCR.\n"" 3 Fully automatic page segmentation, but no OSD. (Default)\n"" 4 Assume a single column of text of variable sizes.\n"" 5 Assume a single uniform block of vertically aligned text.\n"" 6 Assume a single uniform block of text.\n"" 7 Treat the image as a single text line.\n"" 8 Treat the image as a single word.\n"" 9 Treat the image as a single word in a circle.\n"" 10 Treat the image as a single character.\n";printf("%s", msg);
}void PrintHelpMessage(const char* program) {PrintUsage(program);const char* ocr_options ="OCR options:\n"" --tessdata-dir PATH Specify the location of tessdata path.\n"" --user-words PATH Specify the location of user words file.\n"" --user-patterns PATH Specify the location of user patterns file.\n"" -l LANG[+LANG] Specify language(s) used for OCR.\n"" -c VAR=VALUE Set value for config variables.\n"" Multiple -c arguments are allowed.\n"" -psm NUM Specify page segmentation mode.\n""NOTE: These options must occur before any configfile.\n";printf("\n%s\n", ocr_options);PrintHelpForPSM();const char *single_options ="Single options:\n"" -h, --help Show this help message.\n"" --help-psm Show page segmentation modes.\n"" -v, --version Show version information.\n"" --list-langs List available languages for tesseract engine.\n"" --print-parameters Print tesseract parameters to stdout.\n";printf("\n%s", single_options);
}void SetVariablesFromCLArgs(tesseract::TessBaseAPI* api, int argc, char** argv) {char opt1[256], opt2[255];for (int i = 0; i < argc; i++) {if (strcmp(argv[i], "-c") == 0 && i + 1 < argc) {strncpy(opt1, argv[i + 1], 255);opt1[255] = '\0';char *p = strchr(opt1, '=');if (!p) {fprintf(stderr, "Missing = in configvar assignment\n");exit(1);}*p = 0;strncpy(opt2, strchr(argv[i + 1], '=') + 1, 255);opt2[254] = 0;++i;if (!api->SetVariable(opt1, opt2)) {fprintf(stderr, "Could not set option: %s=%s\n", opt1, opt2);}}}
}void PrintLangsList(tesseract::TessBaseAPI* api) {GenericVector<STRING> languages;api->GetAvailableLanguagesAsVector(&languages);printf("List of available languages (%d):\n", languages.size());for (int index = 0; index < languages.size(); ++index) {STRING& string = languages[index];printf("%s\n", string.string());}api->End();
}void PrintBanner() {tprintf("Tesseract Open Source OCR Engine v%s with Leptonica\n",tesseract::TessBaseAPI::Version());
}void FixPageSegMode(tesseract::TessBaseAPI* api,tesseract::PageSegMode pagesegmode) {if (api->GetPageSegMode() == tesseract::PSM_SINGLE_BLOCK)api->SetPageSegMode(pagesegmode);
}// NOTE: arg_i is used here to avoid ugly *i so many times in this function
void ParseArgs(const int argc, char** argv,const char** lang,const char** image,const char** outputbase,const char** datapath,bool* list_langs,bool* print_parameters,GenericVector<STRING>* vars_vec,GenericVector<STRING>* vars_values,int* arg_i,tesseract::PageSegMode* pagesegmode) {if (argc == 1) {PrintHelpMessage(argv[0]);exit(0);}if (argc == 2) {if ((strcmp(argv[1], "-h") == 0) ||(strcmp(argv[1], "--help") == 0)) {PrintHelpMessage(argv[0]);exit(0);}if ((strcmp(argv[1], "--help-psm") == 0)) {PrintHelpForPSM();exit(0);}if ((strcmp(argv[1], "-v") == 0) ||(strcmp(argv[1], "--version") == 0)) {PrintVersionInfo();exit(0);}}bool noocr = false;int i = 1;while (i < argc && (*outputbase == NULL || argv[i][0] == '-')) {if (strcmp(argv[i], "-l") == 0 && i + 1 < argc) {*lang = argv[i + 1];++i;}else if (strcmp(argv[i], "--tessdata-dir") == 0 && i + 1 < argc) {*datapath = argv[i + 1];++i;}else if (strcmp(argv[i], "--user-words") == 0 && i + 1 < argc) {vars_vec->push_back("user_words_file");vars_values->push_back(argv[i + 1]);++i;}else if (strcmp(argv[i], "--user-patterns") == 0 && i + 1 < argc) {vars_vec->push_back("user_patterns_file");vars_values->push_back(argv[i + 1]);++i;}else if (strcmp(argv[i], "--list-langs") == 0) {noocr = true;*list_langs = true;}else if (strcmp(argv[i], "-psm") == 0 && i + 1 < argc) {*pagesegmode = static_cast<tesseract::PageSegMode>(atoi(argv[i + 1]));++i;}else if (strcmp(argv[i], "--print-parameters") == 0) {noocr = true;*print_parameters = true;}else if (strcmp(argv[i], "-c") == 0 && i + 1 < argc) {// handled properly after api init++i;}else if (*image == NULL) {*image = argv[i];}else if (*outputbase == NULL) {*outputbase = argv[i];}++i;}*arg_i = i;if (argc == 2 && strcmp(argv[1], "--list-langs") == 0) {*list_langs = true;noocr = true;}if (*outputbase == NULL && noocr == false) {PrintHelpMessage(argv[0]);exit(1);}
}void PreloadRenderers(tesseract::TessBaseAPI* api,tesseract::PointerVector<tesseract::TessResultRenderer>* renderers,tesseract::PageSegMode pagesegmode,const char* outputbase) {if (pagesegmode == tesseract::PSM_OSD_ONLY) {renderers->push_back(new tesseract::TessOsdRenderer(outputbase));}else {bool b;api->GetBoolVariable("tessedit_create_hocr", &b);if (b) {bool font_info;api->GetBoolVariable("hocr_font_info", &font_info);renderers->push_back(new tesseract::TessHOcrRenderer(outputbase, font_info));}api->GetBoolVariable("tessedit_create_tsv", &b);if (b) {bool font_info;api->GetBoolVariable("hocr_font_info", &font_info);renderers->push_back(new tesseract::TessTsvRenderer(outputbase, font_info));}api->GetBoolVariable("tessedit_create_pdf", &b);if (b) {renderers->push_back(new tesseract::TessPDFRenderer(outputbase,api->GetDatapath()));}api->GetBoolVariable("tessedit_write_unlv", &b);if (b) {renderers->push_back(new tesseract::TessUnlvRenderer(outputbase));}api->GetBoolVariable("tessedit_create_boxfile", &b);if (b) {renderers->push_back(new tesseract::TessBoxTextRenderer(outputbase));}api->GetBoolVariable("tessedit_create_txt", &b);if (b || renderers->empty()) {renderers->push_back(new tesseract::TessTextRenderer(outputbase));}}if (!renderers->empty()) {// Since the PointerVector auto-deletes, null-out the renderers that are// added to the root, and leave the root in the vector.for (int r = 1; r < renderers->size(); ++r) {(*renderers)[0]->insert((*renderers)[r]);(*renderers)[r] = NULL;}}
}int main(int argc, char **argv)
{const char* lang = "eng";const char* image = NULL;const char* outputbase = NULL;const char* datapath = NULL;bool list_langs = false;bool print_parameters = false;GenericVector<STRING> vars_vec, vars_values;int arg_i = 1;tesseract::PageSegMode pagesegmode = tesseract::PSM_AUTO;ParseArgs(argc, argv,&lang, &image, &outputbase, &datapath,&list_langs, &print_parameters,&vars_vec, &vars_values, &arg_i, &pagesegmode);bool banner = false;if (outputbase != NULL && strcmp(outputbase, "-") &&strcmp(outputbase, "stdout")) {banner = true;}PERF_COUNT_START("Tesseract:main")tesseract::TessBaseAPI api;api.SetOutputName(outputbase);int init_failed = api.Init(datapath, lang, tesseract::OEM_DEFAULT,&(argv[arg_i]), argc - arg_i, &vars_vec, &vars_values, false);if (init_failed) {fprintf(stderr, "Could not initialize tesseract.\n");exit(1);}SetVariablesFromCLArgs(&api, argc, argv);if (list_langs) {PrintLangsList(&api);exit(0);}if (print_parameters) {FILE* fout = stdout;fprintf(stdout, "Tesseract parameters:\n");api.PrintVariables(fout);api.End();exit(0);}FixPageSegMode(&api, pagesegmode);if (pagesegmode == tesseract::PSM_AUTO_ONLY) {int ret_val = 0;Pix* pixs = pixRead(image);if (!pixs) {fprintf(stderr, "Cannot open input file: %s\n", image);exit(2);}api.SetImage(pixs);tesseract::Orientation orientation;tesseract::WritingDirection direction;tesseract::TextlineOrder order;float deskew_angle;tesseract::PageIterator* it = api.AnalyseLayout();if (it) {it->Orientation(&orientation, &direction, &order, &deskew_angle);tprintf("Orientation: %d\nWritingDirection: %d\nTextlineOrder: %d\n" \"Deskew angle: %.4f\n",orientation, direction, order, deskew_angle);}else {ret_val = 1;}delete it;pixDestroy(&pixs);exit(ret_val);}// set in_training_mode to true when using one of these configs:// ambigs.train, box.train, box.train.stderr, linebox, reboxbool b = false;bool in_training_mode =(api.GetBoolVariable("tessedit_ambigs_training", &b) && b) ||(api.GetBoolVariable("tessedit_resegment_from_boxes", &b) && b) ||(api.GetBoolVariable("tessedit_make_boxes_from_boxes", &b) && b);tesseract::PointerVector<tesseract::TessResultRenderer> renderers;if (in_training_mode) {renderers.push_back(NULL);}else {PreloadRenderers(&api, &renderers, pagesegmode, outputbase);}if (!renderers.empty()) {if (banner) PrintBanner();bool succeed = api.ProcessPages(image, NULL, 0, renderers[0]);if (!succeed) {fprintf(stderr, "Error during processing.\n");exit(1);}}PERF_COUNT_ENDreturn 0; // Normal exit
}
GitHub: https://github.com/fengbingchun/Tesseract-OCR_Test
相关文章:

【Laravel-海贼王系列】第九章, Events 功能解析
Events 注册 框架如何在启动的时候加载注册的事件?框架如何触发事件?1,先在容器中注册 events 的全局对象。 Application 构造函数中对 events 进行注册代码 protected function registerBaseServiceProviders(){$this->register(new EventServiceProvider($th…

触类旁通,经典面试题最长公共子序列应该这么答
作者 | labuladong来源 | labuladong(ID:labuladong)【导读】最长公共子序列(Longest Common Subsequence,简称 LCS)是一道非常经典的面试题目,因为它的解法是典型的二维动态规划,大部分比较困难的字符串问…

两分公支的IPSec***流量走总部测试
一.概述:在论坛上看到一个朋友发帖希望两个分支的IPSEC ***流量经过总部,如是搭建拓扑测试了一下,因为跑两个VM版的ASA8.42机器性能不过,所以用PIX8.0来代替ASA,应该主要配置都跟ASA8.0差不多。二.基本思路:A.两个分支…

OpenCV代码提取:cvtColor函数的实现
OpenCV中的cvtColor函数包括了很多颜色格式之间的转换,用起来很方便,这里对cvtColor函数的code进行了提取,经测试,和OpenCV3.1结果完全一致。实现代码cvtColor.hpp:// fbc_cv is free software and uses the same licence as Open…

关于java.util.LinkedHashMap cannot be cast to ......的解决办法
今天在项目中遇到一个问题,接口接收到list在对list进行遍历的时候报出如下错误: 断点看一下这个list感觉没有任何的问题: 那为什么会报这个错误呢 这个接口是这样的,在想会不会是json在转list的时候把这个list给整坏了。 于是,我把这个list再…

三两下实现NLP训练和预测,这四个框架你要知道
作者 | 狄东林 刘元兴 朱庆福 胡景雯编辑 | 刘元兴,崔一鸣来源 | 哈工大SCIR(ID:HIT_SCIR)引言随着人工智能的发展,越来越多深度学习框架如雨后春笋般涌现,例如PyTorch、TensorFlow、Keras、MXNet、Theano 和 PaddlePaddle 等。这…

大学计算机基础实验
下载2013算法实验报告.rar转载于:https://www.cnblogs.com/shajianheng/p/3381968.html

java基础(十三)-----详解内部类——Java高级开发必须懂的
java基础(十三)-----详解内部类——Java高级开发必须懂的 目录 为什么要使用内部类内部类基础静态内部类 成员内部类 成员内部类的对象创建继承成员内部类局部内部类推荐博客匿名内部类正文 可以将一个类的定义放在另一个类的定义内部,这就是内部类。 回到顶部为什么…

C++中函数指针的使用
A function pointer is a variable that stores the address of a function that can later be called through that function pointer. This is useful because functions encapsulate behavior.函数指针是一个指向函数的指针,函数指针表示一个函数的入口地址。指针是变量&…

只做好CTR预估远不够,淘宝融合CTR、GMV、收入等多目标有绝招
作者 | 吴海波转载自知乎用户吴海波【导读】一直以来,电商场景就存在 ctr、cvr、gmv、成交 uv 等多个目标,都是核心指标。理想情况下,提升 ctr 就能提升 gmv,但本文作者认为,在一定程度上, ctr 和 gmv 并不…

Android监听HOME按键
2019独角兽企业重金招聘Python工程师标准>>> <!-- lang: java --> class HomeKeyEventBroadCastReceiver extends BroadcastReceiver {static final String SYSTEM_REASON "reason";static final String SYSTEM_HOME_KEY "homekey";// …

OpenCV代码提取:merge/split函数的实现
对OpenCV中的merge/split函数进行了实现,经测试,与OpenCV3.1结果完全一致。merge实现代码merge.hpp:// fbc_cv is free software and uses the same licence as OpenCV // Email: fengbingchun163.com#ifndef FBC_CV_MERGE_HPP_ #define FBC_…

DeepMind提图像生成的递归神经网络DRAW,158行Python代码复现
作者 | Samuel Noriega译者 | Freesia编辑 | 夕颜出品 | AI科技大本营(ID: rgznai100)【导读】最近,谷歌 DeepMInd 发表论文( DRAW: A Recurrent Neural Network For Image Generation),提出了一个用于图像生成的递归神…

其他进制的数字
JS中如果需要表示16进制的数字,则需要以0X开头 0X10 八进制数字以0开头 070 070有些浏览器会以8进制解析,但是有些则用10进制解析,10进制为70,8进制为56 所以parseint() 第二个参数可以设定进制,比如 parseint(“070”,10)代表以10进制解析070 2进制以0b开头,但是不是所有浏览…

java中的移位运算符
移位运算符是在数字的二进制形式上进行平移。主要有左移(<<)、带符号右移(>>)以及无符号右移(>>>)。左移运算符(<<)的运算规则为:按二进制形…

C++11中nullptr的使用
在C语言中,NULL实际上是一个void* 的指针,然后把void* 指针赋值给其它类型的指针的时候,会隐式转换成相应的类型。而如果用一个C编译器来编译的时候是要出错的,因为C是强类型的,void* 是不能隐式转换成其它指针类型的。…

埃森哲、亚马逊和万事达卡抱团推出的区块链项目有何神通?
据外媒报道,今日埃森哲宣布了一项新的区块链项目,该项目为基于区块链的循环供应链,将与万事达卡和亚马逊共同合作。据官方介绍,这个基于区块链的循环供应链能够让客户识别供应链上的小规模供应商和种植者,例如…

小团队如何玩转物联网开发?
近几年来,物联网发展迅速:据中商产业研究院《2016——2021年中国物联网产业市场研究报告》显示,预计到2020年,中国物联网的整体规模将达2.2万亿元,产业规模比互联网大30倍。与之相反的是,物联网开发者在开发…

Build Boost C++ libraries for x32/x64 VC++ compilers on Windows
2019独角兽企业重金招聘Python工程师标准>>> Boost is a set of libraries for the C programming language that provide support for tasks and structures such as linear algebra, pseudorandom number generation, multithreading, image processing, regular …

C++11中auto的使用
在C语言中,就有了auto关键字,它被当作是一个变量的存储类型修饰符,表示自动变量(局部变量)。它不能被单独使用,否则编译器会给出警告。在C11标准中,添加了新的类型推导特性。在C 11中,使用auto定义的变量不…
攻和防谁更厉害?AI技术在恶意软件检测中的应用和对抗
AI技术的发展为网络安全带来新机遇的同时,黑客也在逐渐利用AI漏洞建立对抗样本以躲避攻击,双方在各自领域的更多尝试也将是AI技术发展的一场新博弈。那么,在应用中,如何利用AI检测技术与恶意软件展开对抗? 腾讯安全技术…

一文看懂机器学习中的常用损失函数
作者丨stephenDC编辑丨zandy来源 | 大数据与人工智能(ID: ai-big-data)导语:损失函数虽然简单,却相当基础,可以看做是机器学习的一个组件。机器学习的其他组件,还包括激活函数、优化器、模型等。本文针对机…

Using Apache2 with JBoss AS7 on Ubuntu
大体思路同《Using Apache Web Server with Jboss AS 7》一致,但在Ubuntu上的操作与之前有些区别。 这里仍然演示mod_proxy的配置。 首先加载相应的模块。Ubuntu中加载模块和卸载模块均可以通过命令操作,与其对应的命令分别是a2enmod和a2dismod。 启用…
OpenCV代码提取:rotate函数的实现
OpenCV中并没有直接提供实现rotate的函数,这里通过getRotationMatrix2D和warpAffine函数实现rotate,并增加了一个crop参数,用来判断是否进行crop。目前支持uchar和float两种类型,经测试,与OpenCV3.1结果完全一致。公式…
在 Node.js 中用子进程操作标准输入/输出
翻译:疯狂的技术宅原文:http://2ality.com/2018/05/chi... 本文首发微信公众号:jingchengyideng欢迎关注,每天都给你推送新鲜的前端技术文章 在本中,我们在 Node.js 中把 shell 命令作为子进程运行。然后异步读取这些进…

再见,Python 2.x
整理 | 屠敏来源 | CSDN(ID:CSDNnews)在技术的长河中,软件、工具、系统等版本的迭代本是常事,但由于使用习惯、版本的兼容性、易用性等因素,很多用户及开发者在使用或做开发的过程中,并不愿意及…

Android UI系列-----CheckBox和RadioButton(1)
主要记录一下CheckBox多选框和RadioGroup、RadioButton单选框的设置以及注册监听器 1.CheckBox 布局文件: <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools"android…

C++中struct的使用
C语言继承了C语言的struct,并且加以扩充。在C语言中struct是只能定义数据成员,而不能定义成员函数的。而在C中,struct类似于class,在其中既可以定义数据成员,又可以定义成员函数。结构类型是用户定义的复合类型&#x…

填报表中也可以添加 html 事件
在实际的项目开发中,填报表的应用十分广泛。 多数情况下,填报表会作为整个项目的一部分配合需求灵活使用,但有时也会受大项目环境的影响,产生一些特别的要求。比如,通常报表单元格的数据类型大多是文本,有时…

60+业内技术专家,9大核心技术专题,AI ProCon倒计时一周!
2018 年,由 CSDN 举办的第一届 AI 开发者大会喊出“只讲技术,拒绝空谈”,两天会议时间,国内外几十家顶尖科技企业讲述了其主流技术及其应用案例,真正引领国内开发者紧跟技术浪潮。一年过去,在你还未有所觉察…