@@ -102,97 +102,104 @@ int read_number(Logger& logger, const ImageViewRGB32& image, Language language){
102102
103103int read_number_waterfill (
104104 Logger& logger, const ImageViewRGB32& image,
105- uint32_t rgb32_min, uint32_t rgb32_max,
106- bool text_inside_range
107- ){
108- const std::vector<std::pair<uint32_t , uint32_t >> filters = {
109- {rgb32_min, rgb32_max}
110- };
111- return read_number_waterfill (logger, image, filters, UINT32_MAX, text_inside_range);
112- }
113-
114- int read_number_waterfill (
115- Logger& logger, const ImageViewRGB32& image,
116- std::vector<std::pair<uint32_t , uint32_t >> filters,
105+ uint32_t rgb32_min, uint32_t rgb32_max,
106+ bool text_inside_range,
117107 uint32_t width_max,
118- bool text_inside_range
108+ bool check_empty_string
119109){
120110 using namespace Kernels ::Waterfill;
121111
112+ // Direct OCR is unreliable. Instead, we will waterfill each character
113+ // to isolate them, then OCR them individually.
122114
115+ ImageRGB32 filtered = to_blackwhite_rgb32_range (image, rgb32_min, rgb32_max, text_inside_range);
123116
124- for (std::pair<uint32_t , uint32_t > filter : filters){
117+ // static int c = 0;
118+ // int i = 0;
119+ // filtered.save("test-" + std::to_string(c++) + ".png");
125120
126- uint32_t rgb32_min = filter.first ;
127- uint32_t rgb32_max = filter.second ;
128-
129- // Direct OCR is unreliable. Instead, we will waterfill each character
130- // to isolate them, then OCR them individually.
131-
132- ImageRGB32 filtered = to_blackwhite_rgb32_range (image, rgb32_min, rgb32_max, text_inside_range);
133-
134- // static int c = 0;
135- // int i = 0;
136- // filtered.save("test-" + std::to_string(c++) + ".png");
137-
138- PackedBinaryMatrix matrix = compress_rgb32_to_binary_range (filtered, 0xff000000 , 0xff7f7f7f );
139-
140- std::map<size_t , WaterfillObject> map;
141- {
142- std::unique_ptr<WaterfillSession> session = make_WaterfillSession (matrix);
143- auto iter = session->make_iterator (20 );
144- WaterfillObject object;
145- bool exceed_width_max = false ;
146- while (map.size () < 16 && iter->find_next (object, true )){
147- if (object.width () > width_max){
148- exceed_width_max = true ;
149- break ;
150- }
151- map.emplace (object.min_x , std::move (object));
152- }
153- if (exceed_width_max){
154- // try the next color filter
155- continue ;
121+ PackedBinaryMatrix matrix = compress_rgb32_to_binary_range (filtered, 0xff000000 , 0xff7f7f7f );
122+
123+ std::map<size_t , WaterfillObject> map;
124+ {
125+ std::unique_ptr<WaterfillSession> session = make_WaterfillSession (matrix);
126+ auto iter = session->make_iterator (20 );
127+ WaterfillObject object;
128+ while (map.size () < 16 && iter->find_next (object, true )){
129+ if (object.width () > width_max){
130+ logger.log (" Skipped this filter: character exceeded max width." );
131+ return -1 ;
156132 }
133+ map.emplace (object.min_x , std::move (object));
157134 }
135+ }
158136
159- std::string ocr_text;
160- bool empty_char = false ;
161- for ( const auto & item : map){
162- const WaterfillObject& object = item. second ;
163- ImageRGB32 cropped = extract_box_reference (filtered, object). copy ();
164- PackedBinaryMatrix tmp (object. packed_matrix () );
165- filter_by_mask (tmp, cropped, Color ( 0xffffffff ), true );
166- ImageRGB32 padded = pad_image (cropped, cropped. width (), 0xffffffff );
167- std::string ocr = OCR::ocr_read (Language::English, padded );
168- // padded.save("test-cropped" + std::to_string(c) + "-" + std::to_string(i++) + ".png") ;
169- // std::cout << ocr[0] << std::endl;
170- if (! ocr. empty ()){
171- ocr_text += ocr[ 0 ];
172- } else {
173- empty_char = true ;
174- break ;
137+ std::string ocr_text;
138+ for ( const auto & item : map){
139+ const WaterfillObject& object = item. second ;
140+ ImageRGB32 cropped = extract_box_reference (filtered, object). copy ();
141+ PackedBinaryMatrix tmp ( object. packed_matrix ());
142+ filter_by_mask (tmp, cropped, Color ( 0xffffffff ), true );
143+ ImageRGB32 padded = pad_image ( cropped, cropped. width ( ), 0xffffffff );
144+ std::string ocr = OCR::ocr_read (Language::English, padded );
145+ // padded.save("test-cropped" + std::to_string(c) + "-" + std::to_string(i++) + ".png" );
146+ // std::cout << ocr[0] << std::endl ;
147+ if (! ocr. empty ()){
148+ ocr_text += ocr[ 0 ];
149+ } else {
150+ if (check_empty_string) {
151+ logger. log ( " Skipped this filter: empty string. " ) ;
152+ return - 1 ;
175153 }
176154 }
177- if (empty_char){
178- // try the next color filter
179- continue ;
180- }
155+ }
156+
157+ std::string normalized = run_number_normalization (ocr_text);
158+
159+ if (normalized.empty ()){
160+ logger.log (" OCR Text: \" " + ocr_text + " \" -> \" " + normalized + " \" -> Unable to read." , COLOR_RED);
161+ return -1 ;
162+ }
163+
164+ int number = std::atoi (normalized.c_str ());
165+ logger.log (" OCR Text: \" " + ocr_text + " \" -> \" " + normalized + " \" -> " + std::to_string (number));
166+
167+ return number;
168+ }
169+
170+ int read_number_waterfill (
171+ Logger& logger, const ImageViewRGB32& image,
172+ std::vector<std::pair<uint32_t , uint32_t >> filters,
173+ uint32_t width_max,
174+ bool text_inside_range
175+ ){
176+
181177
182- std::string normalized = run_number_normalization (ocr_text);
178+ std::map<int , uint8_t > candidates;
179+ for (std::pair<uint32_t , uint32_t > filter : filters){
183180
184- if (normalized.empty ()){
185- logger.log (" OCR Text: \" " + ocr_text + " \" -> \" " + normalized + " \" -> Unable to read." , COLOR_RED);
186- return -1 ;
181+ uint32_t rgb32_min = filter.first ;
182+ uint32_t rgb32_max = filter.second ;
183+ int candidate = read_number_waterfill (logger, image, rgb32_min, rgb32_max, text_inside_range, width_max, true );
184+ if (candidate != -1 ){
185+ candidates[candidate]++;
187186 }
187+ }
188188
189- int number = std::atoi (normalized.c_str ());
190- logger.log (" OCR Text: \" " + ocr_text + " \" -> \" " + normalized + " \" -> " + std::to_string (number));
189+ if (candidates.empty ()){
190+ logger.log (" Unable to read number." );
191+ return -1 ;
192+ }
191193
192- return number;
194+ std::pair<int , uint8_t > best;
195+ for (const auto & item : candidates){
196+ if (item.second > best.second ){
197+ best = item;
198+ }
193199 }
194200
195- return -1 ;
201+ logger.log (" Best candidate: --------------------------> " + std::to_string (best.first ));
202+ return best.first ;
196203}
197204
198205
0 commit comments