aster icon indicating copy to clipboard operation
aster copied to clipboard

Chinese TXT

Open cloudfool opened this issue 6 years ago • 5 comments

Hi,

I want to use this model to detect Chinese text images . When I create tfrecords, the groundtruth_text for Chinese characters after 'utf-8' encoding is different from English and numbers and might cause problems. Would you please give me some advice?

Thanks.

cloudfool avatar Aug 01 '18 05:08 cloudfool

Non-English characters have not been supported yet. The issue is that tf.string_split in r1.4 splits UTF-8 strings into bytes rather than multi-byte characters. A PR has been created but seems not merged yet. For now, rewriting tf.string_split or using some tricks (e.g. preprocessing text by adding delimiters between characters) should work.

bgshih avatar Aug 01 '18 16:08 bgshih

does the network of left-to-right decoder is same to the right-to-left's ? doing right-to-left decoder by provide_groundtruth reverse?@bgshih

ChChwang avatar Dec 28 '18 03:12 ChChwang

From tf 1.13, there is a function can split utf-8 correctly. I changed the source code as follows. #chars = tf.string_split(text, delimiter='') ragged_chars = tf.strings.unicode_split(text, 'UTF-8') chars = ragged_chars.to_sparse()

Also ops.string_reverse() cannot reverse utf-8 strings correctly. So I modified the code which reverses not strings, but labels.

kojit avatar May 30 '19 19:05 kojit

@kojit Hi~ Can you please show the code to reverse the labels ? Thx for your attention~

BlakeXiaochu avatar Aug 15 '19 17:08 BlakeXiaochu

--- a/aster/predictors/attention_predictor.py
+++ b/aster/predictors/attention_predictor.py
@@ -114,12 +114,22 @@ class AttentionPredictor(predictor.Predictor):
   def provide_groundtruth(self, groundtruth_text, scope=None):
     with tf.name_scope(scope, 'ProvideGroundtruth', [groundtruth_text]):
       batch_size = shape_utils.combined_static_and_dynamic_shape(groundtruth_text)[0]
-      if self._reverse:
-        groundtruth_text = ops.string_reverse(groundtruth_text)
+      #if self._reverse:
+      #  groundtruth_text = ops.string_reverse(groundtruth_text)
+
       text_labels, text_lengths = self._label_map.text_to_labels(
         groundtruth_text,
         pad_value=self.end_label,
         return_lengths=True)
+
+      if self._reverse:
+        def reverse_label(x, y):
+            a, b = tf.split(x, [y, tf.shape(x)[0] - y])
+            reverse_a = tf.reverse(a, [-1])
+            return tf.concat([reverse_a, b], 0)
+
+        text_labels, _ = tf.map_fn(lambda x: (reverse_label(x[0], x[1]), x[1]), (text_labels, text_lengths))
+
       start_labels = tf.fill([batch_size, 1], tf.constant(self.start_label, tf.int64))
       end_labels = tf.fill([batch_size, 1], tf.constant(self.end_label, tf.int64))
       if not self._sync:
@@ -143,9 +153,14 @@ class AttentionPredictor(predictor.Predictor):
   def postprocess(self, predictions_dict, scope=None):
     assert 'scores' in predictions_dict
     with tf.variable_scope(scope, 'Postprocess', list(predictions_dict.values())):
-      text = self._label_map.labels_to_text(predictions_dict['labels'])
       if self._reverse:
-        text = ops.string_reverse(text)
+        text_labels = tf.reverse(predictions_dict['labels'], [1])
+        text = self._label_map.labels_to_text(text_labels)
+      else:
+        text = self._label_map.labels_to_text(predictions_dict['labels'])
+      #text = self._label_map.labels_to_text(predictions_dict['labels'])
+      #if self._reverse:
+      #  text = ops.string_reverse(text)
       scores = predictions_dict['scores']
     return {'text': text, 'scores': scores}

kojit avatar Aug 15 '19 23:08 kojit