From d8494f3215c107308467c961fec05e1bf04dbe0e Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Tue, 2 Jul 2019 06:39:27 +0200 Subject: [PATCH] Revert "Simplify indirect call of LMPainPoints::GeneratePainPoint" This reverts commit 6a0fc4f89ff7ce0f6e0e39291eaded56b7a91c47. It removed global symbols, so the binary API was incompatible. Signed-off-by: Stefan Weil --- src/ccstruct/Makefile.am | 2 -- src/ccstruct/blamer.cpp | 21 +++++++++--------- src/ccstruct/blamer.h | 16 ++++++++------ src/ccutil/tesscallback.h | 42 ++++++++++++++++++++++++++++++++++++ src/wordrec/lm_pain_points.h | 8 +++++++ src/wordrec/segsearch.cpp | 8 +++++-- 6 files changed, 76 insertions(+), 21 deletions(-) diff --git a/src/ccstruct/Makefile.am b/src/ccstruct/Makefile.am index b802870ec..dddd1de28 100644 --- a/src/ccstruct/Makefile.am +++ b/src/ccstruct/Makefile.am @@ -1,8 +1,6 @@ AM_CPPFLAGS += \ -I$(top_srcdir)/src/ccutil \ -I$(top_srcdir)/src/cutil \ - -I$(top_srcdir)/src/dict \ - -I$(top_srcdir)/src/wordrec \ -I$(top_srcdir)/src/viewer \ -I$(top_srcdir)/src/opencl AM_CPPFLAGS += $(OPENCL_CPPFLAGS) diff --git a/src/ccstruct/blamer.cpp b/src/ccstruct/blamer.cpp index 2626e8c33..fd9b022c8 100644 --- a/src/ccstruct/blamer.cpp +++ b/src/ccstruct/blamer.cpp @@ -3,6 +3,7 @@ // Description: Module allowing precise error causes to be allocated. // Author: Rike Antonova // Refactored: Ray Smith +// Created: Mon Feb 04 14:37:01 PST 2013 // // (C) Copyright 2013, Google Inc. // Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,10 +23,10 @@ #include // for abs #include "blobs.h" // for TPOINT, TWERD, TBLOB #include "errcode.h" // for ASSERT_HOST -#include "lm_pain_points.h" // for LMPainPoints #include "matrix.h" // for MATRIX #include "normalis.h" // for DENORM #include "pageres.h" // for WERD_RES +#include "tesscallback.h" // for TessResultCallback2 #include "unicharset.h" // for UNICHARSET // Names for each value of IncorrectResultReason enum. Keep in sync. @@ -470,12 +471,14 @@ bool BlamerBundle::GuidedSegsearchNeeded(const WERD_CHOICE *best_choice) const { } // Setup ready to guide the segmentation search to the correct segmentation. -void BlamerBundle::InitForSegSearch(const WERD_CHOICE* best_choice, +// The callback pp_cb is used to avoid a cyclic dependency. +// It calls into LMPainPoints::GenerateForBlamer by pre-binding the +// WERD_RES, and the LMPainPoints itself. +// pp_cb must be a permanent callback, and should be deleted by the caller. +void BlamerBundle::InitForSegSearch(const WERD_CHOICE *best_choice, MATRIX* ratings, UNICHAR_ID wildcard_id, - bool debug, STRING* debug_str, - tesseract::LMPainPoints* pain_points, - double max_char_wh_ratio, - WERD_RES* word_res) { + bool debug, STRING *debug_str, + TessResultCallback2* cb) { segsearch_is_looking_for_blame_ = true; if (debug) { tprintf("segsearch starting to look for blame\n"); @@ -490,10 +493,8 @@ void BlamerBundle::InitForSegSearch(const WERD_CHOICE* best_choice, if (!ratings->Classified(correct_segmentation_cols_[idx], correct_segmentation_rows_[idx], wildcard_id) && - !pain_points->GeneratePainPoint(correct_segmentation_cols_[idx], - correct_segmentation_rows_[idx], - tesseract::LM_PPTYPE_BLAMER, 0.0, - false, max_char_wh_ratio, word_res)) { + !cb->Run(correct_segmentation_cols_[idx], + correct_segmentation_rows_[idx])) { segsearch_is_looking_for_blame_ = false; *debug_str += "\nFailed to insert pain point\n"; SetBlame(IRR_SEGSEARCH_HEUR, *debug_str, best_choice, debug); diff --git a/src/ccstruct/blamer.h b/src/ccstruct/blamer.h index 89dd7ba0b..b1b325b41 100644 --- a/src/ccstruct/blamer.h +++ b/src/ccstruct/blamer.h @@ -3,6 +3,7 @@ // Description: Module allowing precise error causes to be allocated. // Author: Rike Antonova // Refactored: Ray Smith +// Created: Mon Feb 04 14:37:01 PST 2013 // // (C) Copyright 2013, Google Inc. // Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,9 +40,7 @@ class WERD_RES; struct MATRIX_COORD; struct TWERD; -namespace tesseract { - class LMPainPoints; -} +template class TessResultCallback2; static const int16_t kBlamerBoxTolerance = 5; @@ -267,11 +266,14 @@ struct BlamerBundle { // Returns true if a guided segmentation search is needed. bool GuidedSegsearchNeeded(const WERD_CHOICE *best_choice) const; // Setup ready to guide the segmentation search to the correct segmentation. - void InitForSegSearch(const WERD_CHOICE* best_choice, + // The callback pp_cb is used to avoid a cyclic dependency. + // It calls into LMPainPoints::GenerateForBlamer by pre-binding the + // WERD_RES, and the LMPainPoints itself. + // pp_cb must be a permanent callback, and should be deleted by the caller. + void InitForSegSearch(const WERD_CHOICE *best_choice, MATRIX* ratings, UNICHAR_ID wildcard_id, - bool debug, STRING* debug_str, - tesseract::LMPainPoints* pain_points, - double max_char_wh_ratio, WERD_RES* word_res); + bool debug, STRING *debug_str, + TessResultCallback2* pp_cb); // Returns true if the guided segsearch is in progress. bool GuidedSegsearchStillGoing() const; // The segmentation search has ended. Sets the blame appropriately. diff --git a/src/ccutil/tesscallback.h b/src/ccutil/tesscallback.h index 5d682c724..1c63cb988 100644 --- a/src/ccutil/tesscallback.h +++ b/src/ccutil/tesscallback.h @@ -592,6 +592,48 @@ NewPermanentTessCallback(R (*function)(A1, A2)) { return new _TessFunctionResultCallback_0_2(function); } +template +class _TessMemberResultCallback_2_2 : public TessResultCallback2 { + public: + typedef TessResultCallback2 base; + using MemberSignature = R (T::*)(P1, P2, A1, A2); + + private: + T* object_; + MemberSignature member_; + typename remove_reference::type p1_; + typename remove_reference::type p2_; + + public: + inline _TessMemberResultCallback_2_2(T* object, MemberSignature member, P1 p1, + P2 p2) + : object_(object), member_(member), p1_(p1), p2_(p2) {} + + R Run(A1 a1, A2 a2) override { + if (!del) { + R result = (object_->*member_)(p1_, p2_, a1, a2); + return result; + } + R result = (object_->*member_)(p1_, p2_, a1, a2); + // zero out the pointer to ensure segfault if used again + member_ = nullptr; + delete this; + return result; + } +}; + +#ifndef SWIG +template +inline + typename _TessMemberResultCallback_2_2::base* + NewPermanentTessCallback(T1* obj, R (T2::*member)(P1, P2, A1, A2), + typename Identity::type p1, + typename Identity::type p2) { + return new _TessMemberResultCallback_2_2( + obj, member, p1, p2); +} +#endif + template class _ConstTessMemberResultCallback_0_3 : public TessResultCallback3 { diff --git a/src/wordrec/lm_pain_points.h b/src/wordrec/lm_pain_points.h index 75d671f83..c5cbd288a 100644 --- a/src/wordrec/lm_pain_points.h +++ b/src/wordrec/lm_pain_points.h @@ -5,6 +5,7 @@ // to generate "pain points" - the locations in the ratings // matrix which should be classified next. // Author: Rika Antonova +// Created: Mon Jun 20 11:26:43 PST 2012 // // (C) Copyright 2012, Google Inc. // Licensed under the Apache License, Version 2.0 (the "License"); @@ -98,6 +99,13 @@ class LMPainPoints { void GenerateFromAmbigs(const DANGERR &fixpt, ViterbiStateEntry *vse, WERD_RES *word_res); + // Generate a pain point for the blamer. + bool GenerateForBlamer(double max_char_wh_ratio, WERD_RES *word_res, + int col, int row) { + return GeneratePainPoint(col, row, LM_PPTYPE_BLAMER, 0.0, false, + max_char_wh_ratio, word_res); + } + // Adds a pain point to classify chunks_record->ratings(col, row). // Returns true if a new pain point was added to an appropriate heap. // Pain point priority is set to special_priority for pain points of diff --git a/src/wordrec/segsearch.cpp b/src/wordrec/segsearch.cpp index aca503d11..70e5d69a1 100644 --- a/src/wordrec/segsearch.cpp +++ b/src/wordrec/segsearch.cpp @@ -27,6 +27,7 @@ #include "params.h" // for BoolParam, IntParam, DoubleParam #include "ratngs.h" // for BLOB_CHOICE_LIST, BLOB_CHOICE_IT #include "strngs.h" // for STRING +#include "tesscallback.h" // for TessResultCallback2 #include "tprintf.h" // for tprintf #include "wordrec.h" // for Wordrec, SegSearchPending (ptr only) @@ -329,10 +330,13 @@ void Wordrec::InitBlamerForSegSearch(WERD_RES *word_res, BlamerBundle *blamer_bundle, STRING *blamer_debug) { pain_points->Clear(); // Clear pain points heap. + TessResultCallback2* pp_cb = NewPermanentTessCallback( + pain_points, &LMPainPoints::GenerateForBlamer, + static_cast(segsearch_max_char_wh_ratio), word_res); blamer_bundle->InitForSegSearch(word_res->best_choice, word_res->ratings, getDict().WildcardID(), wordrec_debug_blamer, - blamer_debug, pain_points, - segsearch_max_char_wh_ratio, word_res); + blamer_debug, pp_cb); + delete pp_cb; } } // namespace tesseract