[{"data":1,"prerenderedAt":294},["ShallowReactive",2],{"news-item-\u002Fvi\u002Fnews\u002Ftesseract-ios":3},{"id":4,"title":5,"body":6,"category":279,"created by":282,"date":283,"description":284,"extension":285,"meta":286,"navigation":287,"path":288,"sections":289,"seo":290,"stem":291,"thumbnail":292,"__hash__":293},"content_vi\u002Fvi\u002Fnews\u002Ftesseract-ios.md","Áp dụng Tesseract vào iOS",{"type":7,"value":8,"toc":271},"minimark",[9,14,22,25,33,36,43,46,50,69,73,76,86,91,98,104,107,112,116,124,128,131,135,138,143,149,160,163,167,171,174,178,182,185,188,198,201,207,210,218,220,226,229,235,238,242,245,251,254,258,262,265],[10,11,13],"h2",{"id":12},"giới-thiệu","Giới thiệu",[15,16,17,21],"p",{},[18,19,20],"strong",{},"Tesseract"," là 1 OCR engine hỗ trợ trên nhiều nền tảng khác nhau, miễn phí, bản quyền Apache và được hỗ trợ phát triển bởi Google từ năm 2006 cho tới nay. Đây là 1 OCR engine phổ biến và hiệu quả nhất (cho tới hiện nay), sử dụng AI(trí tuệ nhân tạo) để xác định và nhận diện chữ.  Các hệ điều hành được hỗ trợ: MacOS, Window, Linux, nhưng có thể biên dịch cho iOS và Android để chạy trên 2 nền tảng này.",[15,23,24],{},"Đây là souce của Tessearct.",[15,26,27],{},[28,29,30],"a",{"href":30,"rel":31},"https:\u002F\u002Fgithub.com\u002Ftesseract-ocr\u002Ftesseract",[32],"nofollow",[15,34,35],{},"Số lượng  ngôn ngữ hỗ trợ lên đến 100, với mỗi file .traineddata là mô hình ngôn ngữ đã được huấn luyện.",[15,37,38,42],{},[28,39,40],{"href":40,"rel":41},"https:\u002F\u002Fgithub.com\u002Ftesseract-ocr\u002Ftessdata",[32]," ",[15,44,45],{},"Sau đây tôi sẽ trình bày cách áp dụng Tesseract trong iOS.",[10,47,49],{"id":48},"môi-trường-phát-triển","Môi trường phát triển",[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},"tải-xuống-và-nhúng-các-thư-viện-cần-thiết","Tải xuống và nhúng các thư viện cần thiết",[15,74,75],{},"Trước tiên hãy tạo mới 1 project với chế độ Single View App",[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},"tải-xuống-tesseract-411-phiên-bản-dành-cho-ios","Tải xuống Tesseract 4.1.1 phiên bản dành cho iOS",[15,92,93,94,97],{},"(Đây là phiên bản đã được biên dịch CHỈ dành cho iOS từ nguồn ",[28,95,30],{"href":30,"rel":96},[32],")",[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],{},"Sau khi tải xuống và giải nén, chúng ta sẽ có 2 thư mục \"include\" và \"lib\", hãy kéo thả chúng vào project của bạn.",[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},"tải-xuống-opencv","Tải xuống OpenCV",[15,117,118,119,123],{},"Tải từ link sau  ",[28,120,121],{"href":121,"rel":122},"https:\u002F\u002Fopencv.org\u002Freleases\u002F",[32]," và kéo thả chúng vào project của bạn.",[77,125],{"className":126,"alt":83,"src":127,"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,129,130],{},"Bấm command + R để chạy lại project để đảm bảo không có lỗi phát sinh.",[87,132,134],{"id":133},"tải-xuống-các-file-ngôn-ngữ-đã-được-huấn-luyện","Tải xuống các file ngôn ngữ đã được huấn luyện",[15,136,137],{},"Link tải  xuống:",[15,139,140],{},[28,141,40],{"href":40,"rel":142},[32],[15,144,145,146],{},"Trong bài viết này chúng ta sẽ kiểm tra thử với 3 ngôn ngữ: tiếng Anh, Nhật, Việt Nam. Do đó hãy tải xuống các mô hình sau đây và lưu chúng vào 1 thư mục đặt tên là  ",[18,147,148],{},"tessdata.",[51,150,151,154,157],{},[54,152,153],{},"eng.traineddata",[54,155,156],{},"jpn.traineddata",[54,158,159],{},"vie.traineddata",[15,161,162],{},"Sau đó kéo thả thư mục trên vào xcode project. CHÚ Ý: chọn chế độ \"Create folder references\" thay vì \"Create Group\" khi thêm thư mục vào dự án.",[77,164],{"className":165,"alt":83,"src":166,"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,168,170],{"id":169},"tiến-hành-lập-trình","Tiến hành lập trình",[15,172,173],{},"Bởi vì Tesseract được phát triển bằng ngôn ngử C++ cho nên chúng ta chỉ có thể lập trình bằng C++. Tạo 1 file C++ có tên là tesseract_wrapper.cpp như trong hình.",[77,175],{"className":176,"alt":83,"src":177,"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,179],{"className":180,"alt":83,"src":181,"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,183,184],{},"Lưu ý: nhớ chọn \"Also create a header file\" để Xcode tạo 1 file tesseract_wrapper.hpp sẵn.",[15,186,187],{},"tesseract_wrapper.hpp",[189,190,195],"pre",{"className":191,"code":193,"language":194},[192],"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",[196,197,193],"code",{"__ignoreMap":83},[15,199,200],{},"tesseract_wrapper.cpp",[189,202,205],{"className":203,"code":204,"language":194},[192],"\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",[196,206,204],{"__ignoreMap":83},[15,208,209],{},"Bởi vì Swift không thể gọi trực tiếp các hàm của C++ nên phải có file trung gian objective-C.",[51,211,212,215],{},[54,213,214],{},"TesseractWrapper.h",[54,216,217],{},"TesseractWrapper.mm (đuôi file phải là .mm để cho viêc biên dịch C++)",[15,219,214],{},[189,221,224],{"className":222,"code":223,"language":194},[192],"\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",[196,225,223],{"__ignoreMap":83},[15,227,228],{},"TesseractWrapper.mm",[189,230,233],{"className":231,"code":232,"language":194},[192],"\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",[196,234,232],{"__ignoreMap":83},[15,236,237],{},"Tạo 1 màn hình đơn giản chứa 1 textview và 1 button cho file ViewController.swift.",[77,239],{"className":240,"alt":83,"src":241,"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,243,244],{},"ViewController.swift",[189,246,249],{"className":247,"code":248,"language":194},[192],"\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",[196,250,248],{"__ignoreMap":83},[15,252,253],{},"Sau đây là kết quả kiểm thử với ngôn ngữ tiếng Nhật, chúng ta có thể làm tương tự với 2 ngôn ngữ Anh và Việt.",[77,255],{"className":256,"alt":83,"src":257,"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,259,261],{"id":260},"lời-kết","Lời kết",[15,263,264],{},"Nhận diện chữ trong hình ảnh hoàn toàn có thể nhưng có nhiều vấn đề xung quanh. Vấn đề chủ yếu lớn nhất là chất lượng của hình (độ tương phản, độ sáng, kích cỡ,..). Và mỗi hình lại có những vấn đề khác nhau do đó chúng ta có thể tạo 1 công cụ lọc màu để người dùng tự xử lý hình ảnh trước khi đưa vào xử lý nhận diện. Dưới đây là link tham khảo cho việc cải thiện chất lượng hình ảnh.",[15,266,267],{},[28,268,269],{"href":269,"rel":270},"https:\u002F\u002Fgithub.com\u002Ftesseract-ocr\u002Ftesseract\u002Fwiki\u002FImproveQuality",[32],{"title":83,"searchDepth":272,"depth":272,"links":273},2,[274,275,276,277,278],{"id":12,"depth":272,"text":13},{"id":48,"depth":272,"text":49},{"id":71,"depth":272,"text":72},{"id":169,"depth":272,"text":170},{"id":260,"depth":272,"text":261},[280,281],"tech talk","mobile","Briswell Vietnam Co Ltd","2020-01-17","Giới thiệu Tesseract là 1 OCR engine hỗ trợ trên nhiều nền tảng khác nhau, miễn phí, bản quyền Apache và được hỗ trợ phát triển bởi Google từ năm 2006 cho tới nay. Đây là 1 OCR engine phổ biến và hiệu quả nhất (cho tới hiện nay), sử dụng AI(trí tuệ nhân tạo) để xác định và nhận diện chữ.  Các hệ điều hành được hỗ trợ: MacOS, Window, Linux, nhưng có thể biên dịch cho iOS và Android để chạy trên 2 nền tảng này.","md",{},true,"\u002Fvi\u002Fnews\u002Ftesseract-ios",null,{"title":5,"description":284},"vi\u002Fnews\u002Ftesseract-ios","https:\u002F\u002Fhomepage-media.s3.ap-southeast-1.amazonaws.com\u002Fwp-content\u002Fuploads\u002F2020\u002F01\u002F06172902\u002Ftesseract.png","Q6w66FlXztd3Bu5G52iXcZvAz6G6voqsch-_Y-bd3I8",1785320527775]