Giter VIP home page Giter VIP logo

swiftytesseract's Introduction

SwiftyTesseract

This library is no longer maintained and will see no further updates.

I created this project out of a need to perform OCR on labels and machine readable formats in a warehouse environment. It served that purpose well enough, however I have not worked on that project in over 3 years and have not personally used this project since.

If you need OCR support in your application, I suggest you use the first party option by using the Text Recognition capabilities of Apple's Vision framework. If your language is not supported by Apple, I suggest you fork this project and maintain it yourself. If you need assistance migrating to another solution or in maintaining your own fork, you or your company can reach out to me to arrange a contract agreement.


SPM compatible swift-version platforms

GitHub Workflow Status Examples Status Linux ARM and macOS M1 Build Badge

Table of Contents

Version Compatibility

SwiftyTesseract Version Platforms Supported Swift Version
4.x.x iOS macOS Linux 5.3
3.x.x iOS 5.0 - 5.2
2.x.x iOS 4.2
1.x.x iOS 4.0 - 4.1

Known Issue Submitting to App Store Connect

When submitting to App Store Connect, libtesseract.framework will need to be removed from your app bundle before submission. This can be achieved through a post-build action in your application target's scheme by running the following:

rm -rf "${TARGET_BUILD_DIR}/${PRODUCT_NAME}.app/Frameworks/libtesseract.framework"

If you are facing this error after already building your project, you will need to clear your derived data and perform a clean build.

This issue currently affects all binary Swift packages and is not unique to this project. Please see SwiftyTesseract issue #83 and libtesseract issue #3 for more information.

Develop

Develop should be considered unstable and API breaking changes could happen at any time. If you need to utilize some changes contained in develop, adding the specific commit is highly recommended:

.package(
    url: "https://github.com/SwiftyTesseract/SwiftyTesseract.git",
    // This is just an example of a commit hash, do not just copy and paste this into your Package.swift
    .revision("0e0c6aca147add5d5750ecb7810837ef4fd10fc2")
)

SwiftyTesseract 3.x.x Support

4.0.0 contains a lot of major breaking changes and there have been issues when migrating from Xcode 11 to 12 with versions 3.x.x. The support/3.x.x branch has been created to be able to address any issues for those who are unable or unwilling to migrate to the latest version. This branch is only to support blocking issues and will not see any new features.

Support for Cocoapods and Carthage Dropped

As the Swift Package Manager improves year over year, I have been decided to take advantage of binary Swift Packages that were announced during WWDC 2020 to eliminate having the dependency files being built ad-hoc and served out of the main source repo. This also has the benefit for being able to support other platforms via Swift Package Manager like Linux because the project itself is no longer dependent on Tesseract being vendored out of the source repository. While I understand this may cause some churn with existing projects that rely on SwiftyTesseract as a dependency, Apple platforms themselves have their own first-party OCR support through the Vision APIs.

SwiftyTesseract class renamed to Tesseract

The SwiftyTesseract class name felt a bit verbose and is more descriptive of the project than the class itself. To disambiguate between Google's Tesseract project and SwiftyTesseract's Tesseract class, all mentions of the class will be displayed as a code snippet: Tesseract.

Using SwiftyTesseract in Your Project

Import the module

import SwiftyTesseract

There are two ways to quickly instantiate SwiftyTesseract without altering the default values. With one language:

let tesseract = Tesseract(language: .english)

Or with multiple languages:

let tesseract = Tesseract(languages: [.english, .french, .italian])

Performing OCR

Platform Agnostic

Pass an instance of Data derived from an image to performOCR(on:)

let imageData = try Data(contentsOf: urlOfYourImage)
let result: Result<String, Tesseract.Error> = tesseract.performOCR(on: imageData)

Combine

Pass an instance of Data derived from an image to performOCRPublisher(on:)

let imageData = try Data(contentsOf: urlOfYourImage)
let result: AnyPublisher<String, Tesseract.Error> = tesseract.performOCRPublisher(on: imageData)

UIKit

Pass a UIImage to the performOCR(on:) or performOCRPublisher(on:) methods:

let image = UIImage(named: "someImageWithText.jpg")!
let result: Result<String, Error> = tesseract.performOCR(on: image)
let publisher: AnyPublisher<String, Error> = tesseract.performOCRPublisher(on: image)

AppKit

Pass a NSImage to the performOCR(on:) or performOCRPublisher(on:) methods:

let image = NSImage(named: "someImageWithText.jpg")!
let result: Result<String, Error> = tesseract.performOCR(on: image)
let publisher: AnyPublisher<String, Error> = tesseract.performOCRPublisher(on: image)

Conclusion

For people who want a synchronous call, the performOCR(on:) method provides a Result<String, Error> return value and blocks on the thread it is called on.

The performOCRPublisher(on:) publisher is available for ease of performing OCR in a background thread and receiving results on the main thread (only available on iOS 13.0+ and macOS 10.15+):

let cancellable = tesseract.performOCRPublisher(on: image)
  .subscribe(on: backgroundQueue)
  .receive(on: DispatchQueue.main)
  .sink(
    receiveCompletion: { completion in 
      // do something with completion
    },
    receiveValue: { string in
      // do something with string
    }
  )

The publisher provided by performOCRPublisher(on:) is a cold publisher, meaning it does not perform any work until it is subscribed to.

Extensibility

The major downside to the pre-4.0.0 API was it's lack of extensibility. If a user needed to set a variable or perform an operation that existed in the Google Tesseract API but didn't exist on the SwiftyTesseract API, the only options were to fork the project or create a PR. This has been remedied by creating an extensible API for Tesseract variables and Tesseract functions.

Tesseract Variable Configuration

Starting in 4.0.0, all public instance variables of Tesseract have been removed in favor of a more extensible and declarative API:

let tesseract = Tesseract(language: .english) {
  set(.disallowlist, "@#$%^&*")
  set(.minimumCharacterHeight, .integer(35))
  set(.preserveInterwordSpaces, .true)
}
// or
let tesseract = Tesseract(language: .english)
tesseract.configure {
  set(.disallowlist, "@#$%^&*")
  set(.minimumCharacterHeight, .integer(35))
  set(.preserveInterwordSpaces, .true)
}

The pre-4.0.0 API looks like this:

let swiftyTesseract = SwiftyTesseract(language: .english)
swiftyTesseract.blackList = "@#$%^&*"
swiftyTesseract.minimumCharacterHeight = 35
swiftyTesseract.preserveInterwordSpaces = true

Tesseract.Variable

Tesseract.Variable is a new struct introduced in 4.0.0. It's definition is quite simple:

extension Tesseract {
  public struct Variable: RawRepresentable {
    public init(rawValue: String) {
      self.init(rawValue)
    }
    
    public init(_ rawValue: String) {
      self.rawValue = rawValue
    }
    
    public let rawValue: String
  }
}

extension Tesseract.Variable: ExpressibleByStringLiteral {
  public typealias StringLiteralType = String

  public init(stringLiteral value: String) {
    self.init(value)
  }
}

// Extensions containing the previous API variables available as members of SwiftyTesseract
public extension Tesseract.Variable {
  static let allowlist: Tesseract.Variable = "tessedit_char_whitelist"
  static let disallowlist: Tesseract.Variable = "tessedit_char_blacklist"
  static let preserveInterwordSpaces: Tesseract.Variable = "preserve_interword_spaces"
  static let minimumCharacterHeight: Tesseract.Variable = "textord_min_xheight"
  static let oldCharacterHeight: Tesseract.Variable = "textord_old_xheight"
}

The problem here is that the library doesn't cover all the cases. What if you wanted to set Tesseract to only recognize numbers? You may be able to set the allowlist to only recognize numerals, but the Google Tesseract API already has a variable that does that: "classify_bln_numeric_mode".

Extending the library to make use of that variable could look something like this:

tesseract.configure {
  set("classify_bln_numeric_mode", .true)
}
// Or extend Tesseract.Variable to get a clean trailing dot syntax:
// Using ExpressibleByStringLiteral conformance
extension Tesseract.Variable {
  static let numericMode: Tesseract.Variable = "classify_bln_numeric_mode"
}
// Using initializer
extension Tesseract.Variable {
  static let numericMode = Tesseract.Variable("classify_bln_numeric_mode")
}

tesseract.configure {
  set(.numericMode, .true)
}

perform(action:)

Another issue that I've seen come up several times is "Can you implement X Tesseract feature" as a feature request. This has the same implications as the old property-based accessors for setting Tesseract variables. The perform(action:) method allows users full access to the Tesseract API in a thread-safe manner.

This comes with one major caveat: You will be completely responsible for managing memory when dealing with the Tessearct API directly. Using the Tesseract C API means that ARC will not help you. If you use this API directly, make sure your instrument your code and check for leaks. Swift's defer functionality pairs really well with managing memory when dealing directly with C APIs; check out Sources/SwiftyTesseract/Tesseract+OCR.swift for examples of using defer to release memory.

All of the library methods provided on Tesseract other than Tesseract.perform(action:) and Tesseract.configure(_:) are implemented as extensions using only Tesseract.perform(action:) to access the pointer created during initialization. To see this in action see the implementation of performOCR(on:) in Sources/SwiftyTesseract/Tesseract+OCR.swift

As an example, let's implement issue #66 using perform(action:):

import SwiftyTesseract
import libtesseract

public typealias PageSegmentationMode = TessPageSegMode
public extension PageSegmentationMode {
  static let osdOnly = PSM_OSD_ONLY
  static let autoOsd = PSM_AUTO_OSD
  static let autoOnly = PSM_AUTO_ONLY
  static let auto = PSM_AUTO
  static let singleColumn = PSM_SINGLE_COLUMN
  static let singleBlockVerticalText = PSM_SINGLE_BLOCK_VERT_TEXT
  static let singleBlock = PSM_SINGLE_BLOCK
  static let singleLine = PSM_SINGLE_LINE
  static let singleWord = PSM_SINGLE_WORD
  static let circleWord = PSM_CIRCLE_WORD
  static let singleCharacter = PSM_SINGLE_CHAR
  static let sparseText = PSM_SPARSE_TEXT
  static let sparseTextOsd = PSM_SPARSE_TEXT_OSD
  static let count = PSM_COUNT
}

public extension Tesseract {
  var pageSegmentationMode: PageSegmentationMode {
    get {
      perform { tessPointer in
        TessBaseAPIGetPageSegMode(tessPointer)
      }
    }
    set {
      perform { tessPointer in
        TessBaseAPISetPageSegMode(tessPointer, newValue)
      }
    }
  }
}

// usage
tesseract.pageSegmentationMode = .singleColumn

If you don't care about all of the boilerplate needed to make your call site feel "Swifty", you could implement it simply like this:

import SwiftyTesseract
import libtesseract

extension Tesseract {
  var pageSegMode: TessPageSegMode {
    get {
      perform { tessPointer in
        TessBaseAPIGetPageSegMode(tessPointer)
      }
    }
    set {
      perform { tessPointer in
        TessBaseAPISetPageSegMode(tessPointer, newValue)
      }
    }
  }
}

// usage
tesseract.pageSegMode = PSM_SINGLE_COLUMN

ConfigurationBuilder

The declarative configuration syntax is achieved by accepting a function builder with functions that have a return value of (TessBaseAPI) -> Void. Using the previous example of extending the library to set the page segmentation mode of Tesseract, you could also create a function with a return signature of (TessBaseAPI) -> Void to utilize the declarative configuration block either during initialization or through Tesseract.configure(:_):

import SwiftyTesseract
import libtesseract

func setPageSegMode(_ pageSegMode: TessPageSegMode) -> (TessBaseAPI) -> Void {
  return { tessPointer in
    TessBaseAPISetPageSegMode(tessPointer, pageSetMode)
  }
}

let tesseract = Tesseract(language: .english) {
  setPageSegMode(PSM_SINGLE_COLUMN)
}
// or post initialization
tesseract.configure {
  setPageSegMode(PSM_SINGLE_COLUMN)
}

(The information for what to implement for this example was found in the Tesseract documentation)

Conclusion

The major feature of 4.0.0 is it's lack of features. The core of Tesseract is less than 130 lines of code, with the remainder of the code base implemented as extensions. I have attempted to be as un-opinionated as possible while providing an API that feels right at home in Swift. Users of the library are not limited to what I have time for or what other contributors to the project are able to contribute. Now that this API is available, additions to the API surface of the library will be very selective. There should no longer be any restrictions to users of the library given the extensibility.

A Note on Initializer Defaults

The full signature of the primary Tesseract initializer is

public init Tesseract(
  languages: [RecognitionLanguage], 
  dataSource: LanguageModelDataSource = Bundle.main, 
  engineMode: EngineMode = .lstmOnly,
  @ConfigurationBuilder configure: () -> (TessBaseAPI) -> Void = { { _ in } }
)

The bundle parameter is required to locate the tessdata folder. This will need to be changed if Tesseract is not being implemented in your application bundle or if you are developing a Swift Package project (in this case you would need to specify Bundle.module, see Tests/SwiftyTesseractTests/SwiftyTesseractTests.swift for an example). The engine mode dictates the type of .traineddata files to put into your tessdata folder. .lstmOnly was chosen as a default due to the higher speed and reliability found during testing, but could potentially vary depending on the language being recognized as well as the image itself. See Which Language Training Data Should You Use? for more information on the different types of .traineddata files that can be used with SwiftyTesseract

libtesseract

Tesseract and it's dependencies are now built and distributed as an xcframework under the SwiftyTesseract/libtesseract repository for Apple platforms. Any issues regarding the build configurations for those should be raised under that repository.

Installation

Swift Package Manager is now the only supported dependency manager for bringing SwiftyTesseract into your project.

Apple Platforms

// Package.swift
// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription

let package = Package(
  name: "AwesomePackage",
  platforms: [
    // These are the minimum versions libtesseract supports
    .macOS(.v10_13),
    .iOS(.v11),
  ],
  products: [
    .library(
      name: "AwesomePackage",
      targets: ["AwesomePackage"]
    ),
  ],
  dependencies: [
    .package(url: "https://github.com/SwiftyTesseract/SwiftyTesseract.git", .upToNextMajor(from: "4.0.0"))
  ],
  targets: [
    .target(
      name: "AwesomePackage",
      dependencies: ["SwiftyTesseract"]
    ),
  ]
)

Linux

// Package.swift
// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription

let package = Package(
  name: "AwesomePackage",
  products: [
    .library(
      name: "AwesomePackage",
      targets: ["AwesomePackage"]
    ),
  ],
  dependencies: [
    .package(url: "https://github.com/SwiftyTesseract/SwiftyTesseract.git", .upToNextMajor(from: "4.0.0"))
  ],
  targets: [
    .target(
      name: "AwesomePackage",
      dependencies: ["SwiftyTesseract"]
    ),
  ]
)

Linux Specific System Configuration

You will need to install libtesseract-dev (must be a >= 4.1.0 release) and libleptonica-dev on the host system before running any application that has a dependency on SwiftyTesseract. For Ubuntu (or Debian based distributions) that may look like this:

apt-get install -yq libtesseract-dev libleptonica-dev

The Dockerfiles in the docker directory and Examples/VaporExample provide an example. The Ubuntu 20.04 apt repository ships with compatible versions of libtesseract-dev and libleptonica-dev. If you are building against another distribution, then you will need to research what versions of the libraries are available or how to get appropriate versions installed into your image or system.

Additional configuration

Shipping language training files as part of an application bundle

  1. Download the appropriate language training files from the tessdata, tessdata_best, or tessdata_fast repositories.
  2. Place your language training files into a folder on your computer named tessdata
  3. Drag the folder into your project. You must enure that "Create folder references" is selected or Tesseract will not be successfully instantiated. tessdata_folder_example

Shipping language training files as part of a Swift Package

If you choose to keep the language training data files under source control, you will want to copy your tessdata directory as a package resource:

let package = Package(
  // Context omitted for brevity. The full Package.swift for this example
  // can be found in Examples/VaporExample/Package.swift
  targets: [
    .target(
      name: "App",
      dependencies: [
        .product(name: "Vapor", package: "vapor"),
        "SwiftyTesseract"
      ],
      // The path relative to your Target directory. In this example, the path
      // relative to the source root would be Sources/App/tessdata
      resources: [.copy("tessdata")],
    )
  ]
)

If you prefer not to keep the language training data files under source control see the instructions for using a custom location below.

Custom Location

Thanks to Minitour, developers now have more flexibility in where and how the language training files are included for Tesseract to use. This may be beneficial if your application supports multiple languages but you do not want your application bundle (or git repo) to contain all the possible training files needed to perform OCR (each language training file can range from 1 MB to 15 MB). You will need to provide conformance to the following protocol:

public protocol LanguageModelDataSource {
  var pathToTrainedData: String { get }
}

Then pass it to the Tesseract initializer:

let customDataSource = CustomDataSource()
let tesseract = Tesseract(
  language: .english, 
  dataSource: customDataSource, 
  engineMode: .lstmOnly
)

See the testDataSourceFromFiles() test in SwiftyTesseractTests.swift (located near the end of the file) for an example on how this can be done.

Language Training Data Considerations

There are three different types of .traineddata files that can be used in Tesseract: tessdata, tessdata_best, or tessdata_fast that correspond to Tesseract EngineModes .tesseractOnly, .lstmOnly, and .tesseractLstmCombined. .tesseractOnly uses the legacy Tesseract engine and can only use language training files from the tessdata repository. During testing of SwiftyTesseract, the .tesseractOnly engine mode was found to be the least reliable. .lstmOnly uses a long short-term memory recurrent neural network to perform OCR and can use language training files from either tessdata_best, tessdata_fast, or tessdata repositories. During testing, tessdata_best was found to provide the most reliable results at the cost of speed, while tessdata_fast provided results that were comparable to tessdata (when used with .lstmOnly) and faster than both tessdata and tessdata_best. .tesseractLstmCombined can only use language files from the tessdata repository, and the results and speed seemed to be on par with tessdata_best. For most cases, .lstmOnly along with the tessdata_fast language training files will likely be the best option, but this could vary depending on the language and application of SwiftyTesseract in your project.

Custom Trained Data

The steps required are the same as the instructions provided in additional configuration. To utilize custom .traineddata files, simply use the .custom(String) case of RecognitionLanguage:

let tesseract = Tesseract(language: .custom("custom-traineddata-file-prefix"))

For example, if you wanted to use the MRZ code optimized OCRB.traineddata file provided by Exteris/tesseract-mrz, the instance of Tesseract would be created like this:

let tesseract = Tesseract(language: .custom("OCRB"))

You may also include the first party Tesseract language training files with custom training files:

let tesseract = Tesseract(languages: [.custom("OCRB"), .english])

Recognition Results

When it comes to OCR, the adage "garbage in, garbage out" applies. SwiftyTesseract is no different. The underlying Tesseract engine will process the image and return anything that it believes is text. For example, giving SwiftyTesseract this image raw_unprocessed_image yields the following:

a lot of jibberish...
‘o 1 $ : M |
© 1 3 1; ie oI
LW 2 = o .C P It R <0f
O — £988 . 18 |
SALE + . < m m & f f |
7 Abt | | . 3 I] R I|
3 BE? | is —bB (|
* , § Be x I 3 |
...a lot more jibberish

You can see that it picked SALE out of the picture, but everything else surrounding it was still attempted to be read regardless of orientation. It is up to the individual developer to determine the appropriate way to edit and transform the image to allow SwiftyTesseract to render text in a way that yields predictable results. Originally, SwiftyTesseract was intended to be an out-of-the-box solution, however, the logic that was being added into the project made too many assumptions, nor did it seem right to force any particular implementation onto potential adopters. SwiftyTesseractRTE provides a ready-made solution that can be implemented in a project with a few lines of code that should suit most needs and is a better place to start if the goal for your project is to get OCR into an application with little effort.

Contributions Welcome

SwiftyTesseract does not implement the full Tesseract API. Given the extensible nature of the library, you should try to implement any additions yourself. If you think those additions would be useful to everyone else as well, please open a pull request! Please see Contributing to SwiftyTesseract for the full guidelines on creating issues and opening pull requests to the project.

Documentation

Official documentation for SwiftyTesseract can be found here

Attributions

SwiftyTesseract would not be possible without the work done by the Tesseract team.

See the Attributions section in the libtesseract repo for a full list of vendored dependencies and their licenses.

swiftytesseract's People

Contributors

gmw avatar hactar avatar juliankahnert avatar minitour avatar steven0351 avatar vi4m avatar wacumov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swiftytesseract's Issues

No Project file

I have dowloaded the zip file. it contains the framework but not executable file like .xcodeproj or .xcworkspace etc. can you please upload with that ?
or kindly tell me how to use this framework into out project ?

Question: Any plans for PDF rendering

Hey,
I found your project and it I instantly loved your Swifty tesseract api!!

Since I am currently looking for a OCR + PDF renderer for PDF Archive Viewer, I am wondering if there are any plans to build a similiar method like this in the API?

Best regards, Julian

Page segmentation modes (--psm)

Checklist

Is your feature request related to a problem? Please describe.
Like command line usage:

 tesseract imagename outputbase [-l lang] [--oem ocrenginemode] [--psm pagesegmode]

 tesseract --help-psm
Page segmentation modes:
  0    Orientation and script detection (OSD) only.
  1    Automatic page segmentation with OSD.
  2    Automatic page segmentation, but no OSD, or OCR. (not implemented)
  3    Fully automatic page segmentation, but no OSD. (Default)
  4    Assume a single column of text of variable sizes.
  5    Assume a single uniform block of vertically aligned text.
  6    Assume a single uniform block of text.
  7    Treat the image as a single text line.
  8    Treat the image as a single word.
  9    Treat the image as a single word in a circle.
 10    Treat the image as a single character.
 11    Sparse text. Find as much text as possible in no particular order.
 12    Sparse text with OSD.
 13    Raw line. Treat the image as a single text line,
       bypassing hacks that are Tesseract-specific.

Could you make a function to set psm (aka Page segmentation modes) on this library.

Describe the solution you'd like
Like EngineMode, it would be nice if you make TessPageSegMode enum and public function to set
psm setting.
Something like

public enum PageSegMode: TessPageSegMode.RawValue

public func setPageSegMode(_ pageSegMode: PageSegMode) 

Describe alternatives you've considered
Or at least, please make this API public for used.

TESS_API void TESS_CALL TessBaseAPISetPageSegMode(TessBaseAPI* handle,
                                                  TessPageSegMode mode);

Pod install: Error installing SwiftyTesseract

After adding pod 'SwiftyTesseract' to my podfile and trying pod install with CocoaPods version 1.5.3, I get the following error message:

[!] Unable to find a specification for SwiftyTesseract`

Unable to install iOS application on device

Checklist

Describe the bug
I get the following error using SwiftPM in Xcode for an iOS project, while installing the app.

Details

Unable to install "<app name>"
Domain: com.apple.dt.MobileDeviceErrorDomain
Code: -402620388
--
No code signature found.
Domain: com.apple.dt.MobileDeviceErrorDomain
Code: -402620388
User Info: {
    DVTRadarComponentKey = 261622;
    MobileDeviceErrorCode = "(0xE800801C)";
    "com.apple.dtdevicekit.stacktrace" = (
	0   DTDeviceKitBase                     0x000000011f83190f DTDKCreateNSErrorFromAMDErrorCode + 220
	1   DTDeviceKitBase                     0x000000011f8700f4 __90-[DTDKMobileDeviceToken installApplicationBundleAtPath:withOptions:andError:withCallback:]_block_invoke + 155
	2   DVTFoundation                       0x00000001029bccef DVTInvokeWithStrongOwnership + 71
	3   DTDeviceKitBase                     0x000000011f86fe35 -[DTDKMobileDeviceToken installApplicationBundleAtPath:withOptions:andError:withCallback:] + 1440
	4   IDEiOSSupportCore                   0x000000011f6e0d84 __118-[DVTiOSDevice(DVTiPhoneApplicationInstallation) processAppInstallSet:appUninstallSet:installOptions:completionBlock:]_block_invoke.292 + 3513
	5   DVTFoundation                       0x0000000102aeb45a __DVT_CALLING_CLIENT_BLOCK__ + 7
	6   DVTFoundation                       0x0000000102aed07c __DVTDispatchAsync_block_invoke + 1191
	7   libdispatch.dylib                   0x00007fff20d5d52d _dispatch_call_block_and_release + 12
	8   libdispatch.dylib                   0x00007fff20d5e717 _dispatch_client_callout + 8
	9   libdispatch.dylib                   0x00007fff20d6454e _dispatch_lane_serial_drain + 606
	10  libdispatch.dylib                   0x00007fff20d6501b _dispatch_lane_invoke + 375
	11  libdispatch.dylib                   0x00007fff20d6eb9b _dispatch_workloop_worker_thread + 819
	12  libsystem_pthread.dylib             0x00007fff20ea44f2 _pthread_wqthread + 314
	13  libsystem_pthread.dylib             0x00007fff20ea34c3 start_wqthread + 15
);
}
--


System Information

macOS Version 11.0 (Build 20A5364e)
Xcode 12.0 (17210.1)

Expected behavior
The application should install and run on the device.

Versions

  • Xcode: 12.0 (17210.1)
  • Swift: 5.3 (swiftlang-1200.0.28.1 clang-1200.0.30.1)
  • iOS: 14.0 (18A5373a)
  • SwiftyTesseract: develop branch

Failed loading language 'eng'.

Hello!
I have problem with SwiftyTesseract initialization. When I'm trying to init i get the error:

Error opening data file /Users/username/Library/Developer/CoreSimulator/Devices/399FC739-54D5-49C1-8F97-06962AA2B028/data/Containers/Bundle/Application/306FED96-9738-477C-922D-2ACA51AFC8D7/app name/tessdata/eng.traineddata
Please make sure the TESSDATA_PREFIX environment variable is set to your "tessdata" directory.
Failed loading language 'eng'
Tesseract couldn't load any languages!

I've downloaded tessdata from links which you provided. Also I added folder tessdata to the project and put into it correct trained data. I have no ideas how to solve it, but my previous experience with Gali8 Tessecact wrapper was fine.

I'm using XCode 10, iOS simulator and SwiftyTesseract v.2.0

Exporting Framework Error

Hello,
How to export this framework with included libraries?
I tried few methods but I'm receiving this error while the sdk is imported in any class:
Missing required modules: 'libleptonica', 'libtesseract'

Can we read "Text + Any Emoji"

Hello,
I want to read "text + emoji", but there is issue with emoji
when I read this image it prints "This is for testing =\n"
Let me know if any one help
attached Image which I want to recognise
testImg

Xode 12.0 beta 5 not build

Снимок экрана 2020-08-21 в 11 44 16 AM

**Versions** * Xcode: 12.0 beta 5 * Swift: 5.0 * iOS: 14 * SwiftyTesseract: 3.1.2

Additional context
Please screenshot

read_params_file: parameter not found: enable_new_segsearch

First of all: Thanks for your work!

I´ve encountered the following problem after selecting an UIImage and trying to run SwiftyTesseract:

func performImageRecognition(_ image: UIImage) {
    print("performImageRecognition() called, setting language...")
    let swiftyTesseract = SwiftyTesseract(languages: [.english])
    print("performOCR()...")
    
    swiftyTesseract.performOCR(on: image) { (recognizedString) in
        print("performOCR done...")
        guard let recognizedString = recognizedString else { return }
        print(recognizedString)
    }
    print("recognition done")
}

When executing I got the following error:

performImageRecognition() called, setting language...
read_params_file: parameter not found: enable_new_segsearch

After that line, the app crashes. I haven´t found a solution until now. Does someone has an idea?

Thanks in advance!

Update Tesseract Libs

According to the logs, 4.0.0-beta.1 is included with SwiftTesseract - the latest version appears to be beta 4.

I've tried playing with the build scripts from g8, but can't get it to build on my machine, so an update would be greatly appreciated.

While adding with cocoapods getting below error

Installing SwiftyTesseract (2.2.0)
[!] Unable to determine Swift version for the following pods:

  • SwiftyTesseract-library does not specify a Swift version and none of the targets (Pods) integrating it have the SWIFT_VERSION attribute set. Please contact the author or set the SWIFT_VERSION attribute in at least one of the targets that integrate this pod.

setTesseractVariable has no effect for .lstmOnly

I found out a strange issue.

setTesseractVariable(.preserveInterwordSpaces, value: preserveInterwordSpaces ? "1" : "0")

has no effect if engineMode is set to .lstmOnly.

But setting preserve_interword_spaces parameter should has effect for Tesseract 4 since this commit -
tesseract-ocr/tesseract@ea557a3

Currently the library uses Tesseract 4.0.0beta-4 and that commit was pushed before beta-4 was released.
This Tesseract-OCR-iOS fork also uses Tesseract 4. And setting preserve_interword_spaces works fine there.

@Steven0351 do you have any thoughts what can be the cause?

Language data source protocol

After briefly inspecting the code I noticed that all the traindata files must be included within the application bundle. These files can range from few kilobytes to dozens of megabytes.

My suggestion is, that instead of having a bundle passed as a parameter for the location of the files, there will be a protocol, (aka) data source, which developers can implement to load the tessdata files from any location they want.

This will allow us to download models based on the user's needs. For example, users living in Canada may need only the English and French models, but people living in Israel may only need the Hebrew and Arabic models.

For example:

protocol LanguageModelDataSource {
    var pathToTrainedData: String
}
extension Bundle: LanguageModelDataSource {
    var pathToTrainedData: String {
          return bundleURL.appendingPathComponent("tessdata").path
    }
}
class MyCustomDirectoy: LanguageModelDataSource {
    var pathToTrainedData: String {
          let documentsFolderURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
         return documentsFolderURL.appendingPathComponent("tessdata").path
    }
}

Swift Package Manager Support

Checklist

Is your feature request related to a problem? Please describe.
I'm developing for Linux, but it seems CocoaPods and Carthage doesn't support Linux.

Describe the solution you'd like
Would you like to add Swift Package Manager support for SwiftyTesseract? It just works for Linux!

Describe alternatives you've considered
Is there any other method to add SwiftyTesseract to my project? I noticed that you claimed using CocoaPods or Carthage are the only supported methods.

SwiftyTesseract for MacOS APP

Checklist

Is your feature request related to a problem? Please describe.
I wanted try Tesseract for Swift but it appears that that its only for iOS apps.

Describe the solution you'd like
Im beginner at coding on apple devices (project of myself only) and i don't know if its possible to extend this wrapper to macOS apps?

Describe alternatives you've considered
If its only for iOS, why not create new project for MacOS Apps?

Additional context
[!] The platform of the target 'test-app' (macOS 10.15) is not compatible with 'SwiftyTesseract (3.1.2)', which does not support 'macOS'.

How could I build a ios library for ios-tesseract by myself?

First of all ,It is a great job. thank you very muck.
I read the code ,but I still cant find a way to rebuild a " ios-tesseract" like this.
The tesseract is updated frequency, so ...it is time for updating .
Could you submit a video or a wiki to explain the steps ,how to build a library like this.
many Thanks.

Missing Modules Lib tesseract and Lib leptonica

I build and successfully run one simple app by downloading swiftytesseract and after that I shared code with my team and when they open my code they found following error

"required modules lib tesseract and lib leptonica"

This is happening with everyone, Its a critical issue

Are we missing anything ?

required module missing libtesseract libleptionica always

**required module missing libtesseract libleptionica **
"required module missing libtesseract libleptionica",Clone the swiftytesseract repo and build it, then took the .framework file and I used in my blank project which just gives image and uses tesseract code.

To Reproduce
clone or download the zip file build it and take swiftytesseract.framework. Add this in-app code and build it and run then app will work. Now distribute this code to another development MacBook and build your app it will throw an error saying "required module missing libtesseract libleptionica".
This is happening with every developer (34+ developers )

Expected behaviour
Once any app build with embed & sign (swiftytesseract.framework) same code should work on all the machines instead of throwing error for all.

Versions

  • Xcode: 11.3.1
  • Swift: 5.1
  • iOS: 13.2
  • SwiftyTesseract:2.2.0 and latest version

Dependency Management
Are you using CocoaPods or Carthage? What version?
Tried with CocoaPods and error exist

Additional context
Every time developer needs to clone this repo and build code then take ".framework" file to make it work. it's so horrible

Default config of Tesseract unable to read number-only images

Hi and thank you for this great wrapper around Tesseract. I've successfully used this library to scan sparse text on websites. I've even written tests to optimize the accuracy of text detection and succeeded in reaching an accuracy of 98.3% on German text. But there is one specific issue which must be a Tesseract configuration problem, because the image quality of the data is great and values are sometimes read perfectly fine but sometimes it just doesn't read anything. I mean nothing, not even a single number!

Here are a few example year numbers that I can't read:
1923
1948
1960

The behavior is really weird, it's like flickering, sometimes it seems to accept the given as text and read it perfectly well. But most of the time it just seems to ignore the entire text ... as if it was no text to Tesseract just because it's a number.

I'm using the latest SwiftyTesseract, using this configuration:

SwiftyTesseract(languages: [.german, .english], engineMode: .lstmOnly)

The models are tess_fast in case you want to know, my preprocessing steps (color invert, contrast decrease, binarize) are based on GPUImage and give clear black text on white background results.

My personal guess is, that this line where you simply call TessBaseAPIGetUTF8Text is the problem. I can't find good documentation on Tesseract to prove this, but looking around this line within the Tesseract header, it looks to me like TessBaseAPIGetHOCRText, TessBaseAPIGetBoxText, TessBaseAPIGetUNLVText and specifically TessBaseAPIAllWordConfidences could be useful to add as a configuration option to SwiftyTesseract. I'm not sure what these APIs do, but apparently TessBaseAPIGetUTF8Text isn't a good fit for reading years. Or maybe there's a configuration option to fix this issue elsewhere?

Do you have any idea what the issue could be? I would gladly post a PR with an added configuration option if I was given any hint on where I can read the documentation about these methods. I couldn't find any ...

I read on StackOverflow somewhere that this could have to do with a wrong configuration of "page segmentation mode" in Tesseract. Specifically the recommendation for numbers is to use mode "13 Raw line". It would be great to have at least this as a configuration option.

No such module 'libtesseract'

Hello,

I have added your project manually. But when I run it says "No such module 'libtesseract'"

Can you please help me ?

Make configuration API available post-initialization.

Since this is now the only way to set tesseract variables, there should also be a member function with a signature that looks similar to this:

public func configure(@ConfigurationBuilder configuration: () -> (TessBaseAPI) -> Void) {
  configuration()(tesseract)
}

Swift 5 conversion

Hi there! Sorry for bothering you. When can we expect swift 5 conversion?

custom traineddata error

Checklist

Describe the bug
A clear and concise description of what the bug is.

The custom mrz traineddata part sais:
For example, if you wanted to use the MRZ code optimized OCRB.traineddata file provided by Exteris/tesseract-mrz, the instance of Tesseract would be created like this:

if I use the file from the linked repo like this:
SwiftyTesseract(language: .custom("OCRB"), dataSource: Bundle(identifier: "xxx") ?? Bundle(for: yyy.self), engineMode: .lstmOnly)

the following error is the result:

Error: LSTM requested, but not present!! Loading tesseract.

I tried the original traineddata files from tessdata folder: eng, hun

SwiftyTesseract(language: .custom("eng"), dataSource: Bundle(identifier: "xxx") ?? Bundle(for: yyy.self), engineMode: .tesseractLstmCombined)

those are OK.

Sample Code

Expected behavior
A clear and concise description of what you expected to happen.

Versions

  • Xcode: 11.7
  • Swift: 5
  • iOS: 13.6
  • SwiftyTesseract: 3.1.2

Additional context
Add any other context about the problem here.

Getting error after pod update using CocoaPods 1.7.4

For our project we wanted to upgrade the Lottie-library, and noticed there was a new CocoaPods version 1.7.4.
So I installed that and ran pod update.

After that, our project is no longer building, and we're getting an error from the SwiftyTesseract lib, even though we didn't update or change that. We're running v2.2.0.
It does apparently not work either when using CocoaPods 1.5.3.
Screenshot 2019-07-18 at 13 19 59

Memory Leak when processing a cgImage

Memory does not seem to be released when processing UIImage created with a CGImage, which was created off of a CIImage.

Example:

public func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
    let context = CIContext.init(options: nil)
    let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
    let ciImage = CIImage(cvPixelBuffer: imageBuffer)
    let cgImage = context.createCGImage(ciImage, from: ciImage.extent)!
    let image = UIImage(cgImage: cgImage)

    tesseract.performOCR(on: image) { _ in } // Called repeatedly
}

Instruments:
mem

*I know I could also create an image with a CIImage (UIImage(ciImage: ciImage)) and this would work well, but even something like above should.

Error when archiving

I've used the latest version which support iOS 9.0 and when archiving, the compiler return the error:
ld: could not reparse object file in bitcode bundle: 'Invalid bitcode version (Producer: '902.0.39.1_0' Reader: '900.0.39.2_0')', using libLTO version 'LLVM version 9.0.0, (clang-900.0.39.2)' for architecture armv7
Can you help to check this error? Thanks

PDF OCR progress callback

Hi @Steven0351,
I thought it might be better to have this conversation about a progress feature here in a new issue.

As mentioned in #33 I was looking for some kind of progress monitor to get more information about the state of OCR processing. This tesseract API might be helpful:

let monitor = TessMonitorCreate()
let status = TessMonitorGetProgress(monitor)
TessMonitorDelete(monitor)

To answere your question about the API (in #33 ) ... I thought of a delegate, that will be called when changes in the processing happen, e.g.:

public protocol SwiftyTesseractDelegate: AnyObject {
    func swiftyTesseract(_ swiftyTesseract: SwiftyTesseract, didRecieveProgressChange progress: Double)
}

imho the progress might be a value between 0...1.0 which could be calculated as:

let numOfPages = 4.0
let completedPages = 1.0
let progressOfCurrentPage = 0.66

let totalProgress = (progressOfCurrentPage + completedPages)/numOfPages

This assumes that all pages take an equal amount of time to be calculated, but it might be a good approximation. What do you think?

Support for iOS 10 with excluded archs for simulator

Hi,

First of all, many thanks for this useful framework. I'm trying to add this framework in the podspec of my framework which has to support for iOS 10 as below:

....
s.ios.deployment_target = '10.0'
s.dependency 'SwiftyTesseract'
s.pod_target_xcconfig = { "EXCLUDED_ARCHS[sdk=iphonesimulator*]" => "arm64" }
s.user_target_xcconfig = { "EXCLUDED_ARCHS[sdk=iphonesimulator*]" => "arm64" }
....

When I run pod lint, it uses SwiftyTesseract 2.2.3 version and doesn't build because of iphonesimulator architecture problem. Is it possible to edit the framework to support iOS 10 or how can I use 2.2.3 version excluding iphonesimulator arm64 archs?

Thank you.

Checklist

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

Support different Modes

I implemented a flutter package based on your package. @TheLastGimbus will work on some optimizations. He will implement PageSegMode on java side. Can you make PageSegMode to be a parameter?

SPM implementation gets rejected by AppStore

Checklist

  • I've read the Readme
  • I've read the Contribution Guidelines
  • I've read the Code of Conduct.
  • [] I'm using Cocoapods for dependency management
  • [] I'm using Carthage for dependency management
  • I'm using SPM for dependency management

Describe the bug
I've implemented the Swift package version of the library, added the package to the project just as instructed,
When trying to upload my app to the AppStore it gets rejected with the following Error -
"The binary file 'XYZ.app/Frameworks/libtesseract.framework/libtesseract' is not permitted. Your app can’t contain standalone executables or libraries, other than a valid CFBundleExecutable of supported bundles."

Sample Code

Expected behavior
A successful upload to the AppStore

Versions

  • Xcode: 12.3(12C33)
  • Swift: 5
  • iOS: 12+
  • SwiftyTesseract: 4.0.0

Additional context
None

PDF copy text

مت
لـدـمعةعمـ ـ*&9«ـ*=%اا

مصممجقدعم,ةودمصرمفيةعةلياهء ـــم
و»*«%ماع%ة%«

This is the result of a invoice after trying to copy a part of text...
Is that fixable?

Multi Thread

Is there a way to accomplish multithread without having one instance per thread (operation)?

Pod Target Swift 4.2

Hi,
I implemented your library in my flutter plugin. I have to manually set the Swift version in pod file as below. Can you please specify pod_target_xcconfig = { 'SWIFT_VERSION' => '4.2' } on your plugin, so that I don't have to ask users to add below setting?
Thanks!

post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
if target.name == "SwiftyTesseract"
config.build_settings['SWIFT_VERSION'] = '4.2'
end
end
end
end

Tessdata error

Please make sure the TESSDATA_PREFIX environment variable is set to your "tessdata" directory.
Failed loading language 'eng'
Tesseract couldn't load any languages!
Fatal error: Initialization of SwiftyTesseract has failed. Check that the tessdata folder has been added to the project as a folder reference and contains the correct .traineddata files for the specified engine mode and language(s).: file /Users/msalari/Downloads/SwiftyTesseract-master/SwiftyTesseract/SwiftyTesseract/SwiftyTesseract.swift, line 106
2019-05-13 12:41:59.815989+0300 OCRDemo[4668:83312] Fatal error: Initialization of SwiftyTesseract has failed. Check that the tessdata folder has been added to the project as a folder reference and contains the correct .traineddata files for the specified engine mode and language(s).: file /Users/msalari/Downloads/SwiftyTesseract-master/SwiftyTesseract/SwiftyTesseract/SwiftyTesseract.swift, line 106

Xcode 11.4 compilation issue.

Hi there,

As of Xcode 11.4 this library no longer compiles (despite the swift version being set at 4.2).

The main issue is this:

  public func performOCR(on image: UIImage, completionHandler: @escaping (String?) -> ()) {
    let _ = semaphore.wait(timeout: .distantFuture)
    
    // pixImage is a var because it has to be passed as an inout paramter to pixDestroy to release the memory allocation
    var pixImage: Pix
    
    defer { <---- This block needs to be moved below the "do".
      // Release the Pix instance from memory
      pixDestroy(&pixImage)
      semaphore.signal()
    }
    
    do {
      pixImage = try createPix(from: image)
    } catch {
      completionHandler(nil)
      return
    }

   [I.e. pasted in here].

Afterwards it will compile and run fine.

Is that something we can have changed soon? Hope that's possible.

Thanks heaps in advance!
Matt

Does it support video to scan the text?

Checklist

Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like
A clear and concise description of what you want to happen.

Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.

Additional context
Add any other context or screenshots about the feature request here.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.