16 #include "absl/strings/ascii.h"
17 #include "absl/strings/str_cat.h"
18 #include "allheaders.h"
21 #include "gmock/gmock-matchers.h"
31 using ::testing::ContainsRegex;
32 using ::testing::HasSubstr;
34 static const char* langs[] = {
"eng",
"vie",
"hin",
"ara",
nullptr};
35 static const char* image_files[] = {
"HelloGoogle.tif",
"viet.tif",
"raaj.tif",
36 "arabic.tif",
nullptr};
37 static const char* gt_text[] = {
"Hello Google",
"\x74\x69\xe1\xba\xbf\x6e\x67",
38 "\xe0\xa4\xb0\xe0\xa4\xbe\xe0\xa4\x9c",
39 "\xd8\xa7\xd9\x84\xd8\xb9\xd8\xb1\xd8\xa8\xd9\x8a",
43 FRIEND_TEST(TesseractTest, LSTMGeometryTest);
51 absl::StripAsciiWhitespace(&ocr_result);
56 class TesseractTest :
public testing::Test {
67 TEST_F(TesseractTest, BasicTesseractTest) {
72 Pix* src_pix = pixRead(TestDataNameToPath(
"phototest.tif").c_str());
74 ocr_text = GetCleanedTextResult(&api, src_pix);
77 absl::StripAsciiWhitespace(&truth_text);
78 EXPECT_STREQ(truth_text.c_str(), ocr_text.c_str());
88 TEST_F(TesseractTest, IteratesParagraphsEvenIfNotDetected) {
93 #if 0 // TODO: b622.png is missing
94 Pix* src_pix = pixRead(TestDataNameToPath(
"b622.png").c_str());
99 EXPECT_TRUE(para_boxes !=
nullptr);
102 EXPECT_TRUE(block_boxes !=
nullptr);
104 EXPECT_GE(boxaGetCount(para_boxes), boxaGetCount(block_boxes));
105 boxaDestroy(&block_boxes);
106 boxaDestroy(¶_boxes);
107 pixDestroy(&src_pix);
117 TEST_F(TesseractTest, HOCRWorksWithoutSetInputName) {
124 Pix* src_pix = pixRead(TestDataNameToPath(
"HelloGoogle.tif").c_str());
128 EXPECT_TRUE(result !=
nullptr);
129 EXPECT_THAT(result, HasSubstr(
"Hello"));
130 EXPECT_THAT(result, HasSubstr(
"<div class='ocr_page'"));
132 pixDestroy(&src_pix);
136 TEST_F(TesseractTest, HOCRContainsBaseline) {
143 Pix* src_pix = pixRead(TestDataNameToPath(
"HelloGoogle.tif").c_str());
148 EXPECT_TRUE(result !=
nullptr);
149 EXPECT_THAT(result, HasSubstr(
"Hello"));
150 EXPECT_THAT(result, ContainsRegex(
"<span class='ocr_line'[^>]* "
151 "baseline [-.0-9]+ [-.0-9]+"));
153 pixDestroy(&src_pix);
160 TEST_F(TesseractTest, RickSnyderNotFuckSnyder) {
168 #if 0 // TODO: rick_snyder.jpeg is missing
169 Pix* src_pix = pixRead(TestDataNameToPath(
"rick_snyder.jpeg").c_str());
173 EXPECT_TRUE(result !=
nullptr);
174 EXPECT_THAT(result, Not(HasSubstr(
"FUCK")));
176 pixDestroy(&src_pix);
183 TEST_F(TesseractTest, AdaptToWordStrTest) {
184 #ifdef DISABLED_LEGACY_ENGINE
188 static const char* kTrainingPages[] = {
189 "136.tif",
"256.tif",
"410.tif",
"432.tif",
"540.tif",
190 "692.tif",
"779.tif",
"793.tif",
"808.tif",
"815.tif",
191 "12.tif",
"12.tif",
nullptr};
192 static const char* kTrainingText[] = {
193 "1 3 6",
"2 5 6",
"4 1 0",
"4 3 2",
"5 4 0",
"6 9 2",
"7 7 9",
194 "7 9 3",
"8 0 8",
"8 1 5",
"1 2",
"1 2",
nullptr};
195 static const char* kTestPages[] = {
"324.tif",
"433.tif",
"12.tif",
nullptr};
196 static const char* kTestText[] = {
"324",
"433",
"12",
nullptr};
205 api.
SetVariable(
"matcher_sufficient_examples_for_prototyping",
"1");
206 api.
SetVariable(
"classify_class_pruner_threshold",
"220");
208 for (
int i = 0; kTrainingPages[i] !=
nullptr; ++i) {
209 std::string image_file = TestDataNameToPath(kTrainingPages[i]);
210 Pix* src_pix = pixRead(image_file.c_str());
215 <<
"Failed to adapt to text \"" << kTrainingText[i] <<
"\" on image "
217 pixDestroy(&src_pix);
222 for (
int i = 0; kTestPages[i] !=
nullptr; ++i) {
223 Pix* src_pix = pixRead(TestDataNameToPath(kTestPages[i]).c_str());
225 ocr_text = GetCleanedTextResult(&api, src_pix);
226 absl::StripAsciiWhitespace(&truth_text);
227 EXPECT_STREQ(kTestText[i], ocr_text.c_str());
228 pixDestroy(&src_pix);
234 TEST_F(TesseractTest, BasicLSTMTest) {
243 Pix* src_pix = pixRead(TestDataNameToPath(
"phototest_2.tif").c_str());
245 ocr_text = GetCleanedTextResult(&api, src_pix);
248 absl::StripAsciiWhitespace(&truth_text);
249 EXPECT_STREQ(truth_text.c_str(), ocr_text.c_str());
250 pixDestroy(&src_pix);
259 TEST_F(TesseractTest, LSTMGeometryTest) {
260 #ifdef DISABLED_LEGACY_ENGINE
264 Pix* src_pix = pixRead(TestDataNameToPath(
"deslant.tif").c_str());
265 FriendlyTessBaseAPI api;
271 api.SetImage(src_pix);
272 ASSERT_EQ(api.Recognize(
nullptr), 0);
274 const PAGE_RES* page_res = api.GetPageRes();
275 PAGE_RES_IT page_res_it(const_cast<PAGE_RES*>(page_res));
276 page_res_it.restart_page();
277 BLOCK* block = page_res_it.block()->block;
281 for (page_res_it.restart_page(); page_res_it.word() !=
nullptr;
282 page_res_it.forward()) {
299 EXPECT_LT(tess_blob_box.
left() - lstm_blob_box.
left(), 5);
300 EXPECT_LT(lstm_blob_box.
right() - tess_blob_box.
right(), 5);
301 EXPECT_LT(tess_blob_box.
bottom() - lstm_blob_box.
bottom(), 5);
302 EXPECT_LT(lstm_blob_box.
top() - tess_blob_box.
top(), 5);
305 pixDestroy(&src_pix);
309 TEST_F(TesseractTest, InitConfigOnlyTest) {
311 const char* langs[] = {
"eng",
"chi_tra",
"jpn",
"vie"};
312 std::unique_ptr<tesseract::TessBaseAPI> api;
314 for (
size_t i = 0; i <
ARRAYSIZE(langs); ++i) {
317 EXPECT_EQ(0, api->
Init(TessdataPath().c_str(), langs[i],
321 <<
"ms in regular init";
327 LOG(
INFO) <<
"Switching to config only initialization:";
328 for (
size_t i = 0; i <
ARRAYSIZE(langs); ++i) {
331 EXPECT_EQ(0, api->
Init(TessdataPath().c_str(), langs[i],
333 &vars_values,
false));
336 <<
"ms in config-only init";
346 TEST(TesseractInstanceTest, TestMultipleTessInstances) {
348 while (langs[num_langs] !=
nullptr) ++num_langs;
353 std::vector<Pix*> pix(num_langs);
354 for (
int i = 0; i < num_langs; ++i) {
355 SCOPED_TRACE(absl::StrCat(
"Single instance test with lang = ", langs[i]));
357 pix[i] = pixRead(path.c_str());
358 QCHECK(pix[i] !=
nullptr) <<
"Could not read " << path;
361 EXPECT_EQ(0, tess.
Init(kTessdataPath.c_str(), langs[i]));
362 std::string ocr_result = GetCleanedTextResult(&tess, pix[i]);
363 EXPECT_STREQ(gt_text[i], ocr_result.c_str());
368 for (
int i = 0; i < num_langs; ++i) {
369 for (
int j = i + 1; j < num_langs; ++j) {
371 tess1.
Init(kTessdataPath.c_str(), langs[i]);
372 tess2.
Init(kTessdataPath.c_str(), langs[j]);
374 ocr_result[0] = GetCleanedTextResult(&tess1, pix[i]);
375 ocr_result[1] = GetCleanedTextResult(&tess2, pix[j]);
377 EXPECT_FALSE(strcmp(gt_text[i], ocr_result[0].c_str()) ||
378 strcmp(gt_text[j], ocr_result[1].c_str()))
379 <<
"OCR failed on language pair " << langs[i] <<
"-" << langs[j];
383 for (
int i = 0; i < num_langs; ++i) pixDestroy(&pix[i]);
387 TEST(TesseractInstanceTest, TestMultipleTessInstanceVariables) {
390 std::string int_param_name =
"tessedit_pageseg_mode";
391 int int_param[2] = {1, 2};
393 std::string bool_param_name =
"tessedit_ambigs_training";
394 bool bool_param[2] = {
false,
true};
396 std::string str_param_name =
"tessedit_char_blacklist";
398 std::string double_param_name =
"segment_penalty_dict_frequent_word";
400 double double_param[2] = {0.01, 2};
405 for (
int i = 0; i < 2; ++i) {
407 api->
Init(kTessdataPath.c_str(), langs[i].c_str());
409 api->
SetVariable(int_param_name.c_str(), int_param_str[i].c_str());
410 api->
SetVariable(bool_param_name.c_str(), bool_param_str[i].c_str());
411 api->
SetVariable(str_param_name.c_str(), str_param[i].c_str());
412 api->
SetVariable(double_param_name.c_str(), double_param_str[i].c_str());
414 for (
int i = 0; i < 2; ++i) {
418 EXPECT_TRUE(api->
GetIntVariable(int_param_name.c_str(), &intvar));
419 EXPECT_EQ(int_param[i], intvar);
422 EXPECT_EQ(bool_param[i], boolvar);
423 EXPECT_STREQ(str_param[i].c_str(),
427 EXPECT_EQ(double_param[i], doublevar);