26 #include <tensorflow/core/lib/core/threadpool.h>
27 #include "absl/strings/ascii.h"
28 #include "allheaders.h"
44 INT_PARAM_FLAG(reps, 1,
"Num of parallel test repetitions to run.");
47 "Maximum number of instances to run in parallel at any given "
48 "instant. The number of concurrent instances cannot exceed "
49 "reps * number_of_langs_tested, which is also the default value.");
55 static const char* kTessLangs[] = {
"eng",
"vie",
nullptr};
56 static const char* kTessImages[] = {
"HelloGoogle.tif",
"viet.tif",
nullptr};
57 static const char* kTessTruthText[] = {
"Hello Google",
"\x74\x69\xe1\xba\xbf\x6e\x67",
60 static const char* kCubeLangs[] = {
"hin",
"ara",
nullptr};
61 static const char* kCubeImages[] = {
"raaj.tif",
"arabic.tif",
nullptr};
62 static const char* kCubeTruthText[] = {
63 "\xe0\xa4\xb0\xe0\xa4\xbe\xe0\xa4\x9c",
64 "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a",
nullptr};
66 class BaseapiThreadTest :
public ::testing::Test {
68 static void SetUpTestCase() {
69 CHECK(FLAGS_test_tesseract || FLAGS_test_cube)
70 <<
"Need to test at least one of Tesseract/Cube!";
72 std::vector<std::string> image_files;
73 if (FLAGS_test_tesseract) {
75 while (kTessLangs[i] && kTessTruthText[i] && kTessImages[i]) {
76 langs_.push_back(kTessLangs[i]);
77 gt_text_.push_back(kTessTruthText[i]);
78 image_files.push_back(kTessImages[i]);
81 LOG(
INFO) <<
"Testing Tesseract on " << i <<
" languages.";
83 if (FLAGS_test_cube) {
85 while (kCubeLangs[i] && kCubeTruthText[i] && kCubeImages[i]) {
86 langs_.push_back(kCubeLangs[i]);
87 gt_text_.push_back(kCubeTruthText[i]);
88 image_files.push_back(kCubeImages[i]);
91 LOG(
INFO) <<
"Testing Cube on " << i <<
" languages.";
93 num_langs_ = langs_.size();
99 const int n = num_langs_ * FLAGS_reps;
100 for (
int i = 0; i < n; ++i) {
101 std::string path = TESTING_DIR
"/" + image_files[i % num_langs_];
102 Pix* new_pix = pixRead(path.c_str());
103 QCHECK(new_pix !=
nullptr) <<
"Could not read " << path;
104 pix_.push_back(new_pix);
107 pool_size_ = (FLAGS_max_concurrent_instances < 1)
108 ? num_langs_ * FLAGS_reps
109 : FLAGS_max_concurrent_instances;
112 static void TearDownTestCase() {
113 for (
auto& pix : pix_) {
119 pool_.reset(
new tensorflow::thread::ThreadPool(tensorflow::Env::Default(),
"tessthread", pool_size_));
122 void WaitForPoolWorkers() { pool_.reset(
nullptr); }
124 std::unique_ptr<tensorflow::thread::ThreadPool> pool_;
125 static int pool_size_;
126 static std::vector<Pix*> pix_;
127 static std::vector<std::string> langs_;
128 static std::vector<std::string> gt_text_;
129 static int num_langs_;
133 int BaseapiThreadTest::pool_size_;
134 std::vector<Pix*> BaseapiThreadTest::pix_;
135 std::vector<std::string> BaseapiThreadTest::langs_;
136 std::vector<std::string> BaseapiThreadTest::gt_text_;
137 int BaseapiThreadTest::num_langs_;
140 CHECK(tess !=
nullptr);
141 EXPECT_EQ(0, tess->
Init(TESSDATA_DIR, lang.c_str()));
149 absl::StripAsciiWhitespace(ocr_text);
159 InitTessInstance(tess_local, lang);
162 GetCleanedText(tess_local, pix, &ocr_text);
163 EXPECT_STREQ(expected_text.c_str(), ocr_text.c_str());
164 if (tess_local != tess)
delete tess_local;
169 TEST_F(BaseapiThreadTest, TestBasicSanity) {
170 for (
int i = 0; i < num_langs_; ++i) {
172 InitTessInstance(&tess, langs_[i]);
174 GetCleanedText(&tess, pix_[i], &ocr_text);
175 CHECK(strcmp(gt_text_[i].c_str(), ocr_text.c_str()) == 0)
176 <<
"Failed with lang = " << langs_[i];
181 TEST_F(BaseapiThreadTest, TestInit) {
182 const int n = num_langs_ * FLAGS_reps;
184 std::vector<TessBaseAPI> tess(n);
185 for (
int i = 0; i < n; ++i) {
186 pool_->Schedule(std::bind(InitTessInstance, &tess[i], langs_[i % num_langs_]));
188 WaitForPoolWorkers();
192 TEST_F(BaseapiThreadTest, TestRecognition) {
193 const int n = num_langs_ * FLAGS_reps;
194 std::vector<TessBaseAPI> tess(n);
196 for (
int i = 0; i < n; ++i) {
197 InitTessInstance(&tess[i], langs_[i % num_langs_]);
201 for (
int i = 0; i < n; ++i) {
202 pool_->Schedule(std::bind(VerifyTextResult, &tess[i], pix_[i],
203 langs_[i % num_langs_], gt_text_[i % num_langs_]));
205 WaitForPoolWorkers();
208 TEST_F(BaseapiThreadTest, TestAll) {
209 const int n = num_langs_ * FLAGS_reps;
211 for (
int i = 0; i < n; ++i) {
212 pool_->Schedule(std::bind(VerifyTextResult,
nullptr, pix_[i],
213 langs_[i % num_langs_], gt_text_[i % num_langs_]));
215 WaitForPoolWorkers();