ofxTesseract discussion

I’m trying to run the example of @kylemcdonald 's ofxTesseract:

GitHub - kylemcdonald/ofxTesseract: tesseract-ocr wrapper for openFrameworks

It includes CvUtils.h which includes cv.h. But cv.h cannot be found:

Where is cv.h supposed to be? Am I supposed to follow the instructions here to install openCV for Windows/c++… or is there an oF-specific thing I’m supposed to do?

I think just make sure you include the ofxOpenCv addon in your project too.
Anywhere you see include “cv.h” replace with “ofxOpenCv.h”

1 Like

@theo Thanks, that gets rid of most of the errors. Still getting an arguments-don’t-match-constructor error in getMat():

getMat() has 29 different constructors and the one that looks the closes requires a void pointer where img.getPixels() is, so I tried this:


and tried building but ran into another bug. setenv() definition not found:

EDIT: Looks like this is a Windows problem and can be fixed with a wrapper method as found here.

Trying to build now gives a bunch of linking errors. Are these due to these methods not being the same in the newest version of openCV (in ofxCV)?

I think Kyle’s addon doesn’t have windows libs for the tesseract library. That is what those errors point to.

Someone made 32bit libs for VS 2015 but they might not be compatible with VS 2019:

( VS 2017 was the first visual studio that didn’t need libs recompiled for newer VS versions ).

So you might need to find libs or build them see the note:

Probably easiest is to use cmake to build from the official repo:

Also maybe this is a solution?:

If you do get working libs you should fork the addon and do a Pull Request to Kyle’s repo - I’m sure others would benefit. :slightly_smiling_face:

1 Like

Looks like you can grab the prebuilt libs actually see:

1 Like

Hey @theo , thanks for the resources.

I tried the link you posted in your last post. In the Windows section there, I followed the link to the Tesseract at UB Mannheim page, but the windows installer there was to set up an executable and didn’t make any lib files…

Next, I tried the method in that stackoverflow thread. The installation was successful, but the include, lib, and bin folders contain many, many files and I’m not sure which are needed in my project and where I need to put them or if I need to rename them…

@s_e_p I got this running fine on OSX in Xcode a while ago - but I do remember some fiddling with links and libraries had to be done - apologies - i dont remember exactly what I did at the time but the structure of the working addon and a working project (on Mac) looked like this - in case it helps?



(I just put a walkthru video of it working reading the sides of freight trains up onto youtube if that helps?)

Hey @s_e_p

I think the best bet would be to add all the .a or .lib files generated by the build process into the addon folder in the same format as used by the ofxOpenCv addon. ie addons/ofxTesseract/libs/tesseract/lib/vs/x64/

Then you could use the Project Generator to make a new project with the addon and it should add the libs correctly to the linker.

Note: you might need to separate Debug and Release libs or just use release libs and only build for release.

Feel free to share the file list from the build and we can help you id which files you need.

Theo

Hey @danb . Actually, it’s because I watched your video that I started messing with this, so thank you! It looks like you have some lib files in your bin folder (idk what the dylib extension is though…)

@theo OK, I tried regenerating the sln file after moving, as you said, all the .lib files installed via the stackoverflow approach (from the directory installed/x64-windows/lib) into addons/ofxTesseract/libs/tesseract/lib/vs/x64/
but it didn’t work. I do get less errors now than before though:

Here is my ofxTesseract directory.

Now, the stackoverflow method (vcpkg) also generated h files, so I wonder if I need to replace the original header files in the include folder (baseapi.h & thresholder.h) with those files… Here’s a screenshot of the vcpkg-generated include folder:

Am I being lazy? Should I look through each of these header files individually and look for a file that resembles the original baseapi.h…? Or is the problem really just the lib files…?

I’ve also tried installing cmake and using that to build from the original repo, but I don’t really get that either. I followed the instructions here, and got this:

So there’s an error, and the build folder contains a bunch of files:

Not sure what to do, though this may be just be an I-need-to-take-a-Cmake-tutorial-Issue.

Ah yeah - you might want to add the files from the include/tesseract/ folder and that might fix those errors. as the API might have changed between the version in the addon and the vcpkg version.

@theo OK, I’ve copied all the header files (but none of the folders) from fcpkg/installed/x64-windows/include/tesseract into ofxTesseract/libs/tesseract/include:

but the new api doesn’t seem to have accuracy types, so I’m getting these errors:

Should I rifle through the header files looking for enums that seem to serve a similar role…?

Yeah, I am not sure if that is used anymore.
you could comment out anything that uses it. Or try setting ACCURATE = 100; FAST = 0;

OK, commenting out the accuracy stuff allowed it to build.!

@theo So after I set the location of the eng.traineddata file properly, using the file that originally came with this repo, I ran and got a stream of ‘Bad read of inttemp!’ messages. Then I tried downloading the eng.traineddata file from here. I would expect this to work because the readme says it’s for versions 4.0.0 and newer and the version.h of the files I’m using (gotten with vcpkg) says this is version 5.3.1 of Tesseract. But when I run it, the program immediately exits with an error. Running in debug mode shows an access violation bug set off by runOcr():

EDIT: After some experimenting, I found the problem is the medianblur method. If I remove the call to it, the build runs and image detection works!

Not sure if the medianblur thing is important though… Does blurring help legibility in some cases? And if so, should I replace this call with one to another ofxCv::medianBlur? Having both ofxCv and ofxOpenCv as needed addons isn’t ideal if I’m going to be forking ofxTesseract for Windows though…

EDIT2: Now that I think about it, this CvUtils file isn’t even part of the ofxTesseract addon, so I guess I don’t need to do anything about that…

@danb Hey, have you added the code from your video to your GitHub? I cant find it. The parts of your code for detection work well and curious about how you cleanText() method works (dictionary comparison).

EDIT: Ah, sorry, I watched again and in your video you haven’t implemented it yet. I thought you had due to the existence of cleanText()

I looked into this myself and adopted the code here. I also added functionality to check for upper/lower-case variations:

struct Lexicon
{
	Lexicon()
	{
		cout << "um " << endl;
		//std::ifstream input("data\\dict.txt");
		std::ifstream input("C:\\Users\\selli\\openFrameworks\\addons\\ofxCustom\\textData\\dict.txt");
		if (input.is_open())
		{
			std::cout << "lex opened" << endl;
		}
		else
		{
			std::cout << "lex not opened " << endl;
		}

		for (std::string line; std::getline(input, line);)
		{
			//cout << "insert: " << line << endl;
			words.insert(line);
		}
	}
	bool contains(std::string const& word, bool checkAllLower = false, bool checkAllUpper = true) const 
	{ 
		bool isWord = words.count(word);
		if (isWord)
		{
			//cout << word << " is a word" << endl;
			return true;
		}
		if (checkAllLower)
		{
			std::string wordLower = word;
			for (int i = 0; i < wordLower.size(); ++i)
			{
				wordLower[i] = std::tolower(wordLower[i]);
			}
			if (words.count(wordLower))
			{
				//cout << wordLower << " is a lower word" << endl;
				return true;
			}
		}
		if (checkAllUpper)
		{
			std::string wordUpper = word;
			for (int i = 0; i < wordUpper.size(); ++i)
			{
				wordUpper[i] = std::tolower(wordUpper[i]);
			}
			if (words.count(wordUpper))
			{
				//cout << wordUpper << " is an upper word" << endl;
				return true;
			}
		}
		return false; 
	}

	std::set<std::string> words;
};

This works well… the lexicon text file I found included every single letter as a word, so I had to get rid of those. That includes ‘a’ and ‘I’. Despite being important words, they get detected constantly. I may consider restoring them if I find other ways to increase accuracy (maybe using blur?)

1 Like

yep - that is coming in the next video - at the moment the cleantext() routine just removes line breaks and allows concatenation - but is waiting for just the kind of process you added !

string ofApp::cleanText(string textIn){
    // clean out carriage returns from text
    textIn.erase( std::remove(textIn.begin(), textIn.end(), '\n'), textIn.end() );
    
    return textIn;
}
1 Like

@danb Ah, I see, thanks.

I’ve been messing with it and found so far two ways to affect sensitivity/accuracy.

  1. Applying a little bit of blur will reduce false positives

  2. making the image monochrome seems to help a lot. Red text on white background doesn’t get picked up, but does when I make the image grayscale.

Big problem I’m noticing now is that some fonts don’t get picked up at all. I was hoping there’d be a quick way to get training data for different fonts, but I may need to create my own training data or else resign myself to incomplete recognition.

I found the technical description from the tesseract documentation on improving recognition helpful to understand what it’s looking for Improving the quality of the output | tessdoc

1 Like