一、为什么用线程

在这里将ocr识别的这个耗时的操作放在新线程内,这样是为了主线程/UI界面不会卡在那里没有响应。如果说不在乎用户体验,ocr识别也可以放在主线程,卡住就卡住,就是会被骂。

不过关于线程的使用有的时候也要看平台框架的要求,比如android,网络请求就要在新线程内,否则就会报错。

QT内的线程类叫做QThread,看看qthread.h内的部分方法,熟悉Java线程的大概在就会知道用法了(因为挺像的),我们这里采用创建一个新的继承自QThread类的方法使用线程。

QThread 的头文件的部分截图

二、创建继承自Thread的类

1、创建头文件

起了个名字,有点长,MyThreadForTextRecognition.h。

其中public方法内主要是自定义的init方法,用来传递给线程一些ocr识别的参数,比如语言、用哪个引擎等。

其中private是一些线程内的参数,以及对应两个ocr引擎的识别方法。

其中protected就是我们要覆写的run方法。

其中signals就是我们用来和主线程通信的方法。关于信号和槽可以查看官网说明。其中getRecognitionText方法是用来将识别结果传递给主线程以显示在界面上。其中recognitionFinish方法是告诉主线程识别完了,可以关闭loading了。

#ifndef MYTHREADFORTEXTRECOGNITION_H
#define MYTHREADFORTEXTRECOGNITION_H// windows sdk api
#define _SILENCE_CLANG_COROUTINE_MESSAGE
#include "winrt/Windows.Globalization.h"
#include "winrt/windows.media.ocr.h"
#include "winrt/windows.graphics.imaging.h"
#include "winrt/Windows.Storage.h"
#include "winrt/Windows.Storage.Streams.h"
#include "winrt/Windows.Foundation.Collections.h"// QT
#include <QObject>
#include <QThread>
#include "qdebug.h"// 自定义
#include "mytools.h"// tesseract
#include <tesseract/baseapi.h>
#include <leptonica/allheaders.h>class MyThreadForTextRecognition : public QThread
{Q_OBJECT
public:MyThreadForTextRecognition();void init(std::string filepath, std::string newFilepath, int language_index, bool preprocessing, int ocrengine);private:char *outText;std::string _filepath;int _language_index;std::string _newFilepath;bool _preprocessing = false;std::string _ocrengine;void _cognizeByWinOCR();void _cognizeByTesseract();protected:void run() override;signals:void minNumToamin(int min);void getRecognitionText(std::string outText);void recognitionFinish();};#endif // MYTHREADFORTEXTRECOGNITION_H

2、创建cpp文件

参考代码如下

#include <MyThreadForTextRecognition.h>
#include <string>
#include <iostream>
#include <locale>
#include <codecvt>//#pragma execution_character_set("utf-8");//comment(lib, "windowsapp")using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Storage;
using namespace winrt::Windows::Storage::Streams;
using namespace winrt::Windows::Globalization;
using namespace winrt::Windows::Media::Ocr;
using namespace winrt::Windows::Graphics::Imaging;MyThreadForTextRecognition::MyThreadForTextRecognition()
{}/*** @brief MyThreadForTextRecognition::init 接收一些参数* @param filepath* @param newFilepath* @param language* @param preprocessing*/
void MyThreadForTextRecognition::init(std::string filepath, std::string newFilepath, int language_index, bool preprocessing, int ocrengine)
{_filepath = filepath;_language_index = language_index;_newFilepath = newFilepath;_preprocessing = preprocessing;_ocrengine = (ocrengine==0) ? "micocr" : "tesseract";
}/*** @brief MyThreadForTextRecognition::_cognizeByWinOCR* 基于windows的ocr*/
void MyThreadForTextRecognition::_cognizeByWinOCR()
{//获取图片路径std::wstring uriImage = MyTools::ConvertUtf8ToWide(_newFilepath);//获取SoftwareBitmapRandomAccessStreamReference streamRef = RandomAccessStreamReference::CreateFromFile(StorageFile::GetFileFromPathAsync(uriImage).get());IAsyncOperation<IRandomAccessStreamWithContentType> stream = streamRef.OpenReadAsync();Buffer buffer = Buffer((uint)stream.get().Size());auto decoder = BitmapDecoder::CreateAsync(stream.get().CloneStream());IAsyncOperation<SoftwareBitmap> softwareBitmap = decoder.get().GetSoftwareBitmapAsync();//进行识别Language language(winrt::to_hstring(MyTools::get_Choise_Language(_language_index, _ocrengine)));//如果不支持的语言if (OcrEngine::IsLanguageSupported(language)) {OcrEngine engine = OcrEngine::TryCreateFromLanguage(language);Collections::IVectorView<OcrLine> lines = engine.RecognizeAsync(softwareBitmap.get()).get().Lines();if(lines.Size()>0){for (auto p : lines){std::string text = "";for (OcrWord word : p.Words()) {text += to_string(word.Text()) + ((_language_index>0)?" ":"");}emit getRecognitionText(text/*const_cast<char *>(text.c_str())*/);qDebug() << "识别结果:" << text.c_str();}}else{emit getRecognitionText("");}}else{qDebug() << "不支持的语言:" << QString::fromStdString(MyTools::get_Choise_Language(_language_index, _ocrengine));emit getRecognitionText("");}
}/*** @brief MyThreadForTextRecognition::_cognizeByTesseract* 基于Tesseract的ocr*/
void MyThreadForTextRecognition::_cognizeByTesseract()
{// 初始化apitesseract::TessBaseAPI *api = new tesseract::TessBaseAPI();// 初始化ocr识别,使用中文并且指定tessdata路径if (api->Init("lib/tesseract/tessdata/", MyTools::get_Choise_Language(_language_index, _ocrengine).c_str(), tesseract::OcrEngineMode::OEM_LSTM_ONLY)) {emit getRecognitionText("");}else{// 使用leptonica库打开图像Pix *image = pixRead(_newFilepath.c_str());api->SetImage(image);// 【最简单的api】//outText = api->GetUTF8Text();//qDebug()<<"outText:"<<outText;//getRecognitionText(outText);// 【获取组件图像示例】Boxa* boxes = api->GetComponentImages(tesseract::RIL_PARA, true, NULL, NULL);for (int i = 0; i < boxes->n; i++) {BOX* box = boxaGetBox(boxes, i, L_CLONE);api->SetRectangle(box->x, box->y, box->w, box->h);char* ocrResult = api->GetUTF8Text();int meanConf = api->MeanTextConf();int *confs = api->AllWordConfidences();qDebug()<<"meanConf:"<<meanConf;emit getRecognitionText(ocrResult);//fprintf(stdout, "Box[%d]: x=%d, y=%d, w=%d, h=%d, confidence: %d, text: %s", i, box->x, box->y, box->w, box->h, conf, ocrResult);boxDestroy(&box);}emit recognitionFinish();// 销毁使用过的对象并释放内存api->End();delete api;//delete[] outText;pixDestroy(&image);}
}/*** @brief MyThreadForTextRecognition::run 运行线程*/
void MyThreadForTextRecognition::run()
{try{//图像预处理,可以没有if(_preprocessing){MyTools::BinarythresoldByOpenCV(_filepath.c_str(), _newFilepath.c_str());}else{_newFilepath = _filepath;}if(_ocrengine == "micocr"){_cognizeByWinOCR();}else if(_ocrengine == "tesseract"){_cognizeByTesseract();}}catch(_exception e){emit getRecognitionText("");qDebug()<<"ocr识别异常:"<<0;}emit recognitionFinish();
}

三、使用线程

首先实例化线程类,然后调用init传递参数,然后绑定两个信号/槽,最后调用start方法启动线程。

//启动线程
m_thread  =  new MyThreadForTextRecognition;
m_thread->init(filePath.toStdString(), QString("%1\\screen_action.jpg").arg(qApp->applicationDirPath().replace("/", "\\")).toStdString(),ui->comboBox->currentIndex(), ui->checkBox_3->isChecked(), ui->comboBox_2->currentIndex());
connect(m_thread, &MyThreadForTextRecognition::getRecognitionText,this,&TextRecognition::getRecognitionText);
connect(m_thread, &MyThreadForTextRecognition::recognitionFinish,this,&TextRecognition::recognitionFinish);
m_thread->start();

QT案例实战1 - 从零开始编写一个OCR工具软件 (6) 关于QThread线程的使用相关推荐

  1. QT案例实战1 - 从零开始编写一个OCR工具软件 (3)创建项目

    一.创建项目 打开Qt Creator,点击Create Project. 可以看到项目类型有应用.应用for python.类库等等,这里选择第一个QT应用,然后第二个栏中选择QT Weidgets ...

  2. QT案例实战1 - 从零开始编写一个OCR工具软件 (7) 屏幕截图/图像展示/文字识别

    一.图片文字识别功能 在之前的的文章中,引入了ocr识别引擎,也在线程内实现了调用引擎进行识别.基本功能都有了,就可以把功能和UI组织在一起了. 关于图片文字识别的功能,UI分两部分,左侧实现屏幕截图 ...

  3. QT案例实战1 - 从零开始编写一个OCR工具软件 (8) Pdf读取展示/截图/文字识别

    一.PDF读取展示功能 QT提供了pdf.PdfWidgets模块,需要安装模块,然后在项目的CMakeLists.txt文件内,添加如下代码,以便在项目中使用. 官方提供了完整的pdf展示示例,示例 ...

  4. 从零开始编写一个上位机(串口助手)QT Creator + Python

    提示:本博客作为学习笔记,有错误的地方希望指正,此文可能会比较长,作为学习笔记的积累,希望对来着有帮助.   绪论:笔者这里使用的是QTCreator和Python来实现一个简单的串口上位机的开发的简 ...

  5. 从零开始编写一个vue插件

    title: 从零开始编写一个vue插件 toc: true date: 2018-12-17 10:54:29 categories: Web tags: vue mathjax 写毕设的时候需要一 ...

  6. 从零开始编写一个宠物识别系统(爬虫、模型训练和调优、模型部署、Web服务)

    心血来潮,想从零开始编写一个相对完整的深度学习小项目.想到就做,那么首先要考虑的问题是,写什么? 思量再三,我决定写一个宠物识别系统,即给定一张图片,判断图片上的宠物是什么.宠物种类暂定为四类--猫. ...

  7. Linux驱动开发(从零开始编写一个驱动程序)

    1.系统整体工作原理 (1)应用层->API->设备驱动->硬件 (2)API:open.read.write.close等 (3)驱动源码中提供真正的open.read.write ...

  8. 基于PYQT编写一个人脸识别软件(2)

    前言 以前在博客:基于PYQT编写一个人脸识别软件 中给出了我自己用PYQT编写的一个小软件.鉴于使用的是开源库--face_recogniton,尽管使用很简单,但是还有些问题,比如:识别黄种人时效 ...

  9. 编写一个Java程序实现多线程,在线程中输出线程的名字,隔300毫秒输出一次,共输出20次。

    编写一个Java程序实现多线程,在线程中输出线程的名字,隔300毫秒输出一次,共输出20次. 一.ThreadDemo class ThreadDemo extends Thread {public ...

最新文章

  1. 操作系统---Systemd
  2. python装饰器_Python装饰器是个什么鬼?
  3. C#控制DataMax指令打印DPL问题总结
  4. 实验代做 行人识别_CVPR 2020 | 针对VI-ReID的分层跨模态行人识别
  5. 基于Boost::beast模块的同步WebSocket客户端
  6. Android开发之自定义输入框无法弹起键盘输入法的解决方法
  7. PAT_B_1049_C++(20分)
  8. linux增加 inode空间,linux 增加inode 的方法
  9. 李迟2021年10月知识总结
  10. workbench拓扑优化教程_轻量化及拓扑优化软件GENESIS介绍——可集成到Workbench
  11. 扫雷计算机教案,《扫雷游戏》教学设计
  12. 每日一记:2017.7.20
  13. azul zing_微软和Azul将OpenJDK提升到Azure云中
  14. CSS实现文字凹凸效果
  15. 用ln命令链接文件 --- 一根绳子上的蚂蚱?
  16. python中简述文件_python中的文件操作
  17. 华为Mate book D 2018加装内存条
  18. 冯唐:老聃的金字塔原则
  19. 计算机缺少codex64.dll,win10x64缺少dll依赖库致使程序无法运行
  20. 使用纯css完成行星图并且封装成组件

热门文章

  1. 计算机组成原理的VDD与VCC
  2. 图片文字翻译的软件有哪些?快收藏这几款实用的软件
  3. 一些学习经验总结和分享
  4. 【ArcGIS Pro二次开发】(5):UI管理_自定义控件的位置
  5. FTP服务器的配置,以及配置ftp支持ftps
  6. 腾讯文档自动填写工具(工具)
  7. 选择排序总结以及排序算法的稳定性
  8. AIoT系列:AI赋能物联网,探索AIoT发展新趋势
  9. SQL 注入漏洞(一)
  10. python hasattr()函数详解