[{"data":1,"prerenderedAt":291},["ShallowReactive",2],{"news-item-\u002Fnews\u002Ftesseract-ios":3},{"id":4,"title":5,"body":6,"category":276,"created by":279,"date":280,"description":281,"extension":282,"meta":283,"navigation":284,"path":285,"sections":286,"seo":287,"stem":288,"thumbnail":289,"__hash__":290},"content_en\u002Fnews\u002Ftesseract-ios.md","Tesseract for iOS",{"type":7,"value":8,"toc":268},"minimark",[9,14,22,25,33,36,43,46,50,69,73,76,86,91,98,104,107,112,116,123,127,130,134,139,146,157,160,164,168,171,175,179,182,185,195,198,204,207,215,217,223,226,232,235,239,242,248,251,255,259,262],[10,11,13],"h2",{"id":12},"introduction","Introduction",[15,16,17,21],"p",{},[18,19,20],"strong",{},"Tesseract"," is an optical character recognition engine for various operating systems. It is free software, released under the Apache License, and development has been sponsored by Google since 2006 until now (2020). This is the most popular and qualitative OCR-library. It uses artificial intelligence(AI) for text search and its recognition on images. It supports multiple platforms: MacOS, Window, Linux, but it can be compiled for iOS and Android also. ",[15,23,24],{},"This is the source code’ s repository.",[15,26,27],{},[28,29,30],"a",{"href":30,"rel":31},"https:\u002F\u002Fgithub.com\u002Ftesseract-ocr\u002Ftesseract",[32],"nofollow",[15,34,35],{},"The number of languages supported is over 100, which each .traineddata file is a language trained model.",[15,37,38,42],{},[28,39,40],{"href":40,"rel":41},"https:\u002F\u002Fgithub.com\u002Ftesseract-ocr\u002Ftessdata",[32]," ",[15,44,45],{},"Now I would like to describe how to implement Tesseract for iOS.",[10,47,49],{"id":48},"development-environment","Development Environment",[51,52,53,57,60,63,66],"ul",{},[54,55,56],"li",{},"Macos Catalina 10.15.2",[54,58,59],{},"Xcode 11.3, Swift 5",[54,61,62],{},"Tesseract 4.1.1",[54,64,65],{},"Leptonica 1.79.0",[54,67,68],{},"OpenCV 4.2.0",[10,70,72],{"id":71},"download-and-include-dependencies","Download and include dependencies",[15,74,75],{},"First, create new xcode project with Single View App mode",[77,78],"img",{"className":79,"alt":83,"src":84,"style":85},[80,81,82],"block","mx-auto","mb-4","","https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2020\u002F01\u002F06172932\u002FScreen-Shot-2020-01-13-at-2.23.57-PM-1024x737.png","width: 100%;",[87,88,90],"h4",{"id":89},"download-tesseract-411-version-for-ios","Download tesseract 4.1.1 version for iOS",[15,92,93,94,97],{},"(This is the compiled version from ",[28,95,30],{"href":30,"rel":96},[32]," for iOS ONLY)",[15,99,100],{},[28,101,102],{"href":102,"rel":103},"https:\u002F\u002Fgithub.com\u002Fkang298\u002FTesseract-builds-for-iOS\u002Ftree\u002Ftesseract-4.1.1",[32],[15,105,106],{},"After downloaded and unzipped, you will have 2 folders “include” and “lib”, drag and drop both to your xcode project ",[77,108],{"className":109,"alt":83,"src":110,"style":111},[80,81,82],"https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2020\u002F01\u002F06172953\u002FScreen-Shot-2020-01-13-at-2.39.35-PM.png","width: 60%;",[87,113,115],{"id":114},"download-opencv-ios-framework","Download OpenCV iOS framework",[15,117,118,122],{},[28,119,120],{"href":120,"rel":121},"https:\u002F\u002Fopencv.org\u002Freleases\u002F",[32]," then drag drop to xcode project",[77,124],{"className":125,"alt":83,"src":126,"style":111},[80,81,82],"https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2020\u002F01\u002F06173010\u002FScreen-Shot-2020-01-13-at-1.19.07-PM.png",[15,128,129],{},"Press command + R to build to make sure no error",[87,131,133],{"id":132},"download-languages-trained-model-files","Download languages' trained model files",[15,135,136],{},[28,137,40],{"href":40,"rel":138},[32],[15,140,141,142,145],{},"In this tutorial, we will test with 3 languages: English, Japanese, Vietnamese. So we should download the following models files and saved them in a folder named ",[18,143,144],{},"tessdata",":",[51,147,148,151,154],{},[54,149,150],{},"eng.traineddata",[54,152,153],{},"jpn.traineddata",[54,155,156],{},"vie.traineddata",[15,158,159],{},"Then drag drop that folder to xcode project. NOTE: choose \"Create folder references\" instead of \"Create Group\" when adding that folder to project",[77,161],{"className":162,"alt":83,"src":163,"style":85},[80,81,82],"https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2020\u002F01\u002F06173027\u002FScreen-Shot-2020-01-13-at-3.58.09-PM-1024x299.png",[10,165,167],{"id":166},"coding","Coding",[15,169,170],{},"Because Tesseract is developed by C++ so you only code by C++. Create an C++ file named tesseract_wrapper.cpp in project like following",[77,172],{"className":173,"alt":83,"src":174,"style":85},[80,81,82],"https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2020\u002F01\u002F06173100\u002FScreen-Shot-2020-01-13-at-2.44.03-PM-1024x740.png",[77,176],{"className":177,"alt":83,"src":178,"style":85},[80,81,82],"https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2020\u002F01\u002F06173117\u002FScreen-Shot-2020-01-13-at-2.44.09-PM-1024x379.png",[15,180,181],{},"Remember to check “Also create a header file” so that Xcode will create a header (tesseract_wrapper.hpp) file for you C++ file.",[15,183,184],{},"tesseract_wrapper.hpp",[186,187,192],"pre",{"className":188,"code":190,"language":191},[189],"language-text","\u002F\u002F\n\u002F\u002F  tesseract_wrapper.hpp\n\u002F\u002F  TestTesseract\n\u002F\u002F\n\u002F\u002F  Created by Briswell on 1\u002F13\u002F20.\n\u002F\u002F  Copyright © 2020 Briswell. All rights reserved.\n\u002F\u002F\n\n#ifndef tesseract_wrapper_hpp\n#define tesseract_wrapper_hpp\n\n#include \"opencv2\u002Fimgproc.hpp\"\n#include \"stdio.h\"\n\nusing namespace cv;\nString ocrUsingTesseractCPP(String image_path,String data_path,String language);\n\n#endif \u002F* tesseract_wrapper_hpp *\u002F\n\n","text",[193,194,190],"code",{"__ignoreMap":83},[15,196,197],{},"tesseract_wrapper.cpp",[186,199,202],{"className":200,"code":201,"language":191},[189],"\u002F\u002F\n\u002F\u002F  tesseract_wrapper.cpp\n\u002F\u002F  TestTesseract\n\u002F\u002F\n\u002F\u002F  Created by Briswell on 1\u002F13\u002F20.\n\u002F\u002F  Copyright © 2020 Briswell. All rights reserved.\n\u002F\u002F\n\n#include \"allheaders.h\"\n#include \"opencv2\u002Fimgproc.hpp\"\n#include \"opencv2\u002Fhighgui.hpp\"\n#include \"baseapi.h\"\n#include \"tesseract_wrapper.hpp\"\n\nusing namespace cv;\nusing namespace tesseract;\n\n\u002F*\n matToPix():\n    convert from OpenCV Image Container to Leptonica's Pix Struct\n Params:\n    mat: OpenCV Mat image Container\n Output\n    Leptonica's Pix Struct\n *\u002F\nPix* matToPix(Mat *mat){\n    int image_depth = 8;\n    \u002F\u002Fcreate a Leptonica's Pix Struct with width, height of OpenCV Image Container\n    Pix *pixd = pixCreate(mat->size().width, mat->size().height, image_depth);\n    for(int y=0; yrows; y++) {\n        for(int x=0; xcols; x++) {\n            pixSetPixel(pixd, x, y, (l_uint32) mat->at(y,x));\n        }\n    }\n    return pixd;\n}\n\n\u002F*\n ocrUsingTesseractCPP():\n    Using Tesseract engine to read text from image\n Params:\n    image_path: path to image\n    data_path: path to folder containing .traineddata files\n    language: expeted language to detect (eng,jpn,..)\n Output:\n    String detected from image\n *\u002F\nString ocrUsingTesseractCPP(String image_path,String data_path,String language){\n    \u002F\u002Fload a Mat Image Container from image's path and gray scale mode\n    Mat image = imread(image_path,IMREAD_GRAYSCALE);\n    TessBaseAPI* tessEngine = new TessBaseAPI();\n    \u002F\u002FTesseract 4 adds a new neural net (LSTM) based OCR engine which is focused on line recognition, but also still supports the legacy Tesseract OCR engine of Tesseract 3 which works by recognizing character patterns, in this tutorial we just focus on LSTM only\n    OcrEngineMode mode = tesseract::OEM_LSTM_ONLY;\n    \n    \u002F\u002Finit Tesseract engine\n    tessEngine->Init(data_path.c_str(), language.c_str(), mode);\n    \n    \u002F\u002FSet mode for page layout analysis, refer for all modes supporting\n    \u002F\u002Fhttps:\u002F\u002Ftesseract.patagames.com\u002Fhelp\u002Fhtml\u002FT_Patagames_Ocr_Enums_PageSegMode.htm\n    PageSegMode pageSegMode = tesseract::PSM_SINGLE_BLOCK;\n    tessEngine->SetPageSegMode(pageSegMode);\n    \n    \u002F\u002Fincrease accuracy for japanese\n    if(language.compare(\"jpn\") == 0){\n        tessEngine->SetVariable(\"chop_enable\", \"true\");\n        tessEngine->SetVariable(\"use_new_state_cost\", \"false\");\n        tessEngine->SetVariable(\"segment_segcost_rating\", \"false\");\n        tessEngine->SetVariable(\"enable_new_segsearch\", \"0\");\n        tessEngine->SetVariable(\"language_model_ngram_on\", \"0\");\n        tessEngine->SetVariable(\"textord_force_make_prop_words\", \"false\");\n        tessEngine->SetVariable(\"edges_max_children_per_outline\", \"40\");\n    }\n    \n    \n    \u002F\u002Fconvert from OpenCV Image Container to Leptonica's Pix Struct\n    Pix *pixImage = matToPix(&image);\n    \u002F\u002Fset Leptonica's Pix Struct to Tesseract engine\n    tessEngine->SetImage(pixImage);\n    \n    \u002F\u002Fget recognized text in UTF8 encoding\n    char *text = tessEngine->GetUTF8Text();\n    \n    \u002F\u002Frelease Tesseract's cache\n    tessEngine->End();\n    pixDestroy(&pixImage);\n    \n    return text;\n}\n",[193,203,201],{"__ignoreMap":83},[15,205,206],{},"Because Swift can not call C++ function directly so we will a objective-c wrapper file to handle that.",[51,208,209,212],{},[54,210,211],{},"TesseractWrapper.h",[54,213,214],{},"TesseractWrapper.mm (not .m because this file is for C++ compilation)",[15,216,211],{},[186,218,221],{"className":219,"code":220,"language":191},[189],"\u002F\u002F\n\u002F\u002F  TesseractWrapper.h\n\u002F\u002F  TestTesseract\n\u002F\u002F\n\u002F\u002F  Created by Briswell on 1\u002F13\u002F20.\n\u002F\u002F  Copyright © 2020 Briswell. All rights reserved.\n\u002F\u002F\n\n#import \"Foundation\u002FFoundation.h\"\n#import \"UIKit\u002FUIKit.h\"\n@interface TesseractWrapper : NSObject\n+(NSString*)ocrUsingTesseractObjectiveC:(UIImage*)image language:(NSString*)language;\n@end\n",[193,222,220],{"__ignoreMap":83},[15,224,225],{},"TesseractWrapper.mm",[186,227,230],{"className":228,"code":229,"language":191},[189],"\u002F\u002F\n\u002F\u002F  TesseractWrapper.m\n\u002F\u002F  TestTesseract\n\u002F\u002F\n\u002F\u002F  Created by Briswell on 1\u002F13\u002F20.\n\u002F\u002F  Copyright © 2020 Briswell. All rights reserved.\n\u002F\u002F\n\n#import \"TesseractWrapper.h\"\n\n#include \"tesseract_wrapper.hpp\"\n@implementation TesseractWrapper\n\n\u002F*\nocrUsingTesseractObjectiveC()\n    call ocrUsingTesseractCPP() to recognize  text from image\n params:\n    image: image to recognize text\n    language: eng\u002Fjpn\u002Fvie\n output:\n    recognized string\n *\u002F\n+(NSString*)ocrUsingTesseractObjectiveC:(UIImage*)image language:(NSString*)language{\n    \u002F\u002Fget path of folder containing .traineddata files\n    NSString* data_path = [NSString stringWithFormat:@\"%@\u002Ftessdata\u002F\",[[NSBundle mainBundle] bundlePath]];\n    \u002F\u002Fsave image to app's cache directory\n    NSString* cache_dir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];\n    NSString* image_path = [NSString stringWithFormat:@\"%@\u002Fimage.jpeg\",cache_dir];\n    NSData* data = UIImageJPEGRepresentation(image, 0.5);\n    NSURL* url = [NSURL fileURLWithPath:image_path];\n    [data writeToURL:url atomically:true];\n    \n    \u002F\u002Fget text from image using ocrUsingTesseractCPP() from file tesseract_wrapper.hpp\n    String str = ocrUsingTesseractCPP([image_path UTF8String], [data_path UTF8String], [language UTF8String]);\n    NSString* result_string = [NSString stringWithCString:str.c_str()\n    encoding:NSUTF8StringEncoding];\n    \u002F\u002Fremove cached image\n    [[NSFileManager defaultManager] removeItemAtURL:url error:nil];\n    return result_string;\n}\n@end\n",[193,231,229],{"__ignoreMap":83},[15,233,234],{},"Create a simple screen with a textview and button only in ViewController.swift",[77,236],{"className":237,"alt":83,"src":238,"style":111},[80,81,82],"https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2020\u002F01\u002F06173139\u002FIMG_8597.png",[15,240,241],{},"ViewController.swift",[186,243,246],{"className":244,"code":245,"language":191},[189],"\u002F\u002F\n\u002F\u002F  ViewController.swift\n\u002F\u002F  TestTesseract\n\u002F\u002F\n\u002F\u002F  Created by Briswell on 1\u002F13\u002F20.\n\u002F\u002F  Copyright © 2020 Briswell. All rights reserved.\n\u002F\u002F\n\nimport UIKit\nimport CropViewController\n\nclass ViewController: UIViewController {\n\n    @IBOutlet weak var txt: UITextView!\n    \n    override func viewDidLoad() {\n        super.viewDidLoad()\n        \u002F\u002F Do any additional setup after loading the view.\n    }\n\n    @IBAction func ocr(_ sender: Any) {\n        \u002F\u002Fif camera not supported\n        if !UIImagePickerController.isSourceTypeAvailable(.camera){\n            return\n        }\n        \u002F\u002Fpresent camera to take image\n        let pickerController = UIImagePickerController()\n        pickerController.delegate = self as UIImagePickerControllerDelegate & UINavigationControllerDelegate\n        pickerController.sourceType = .camera\n        self.present(pickerController, animated: true, completion: nil)\n    }\n    \n}\n\nextension ViewController: UIImagePickerControllerDelegate,UINavigationControllerDelegate{\n    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {\n        picker.dismiss(animated: true) {\n            guard let image = info[.originalImage] as? UIImage else { return  }\n            \u002F\u002Fpresent a crop image frame to focus on text content\n            let cropViewController = CropViewController.init(image: image)\n            cropViewController.delegate = self\n            self.present(cropViewController, animated: true, completion: nil)\n        }\n    }\n\n    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {\n        picker.dismiss(animated: true, completion: nil)\n    }\n}\n\nextension ViewController:CropViewControllerDelegate{\n    func cropViewController(_ cropViewController: CropViewController, didCropToImage image: UIImage, withRect cropRect: CGRect, angle: Int) {\n            cropViewController.dismiss(animated: true) {\n                \u002F\u002Fcall objective-c wrapper with expected language\n                let str = TesseractWrapper.ocr(usingTesseract: image, language: \"jpn\")\n                self.txt.text = str\n            }\n        }\n        \n        func cropViewController(_ cropViewController: CropViewController, didFinishCancelled cancelled: Bool) {            \n            cropViewController.dismiss(animated: true, completion: nil)            \n        }\n}\n",[193,247,245],{"__ignoreMap":83},[15,249,250],{},"Here is the test result with Japanese language. You can check with English and Vietnamese also with the same above way.",[77,252],{"className":253,"alt":83,"src":254,"style":85},[80,81,82],"https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2020\u002F01\u002F06173202\u002FIMG_8598-copy.png",[10,256,258],{"id":257},"conclusion","Conclusion",[15,260,261],{},"The text recognition on images is realizable task but there are some difficulties. The main problem is quality (size, lightning, contrast) of images. And each image has different problems so adding a filter tool so that user can edit manually, which is also an option. Refer to below link for improving image quality:",[15,263,264],{},[28,265,266],{"href":266,"rel":267},"https:\u002F\u002Fgithub.com\u002Ftesseract-ocr\u002Ftesseract\u002Fwiki\u002FImproveQuality",[32],{"title":83,"searchDepth":269,"depth":269,"links":270},2,[271,272,273,274,275],{"id":12,"depth":269,"text":13},{"id":48,"depth":269,"text":49},{"id":71,"depth":269,"text":72},{"id":166,"depth":269,"text":167},{"id":257,"depth":269,"text":258},[277,278],"tech talk","mobile","Briswell Vietnam Co Ltd","2020-01-17","Introduction. Tesseract is an optical character recognition engine for various operating systems. It is free software, released under the Apache License, and development has been sponsored by Google since 2006 until now (2020). This is the most popular and qualitative OCR-library. It uses artificial intelligence(AI) for text search and its recognition on images. It supports multiple platforms: MacOS, Window, Linux, but it can be compiled for iOS and Android also. ","md",{},true,"\u002Fnews\u002Ftesseract-ios",null,{"title":5,"description":281},"news\u002Ftesseract-ios","https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2020\u002F01\u002F06172902\u002Ftesseract.png","EwZZLtZO1ke26dkI6xlyT-gWRYTB1ezNRMNz-XgoNQA",1785320522167]