From 3c6d64fa5cd81207b72fe3e4b0db0e146e7e0bd1 Mon Sep 17 00:00:00 2001 From: WinnieMa Date: Fri, 8 Jul 2022 07:58:47 +0000 Subject: [PATCH 01/17] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20Te?= =?UTF-8?q?nsorFlow/contrib/cv/AdvancedEast=5FID0130=5Ffor=5FTensorFlow/RE?= =?UTF-8?q?ADME.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../README.md | 107 ------------------ 1 file changed, 107 deletions(-) delete mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/README.md diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/README.md b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/README.md deleted file mode 100644 index 2f94a656c..000000000 --- a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/README.md +++ /dev/null @@ -1,107 +0,0 @@ -# AdvancedEAST -AdvancedEAST 是一种用于场景图像文本检测的算法,主要基于 EAST:An Efficient and Accurate Scene Text Detector,并进行了重大改进,使长文本预测更加准确。参考项目:https://github.com/huoyijie/AdvancedEAST - -## 训练环境 - -* python 3.7.5+ -* tensorflow-gpu 1.15.0+ -* numpy 1.14.1+ -* tqdm 4.19.7+ - -## 代码及路径解释 - -``` -AdvancedEAST_ID0130_for_TensorFlow -├── advanced_east.py GPU训练入口 -├── cfg.py 参数配置 -├── icpr 数据集 -│ ├── image_10000 图像文件 -│ └── txt_10000 标签文件 -├── demo 样例图片 -│ ├── 001.png -│ └── 004.png -│ └── ... -├── data 数据集 -│ └── image_test 测试图像文件 -├── model checkpoints -├── saved_model 保存的模型 -├── data_generator.py 数据生成 -├── image_util.py keras中的一些工具 -├── keras_npu.py npu训练入口 -├── label.py 给图像打标签 -├── losses.py 损失函数 -├── network_tensorflow_changeVGG_npu.py 模型结构 -├── nms.py 预测用到的一个函数 -├── predict.py 预测函数 -├── preprocess.py 图片预处理 -├── LICENSE -``` - -## 数据集 -``` -选择使用 tianchi ICPR dataset -``` - -## training - -* tianchi ICPR dataset download -链接: https://pan.baidu.com/s/1NSyc-cHKV3IwDo6qojIrKA 密码: ye9y - -* 数据预处理: -```bash - $ python3 preprocess.py - $ python3 label.py - ``` -* 执行GPU训练: -```bash - $ python3 advanced_east.py -``` -* 执行NPU训练: -```bash - $ python3 keras_npu.py -``` -* 执行predict: -```bash - $ python3 predict.py -``` -## 验证精度 - -* tianchi ICPR MTWI 2018 - -测试集下载地址:链接:https://pan.baidu.com/s/1pU4TXFWfOoZxAmIeAx98dQ 提取码:1234 - -精度验证链接: https://tianchi.aliyun.com/competition/entrance/231685/rankingList - -## 模型文件 - -链接:https://pan.baidu.com/s/1csf-VEwEIF-P0pArvf9lnw -提取码:7kru - -## 精度 - -* 论文精度: - -| Score | Precision | Recall | -| :--------: | ---------- | ------ | -| 0.611 | 0.809 | 0.492 | - -* GPU目标精度: - -| Score | Precision | Recall | -| :--------: | ---------- | ------ | -| 0.554 | 0.760 | 0.436 | - -* Ascend精度: - -| Score | Precision | Recall | -| :--------: | ---------- | ------ | -| 0.582 | 0.762 | 0.471 | - - -## 性能对比: - -| GPU V100 | Ascend 910 | -| :--------: | --------| -| 1057s/epoch | 956s/epoch | - - -- Gitee From 1e8cc3b8bf8705af9d6f34a8b9013218ce1cb47b Mon Sep 17 00:00:00 2001 From: WinnieMa Date: Fri, 8 Jul 2022 07:59:13 +0000 Subject: [PATCH 02/17] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20Te?= =?UTF-8?q?nsorFlow/contrib/cv/AdvancedEast=5FID0130=5Ffor=5FTensorFlow/lo?= =?UTF-8?q?sses.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../losses.py | 94 ------------------- 1 file changed, 94 deletions(-) delete mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/losses.py diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/losses.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/losses.py deleted file mode 100644 index 90f994a2b..000000000 --- a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/losses.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================ -# Copyright 2021 Huawei Technologies Co., Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import cfg -import tensorflow as tf - -def quad_loss(y_true, y_pred): - print('y_true',y_true,'y_pred',y_pred) - # loss for inside_score - logits = y_pred[:, :, :, :1] - labels = y_true[:, :, :, :1] - # balance positive and negative samples in an image - beta = 1 - tf.reduce_mean(labels) - # first apply sigmoid activation - predicts = tf.nn.sigmoid(logits) - # log +epsilon for stable cal - inside_score_loss = tf.reduce_mean( - -1 * (beta * labels * tf.log(predicts + cfg.epsilon) + - (1 - beta) * (1 - labels) * tf.log(1 - predicts + cfg.epsilon))) - inside_score_loss *= cfg.lambda_inside_score_loss - print(inside_score_loss) - # loss for side_vertex_code - vertex_logits = y_pred[:, :, :, 1:3] - vertex_labels = y_true[:, :, :, 1:3] - vertex_beta = 1 - (tf.reduce_mean(y_true[:, :, :, 1:2]) - / (tf.reduce_mean(labels) + cfg.epsilon)) - vertex_predicts = tf.nn.sigmoid(vertex_logits) - pos = -1 * vertex_beta * vertex_labels * tf.log(vertex_predicts + - cfg.epsilon) - neg = -1 * (1 - vertex_beta) * (1 - vertex_labels) * tf.log( - 1 - vertex_predicts + cfg.epsilon) - positive_weights = tf.cast(tf.equal(y_true[:, :, :, 0], 1), tf.float32) - side_vertex_code_loss = \ - tf.reduce_sum(tf.reduce_sum(pos + neg, axis=-1) * positive_weights) / ( - tf.reduce_sum(positive_weights) + cfg.epsilon) - side_vertex_code_loss *= cfg.lambda_side_vertex_code_loss - print(side_vertex_code_loss) - # loss for side_vertex_coord delta - g_hat = y_pred[:, :, :, 3:] - g_true = y_true[:, :, :, 3:] - vertex_weights = tf.cast(tf.equal(y_true[:, :, :, 1], 1), tf.float32) - pixel_wise_smooth_l1norm = smooth_l1_loss(g_hat, g_true, vertex_weights) - side_vertex_coord_loss = tf.reduce_sum(pixel_wise_smooth_l1norm) / ( - tf.reduce_sum(vertex_weights) + cfg.epsilon) - side_vertex_coord_loss *= cfg.lambda_side_vertex_coord_loss - print(side_vertex_coord_loss) - return inside_score_loss + side_vertex_code_loss + side_vertex_coord_loss - - -def smooth_l1_loss(prediction_tensor, target_tensor, weights): - n_q = tf.reshape(quad_norm(target_tensor), tf.shape(weights)) - diff = prediction_tensor - target_tensor - abs_diff = tf.abs(diff) - abs_diff_lt_1 = tf.less(abs_diff, 1) - pixel_wise_smooth_l1norm = (tf.reduce_sum( - tf.where(abs_diff_lt_1, 0.5 * tf.square(abs_diff), abs_diff - 0.5), - axis=-1) / n_q) * weights - return pixel_wise_smooth_l1norm - - -def quad_norm(g_true): - shape = tf.shape(g_true) - delta_xy_matrix = tf.reshape(g_true, [-1, 2, 2]) - diff = delta_xy_matrix[:, 0:1, :] - delta_xy_matrix[:, 1:2, :] - square = tf.square(diff) - distance = tf.sqrt(tf.reduce_sum(square, axis=-1)) - distance *= 4.0 - distance += cfg.epsilon - return tf.reshape(distance, shape[:-1]) -- Gitee From 69c4dc76db111805ea5e4ad6bd5e309a29bc4196 Mon Sep 17 00:00:00 2001 From: WinnieMa Date: Fri, 8 Jul 2022 07:59:20 +0000 Subject: [PATCH 03/17] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20Te?= =?UTF-8?q?nsorFlow/contrib/cv/AdvancedEast=5FID0130=5Ffor=5FTensorFlow/ad?= =?UTF-8?q?vanced=5Feast.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../advanced_east.py | 70 ------------------- 1 file changed, 70 deletions(-) delete mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/advanced_east.py diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/advanced_east.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/advanced_east.py deleted file mode 100644 index 8abd97584..000000000 --- a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/advanced_east.py +++ /dev/null @@ -1,70 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================ -# Copyright 2021 Huawei Technologies Co., Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint -import os - -from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint -from tensorflow.keras.optimizers import Adam - -# from keras.callbacks import EarlyStopping, ModelCheckpoint -# from keras.optimizers import Adam -import cfg -from data_generator import gen -from losses import quad_loss -# from network_tf import East -from network_tensorflow_changeVGG_npu import East - -os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" -os.environ[ - "CUDA_VISIBLE_DEVICES"] = "1" # 这里是gpu的序号,指定使用的gpu对象config = tf.ConfigProto()config.gpu_options.allow_growth = True - -east = East() -east_network = east.east_network() -east_network.summary() -east_network.compile(loss=quad_loss, optimizer=Adam(lr=cfg.lr, - # clipvalue=cfg.clipvalue, - decay=cfg.decay)) -if cfg.load_weights and os.path.exists(cfg.saved_model_weights_file_path): - east_network.load_weights(cfg.saved_model_weights_file_path) -east_network.fit_generator(generator=gen(), - steps_per_epoch=cfg.steps_per_epoch, - epochs=cfg.epoch_num, - validation_data=gen(is_val=True), - validation_steps=cfg.validation_steps, - verbose=1, - initial_epoch=cfg.initial_epoch, - callbacks=[ - EarlyStopping(patience=cfg.patience, verbose=1), - ModelCheckpoint(filepath=cfg.model_weights_path, - save_best_only=True, - save_weights_only=True, - verbose=1)]) -east_network.save(cfg.saved_model_file_path) -east_network.save_weights(cfg.saved_model_weights_file_path) -- Gitee From 2a766705ae3296f3fab2e2d6817151c4ae663f3a Mon Sep 17 00:00:00 2001 From: WinnieMa Date: Fri, 8 Jul 2022 07:59:27 +0000 Subject: [PATCH 04/17] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20Te?= =?UTF-8?q?nsorFlow/contrib/cv/AdvancedEast=5FID0130=5Ffor=5FTensorFlow/da?= =?UTF-8?q?ta=5Fgenerator.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data_generator.py | 66 ------------------- 1 file changed, 66 deletions(-) delete mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/data_generator.py diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/data_generator.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/data_generator.py deleted file mode 100644 index 0ec219c8c..000000000 --- a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/data_generator.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================ -# Copyright 2021 Huawei Technologies Co., Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import numpy as np -from tensorflow.python.keras.preprocessing import image -from tensorflow.python.keras.applications.vgg16 import preprocess_input - -import cfg - - -def gen(batch_size=cfg.batch_size, is_val=False): - img_h, img_w = cfg.max_train_img_size, cfg.max_train_img_size - x = np.zeros((batch_size, img_h, img_w, cfg.num_channels), dtype=np.float32) - pixel_num_h = img_h // cfg.pixel_size - pixel_num_w = img_w // cfg.pixel_size - y = np.zeros((batch_size, pixel_num_h, pixel_num_w, 7), dtype=np.float32) - if is_val: - with open(os.path.join(cfg.data_dir, cfg.val_fname), 'r') as f_val: - f_list = f_val.readlines() - else: - with open(os.path.join(cfg.data_dir, cfg.train_fname), 'r') as f_train: - f_list = f_train.readlines() - while True: - for i in range(batch_size): - # random gen an image name - random_img = np.random.choice(f_list) - img_filename = str(random_img).strip().split(',')[0] - # load img and img anno - img_path = os.path.join(cfg.data_dir, - cfg.train_image_dir_name, - img_filename) - img = image.load_img(img_path) - img = image.img_to_array(img,dtype='float32') - x[i] = preprocess_input(img, mode='tf') - gt_file = os.path.join(cfg.data_dir, - cfg.train_label_dir_name, - img_filename[:-4] + '_gt.npy') - y[i] = np.load(gt_file) - - yield x, y -- Gitee From df14d82956da212ddc0aa143dadfa57678b3d4f4 Mon Sep 17 00:00:00 2001 From: WinnieMa Date: Fri, 8 Jul 2022 07:59:35 +0000 Subject: [PATCH 05/17] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20Te?= =?UTF-8?q?nsorFlow/contrib/cv/AdvancedEast=5FID0130=5Ffor=5FTensorFlow/im?= =?UTF-8?q?age=5Futil.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../image_util.py | 216 ------------------ 1 file changed, 216 deletions(-) delete mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/image_util.py diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/image_util.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/image_util.py deleted file mode 100644 index 5a2c1f67f..000000000 --- a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/image_util.py +++ /dev/null @@ -1,216 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================ -# Copyright 2021 Huawei Technologies Co., Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -import warnings -import tensorflow as tf -from tensorflow.python.ops import variables as tf_variables - -def _obtain_input_shape(input_shape, - default_size, - min_size, - data_format, - require_flatten, - weights=None): - """Internal utility to compute/validate a model's input shape. - - # Arguments - input_shape: Either None (will return the default network input shape), - or a user-provided shape to be validated. - default_size: Default input width/height for the model. - min_size: Minimum input width/height accepted by the model. - data_format: Image data format to use. - require_flatten: Whether the model is expected to - be linked to a classifier via a Flatten layer. - weights: One of `None` (random initialization) - or 'imagenet' (pre-training on ImageNet). - If weights='imagenet' input channels must be equal to 3. - - # Returns - An integer shape tuple (may include None entries). - - # Raises - ValueError: In case of invalid argument values. - """ - if weights != 'imagenet' and input_shape and len(input_shape) == 3: - if data_format == 'channels_first': - if input_shape[0] not in {1, 3}: - warnings.warn( - 'This model usually expects 1 or 3 input channels. ' - 'However, it was passed an input_shape with ' + - str(input_shape[0]) + ' input channels.') - default_shape = (input_shape[0], default_size, default_size) - else: - if input_shape[-1] not in {1, 3}: - warnings.warn( - 'This model usually expects 1 or 3 input channels. ' - 'However, it was passed an input_shape with ' + - str(input_shape[-1]) + ' input channels.') - default_shape = (default_size, default_size, input_shape[-1]) - else: - if data_format == 'channels_first': - default_shape = (3, default_size, default_size) - else: - default_shape = (default_size, default_size, 3) - if weights == 'imagenet' and require_flatten: - if input_shape is not None: - if input_shape != default_shape: - raise ValueError('When setting`include_top=True` ' - 'and loading `imagenet` weights, ' - '`input_shape` should be ' + - str(default_shape) + '.') - return default_shape - if input_shape: - if data_format == 'channels_first': - if input_shape is not None: - if len(input_shape) != 3: - raise ValueError( - '`input_shape` must be a tuple of three integers.') - if input_shape[0] != 3 and weights == 'imagenet': - raise ValueError('The input must have 3 channels; got ' - '`input_shape=' + str(input_shape) + '`') - if ((input_shape[1] is not None and input_shape[1] < min_size) or - (input_shape[2] is not None and input_shape[2] < min_size)): - raise ValueError('Input size must be at least ' + - str(min_size) + 'x' + str(min_size) + '; got ' - '`input_shape=' + str(input_shape) + '`') - else: - if input_shape is not None: - if len(input_shape) != 3: - raise ValueError( - '`input_shape` must be a tuple of three integers.') - if input_shape[-1] != 3 and weights == 'imagenet': - raise ValueError('The input must have 3 channels; got ' - '`input_shape=' + str(input_shape) + '`') - if ((input_shape[0] is not None and input_shape[0] < min_size) or - (input_shape[1] is not None and input_shape[1] < min_size)): - raise ValueError('Input size must be at least ' + - str(min_size) + 'x' + str(min_size) + '; got ' - '`input_shape=' + str(input_shape) + '`') - else: - if require_flatten: - input_shape = default_shape - else: - if data_format == 'channels_first': - input_shape = (3, None, None) - else: - input_shape = (None, None, 3) - if require_flatten: - if None in input_shape: - raise ValueError('If `include_top` is True, ' - 'you should specify a static `input_shape`. ' - 'Got `input_shape=' + str(input_shape) + '`') - return input_shape - - - -def get_source_inputs(tensor, layer=None, node_index=None): - """Returns the list of input tensors necessary to compute `tensor`. - - Output will always be a list of tensors - (potentially with 1 element). - - # Arguments - tensor: The tensor to start from. - layer: Origin layer of the tensor. Will be - determined via tensor._keras_history if not provided. - node_index: Origin node index of the tensor. - - # Returns - List of input tensors. - """ - if not hasattr(tensor, '_keras_history'): - return tensor - - if layer is None or node_index: - layer, node_index, _ = tensor._keras_history - if not layer._inbound_nodes: - return [tensor] - else: - node = layer._inbound_nodes[node_index] - if not node.inbound_layers: - # Reached an Input layer, stop recursion. - return node.input_tensors - else: - source_tensors = [] - for i in range(len(node.inbound_layers)): - x = node.input_tensors[i] - layer = node.inbound_layers[i] - node_index = node.node_indices[i] - previous_sources = get_source_inputs(x, - layer, - node_index) - # Avoid input redundancy. - for x in previous_sources: - if x not in source_tensors: - source_tensors.append(x) - return source_tensors - -def is_keras_tensor(x): - """Returns whether `x` is a Keras tensor. - - A "Keras tensor" is a tensor that was returned by a Keras layer, - (`Layer` class) or by `Input`. - - # Arguments - x: A candidate tensor. - - # Returns - A boolean: Whether the argument is a Keras tensor. - - # Raises - ValueError: In case `x` is not a symbolic tensor. - - # Examples - ```python - >>> from keras import backend as K - >>> from keras.layers import Input, Dense - >>> np_var = numpy.array([1, 2]) - >>> K.is_keras_tensor(np_var) # A numpy array is not a symbolic tensor. - ValueError - >>> k_var = tf.placeholder('float32', shape=(1,1)) - >>> K.is_keras_tensor(k_var) # A variable indirectly created outside of keras is not a Keras tensor. - False - >>> keras_var = K.variable(np_var) - >>> K.is_keras_tensor(keras_var) # A variable created with the keras backend is not a Keras tensor. - False - >>> keras_placeholder = K.placeholder(shape=(2, 4, 5)) - >>> K.is_keras_tensor(keras_placeholder) # A placeholder is not a Keras tensor. - False - >>> keras_input = Input([10]) - >>> K.is_keras_tensor(keras_input) # An Input is a Keras tensor. - True - >>> keras_layer_output = Dense(10)(keras_input) - >>> K.is_keras_tensor(keras_layer_output) # Any Keras layer output is a Keras tensor. - True - ``` - """ - if not isinstance(x, (tf.Tensor, - tf_variables.Variable, - tf.SparseTensor)): - raise ValueError('Unexpectedly found an instance of type `' + str(type(x)) + '`. ' - 'Expected a symbolic tensor instance.') - return hasattr(x, '_keras_history') \ No newline at end of file -- Gitee From 9702ca4d9f7d09b25fddcb03950d34cf4f384064 Mon Sep 17 00:00:00 2001 From: WinnieMa Date: Fri, 8 Jul 2022 07:59:43 +0000 Subject: [PATCH 06/17] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20Te?= =?UTF-8?q?nsorFlow/contrib/cv/AdvancedEast=5FID0130=5Ffor=5FTensorFlow/ke?= =?UTF-8?q?ras=5Fnpu.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../keras_npu.py | 94 ------------------- 1 file changed, 94 deletions(-) delete mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/keras_npu.py diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/keras_npu.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/keras_npu.py deleted file mode 100644 index 945c99160..000000000 --- a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/keras_npu.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================ -# Copyright 2021 Huawei Technologies Co., Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import tensorflow as tf -from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint -from tensorflow.python.keras import backend as K - -import cfg -from network_tensorflow_changeVGG_npu import East -from losses import quad_loss -from data_generator import gen -import argparse -from npu_bridge.estimator.npu.npu_loss_scale_optimizer import NPULossScaleOptimizer -from npu_bridge.estimator.npu.npu_loss_scale_manager import ExponentialUpdateLossScaleManager - -parser = argparse.ArgumentParser() -parser.add_argument('--data_path', type=str, default='', help='data path') -parser.add_argument('--epochs', type=int, default=24, help='epochs') -parser.add_argument('--steps_per_epoch', type=int, default=9000, help='steps_per_epoch') -parser.add_argument('--validation_steps', type=int, default=1000, help='validation_steps') - -args = parser.parse_args() -cfg.data_dir = args.data_path - -from npu_bridge.npu_init import * - -# session config -sess_config = tf.ConfigProto() -custom_op = sess_config.graph_options.rewrite_options.custom_optimizers.add() -custom_op.name = "NpuOptimizer" -sess_config.graph_options.rewrite_options.remapping = RewriterConfig.OFF -sess_config.graph_options.rewrite_options.memory_optimization = RewriterConfig.OFF -# custom_op.parameter_map["precision_mode"].s = tf.compat.as_bytes("allow_mix_precision") - -sess = tf.Session(config=sess_config) -K.set_session(sess) - -east = East() -east_network = east.east_network() -east_network.summary() - -opt_tmp = tf.compat.v1.train.AdamOptimizer(learning_rate=cfg.lr) -loss_scale_manager = ExponentialUpdateLossScaleManager(init_loss_scale=65536, incr_every_n_steps=1000, - decr_every_n_nan_or_inf=2, decr_ratio=0.5) -opt = NPULossScaleOptimizer(opt_tmp, loss_scale_manager) -east_network.compile(loss=quad_loss, optimizer=opt) - -# if cfg.load_weights and os.path.exists(cfg.saved_model_weights_file_path): -# east_network.load_weights(cfg.saved_model_weights_file_path) -# print('load model') -east_network.fit_generator(generator=gen(), - steps_per_epoch=int(args.steps_per_epoch), - epochs=args.epochs, - validation_data=gen(is_val=True), - validation_steps=int(args.validation_steps), - verbose=1, - initial_epoch=cfg.initial_epoch, - callbacks=[ - EarlyStopping(patience=cfg.patience, verbose=1), - ModelCheckpoint(filepath=cfg.model_weights_path, - save_best_only=True, - save_weights_only=True, - verbose=1)]) -print('Train Success') -east_network.save(cfg.saved_model_file_path) -east_network.save_weights(cfg.saved_model_weights_file_path) - - -sess.close() -- Gitee From c56715ab7f415a5bd7a6f0463d74672b9ee4e6b7 Mon Sep 17 00:00:00 2001 From: WinnieMa Date: Fri, 8 Jul 2022 07:59:50 +0000 Subject: [PATCH 07/17] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20Te?= =?UTF-8?q?nsorFlow/contrib/cv/AdvancedEast=5FID0130=5Ffor=5FTensorFlow/nm?= =?UTF-8?q?s.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AdvancedEast_ID0130_for_TensorFlow/nms.py | 114 ------------------ 1 file changed, 114 deletions(-) delete mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/nms.py diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/nms.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/nms.py deleted file mode 100644 index 1b7cbf9c7..000000000 --- a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/nms.py +++ /dev/null @@ -1,114 +0,0 @@ -# coding=utf-8 -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================ -# Copyright 2021 Huawei Technologies Co., Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import numpy as np - -import cfg - - -def should_merge(region, i, j): - neighbor = {(i, j - 1)} - return not region.isdisjoint(neighbor) - - -def region_neighbor(region_set): - region_pixels = np.array(list(region_set)) - j_min = np.amin(region_pixels, axis=0)[1] - 1 - j_max = np.amax(region_pixels, axis=0)[1] + 1 - i_m = np.amin(region_pixels, axis=0)[0] + 1 - region_pixels[:, 0] += 1 - neighbor = {(region_pixels[n, 0], region_pixels[n, 1]) for n in - range(len(region_pixels))} - neighbor.add((i_m, j_min)) - neighbor.add((i_m, j_max)) - return neighbor - - -def region_group(region_list): - S = [i for i in range(len(region_list))] - D = [] - while len(S) > 0: - m = S.pop(0) - if len(S) == 0: - # S has only one element, put it to D - D.append([m]) - else: - D.append(rec_region_merge(region_list, m, S)) - return D - - -def rec_region_merge(region_list, m, S): - rows = [m] - tmp = [] - for n in S: - if not region_neighbor(region_list[m]).isdisjoint(region_list[n]) or \ - not region_neighbor(region_list[n]).isdisjoint(region_list[m]): - # 第m与n相交 - tmp.append(n) - for d in tmp: - S.remove(d) - for e in tmp: - rows.extend(rec_region_merge(region_list, e, S)) - return rows - - -def nms(predict, activation_pixels, threshold=cfg.side_vertex_pixel_threshold): - region_list = [] - for i, j in zip(activation_pixels[0], activation_pixels[1]): - merge = False - for k in range(len(region_list)): - if should_merge(region_list[k], i, j): - region_list[k].add((i, j)) - merge = True - # Fixme 重叠文本区域处理,存在和多个区域邻接的pixels,先都merge试试 - # break - if not merge: - region_list.append({(i, j)}) - D = region_group(region_list) - quad_list = np.zeros((len(D), 4, 2)) - score_list = np.zeros((len(D), 4)) - for group, g_th in zip(D, range(len(D))): - total_score = np.zeros((4, 2)) - for row in group: - for ij in region_list[row]: - score = predict[ij[0], ij[1], 1] - if score >= threshold: - ith_score = predict[ij[0], ij[1], 2:3] - if not (cfg.trunc_threshold <= ith_score < 1 - - cfg.trunc_threshold): - ith = int(np.around(ith_score)) - total_score[ith * 2:(ith + 1) * 2] += score - px = (ij[1] + 0.5) * cfg.pixel_size - py = (ij[0] + 0.5) * cfg.pixel_size - p_v = [px, py] + np.reshape(predict[ij[0], ij[1], 3:7], - (2, 2)) - quad_list[g_th, ith * 2:(ith + 1) * 2] += score * p_v - score_list[g_th] = total_score[:, 0] - quad_list[g_th] /= (total_score + cfg.epsilon) - return score_list, quad_list -- Gitee From 23711c3bb72a409be81089d1555d89249a67c440 Mon Sep 17 00:00:00 2001 From: WinnieMa Date: Fri, 8 Jul 2022 07:59:57 +0000 Subject: [PATCH 08/17] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20Te?= =?UTF-8?q?nsorFlow/contrib/cv/AdvancedEast=5FID0130=5Ffor=5FTensorFlow/pr?= =?UTF-8?q?eprocess.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../preprocess.py | 208 ------------------ 1 file changed, 208 deletions(-) delete mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/preprocess.py diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/preprocess.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/preprocess.py deleted file mode 100644 index b83c589da..000000000 --- a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/preprocess.py +++ /dev/null @@ -1,208 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================ -# Copyright 2021 Huawei Technologies Co., Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import numpy as np -from PIL import Image, ImageDraw -import os -import random -from tqdm import tqdm - -import cfg -from label import shrink - - -def batch_reorder_vertexes(xy_list_array): - reorder_xy_list_array = np.zeros_like(xy_list_array) - for xy_list, i in zip(xy_list_array, range(len(xy_list_array))): - reorder_xy_list_array[i] = reorder_vertexes(xy_list) - return reorder_xy_list_array - - -def reorder_vertexes(xy_list): - reorder_xy_list = np.zeros_like(xy_list) - # determine the first point with the smallest x, - # if two has same x, choose that with smallest y, - ordered = np.argsort(xy_list, axis=0) - xmin1_index = ordered[0, 0] - xmin2_index = ordered[1, 0] - if xy_list[xmin1_index, 0] == xy_list[xmin2_index, 0]: - if xy_list[xmin1_index, 1] <= xy_list[xmin2_index, 1]: - reorder_xy_list[0] = xy_list[xmin1_index] - first_v = xmin1_index - else: - reorder_xy_list[0] = xy_list[xmin2_index] - first_v = xmin2_index - else: - reorder_xy_list[0] = xy_list[xmin1_index] - first_v = xmin1_index - # connect the first point to others, the third point on the other side of - # the line with the middle slope - others = list(range(4)) - others.remove(first_v) - k = np.zeros((len(others),)) - for index, i in zip(others, range(len(others))): - k[i] = (xy_list[index, 1] - xy_list[first_v, 1]) \ - / (xy_list[index, 0] - xy_list[first_v, 0] + cfg.epsilon) - k_mid = np.argsort(k)[1] - third_v = others[k_mid] - reorder_xy_list[2] = xy_list[third_v] - # determine the second point which on the bigger side of the middle line - others.remove(third_v) - b_mid = xy_list[first_v, 1] - k[k_mid] * xy_list[first_v, 0] - second_v, fourth_v = 0, 0 - for index, i in zip(others, range(len(others))): - # delta = y - (k * x + b) - delta_y = xy_list[index, 1] - (k[k_mid] * xy_list[index, 0] + b_mid) - if delta_y > 0: - second_v = index - else: - fourth_v = index - reorder_xy_list[1] = xy_list[second_v] - reorder_xy_list[3] = xy_list[fourth_v] - # compare slope of 13 and 24, determine the final order - k13 = k[k_mid] - k24 = (xy_list[second_v, 1] - xy_list[fourth_v, 1]) / ( - xy_list[second_v, 0] - xy_list[fourth_v, 0] + cfg.epsilon) - if k13 < k24: - tmp_x, tmp_y = reorder_xy_list[3, 0], reorder_xy_list[3, 1] - for i in range(2, -1, -1): - reorder_xy_list[i + 1] = reorder_xy_list[i] - reorder_xy_list[0, 0], reorder_xy_list[0, 1] = tmp_x, tmp_y - return reorder_xy_list - - -def resize_image(im, max_img_size=cfg.max_train_img_size): - im_width = np.minimum(im.width, max_img_size) - if im_width == max_img_size < im.width: - im_height = int((im_width / im.width) * im.height) - else: - im_height = im.height - o_height = np.minimum(im_height, max_img_size) - if o_height == max_img_size < im_height: - o_width = int((o_height / im_height) * im_width) - else: - o_width = im_width - d_wight = o_width - (o_width % 32) - d_height = o_height - (o_height % 32) - return d_wight, d_height - - -def preprocess(): - data_dir = cfg.data_dir - origin_image_dir = os.path.join(data_dir, cfg.origin_image_dir_name) - origin_txt_dir = os.path.join(data_dir, cfg.origin_txt_dir_name) - train_image_dir = os.path.join(data_dir, cfg.train_image_dir_name) - train_label_dir = os.path.join(data_dir, cfg.train_label_dir_name) - if not os.path.exists(train_image_dir): - os.mkdir(train_image_dir) - if not os.path.exists(train_label_dir): - os.mkdir(train_label_dir) - draw_gt_quad = cfg.draw_gt_quad - show_gt_image_dir = os.path.join(data_dir, cfg.show_gt_image_dir_name) - if not os.path.exists(show_gt_image_dir): - os.mkdir(show_gt_image_dir) - show_act_image_dir = os.path.join(cfg.data_dir, cfg.show_act_image_dir_name) - if not os.path.exists(show_act_image_dir): - os.mkdir(show_act_image_dir) - - o_img_list = os.listdir(origin_image_dir) - print('found %d origin images.' % len(o_img_list)) - train_val_set = [] - for o_img_fname, _ in zip(o_img_list, tqdm(range(len(o_img_list)))): - with Image.open(os.path.join(origin_image_dir, o_img_fname)) as im: - # d_wight, d_height = resize_image(im) - d_wight, d_height = cfg.max_train_img_size, cfg.max_train_img_size - scale_ratio_w = d_wight / im.width - scale_ratio_h = d_height / im.height - im = im.resize((d_wight, d_height), Image.NEAREST).convert('RGB') - show_gt_im = im.copy() - # draw on the img - draw = ImageDraw.Draw(show_gt_im) - with open(os.path.join(origin_txt_dir, - o_img_fname[:-4] + '.txt'), 'r', encoding='UTF-8') as f: - anno_list = f.readlines() - xy_list_array = np.zeros((len(anno_list), 4, 2)) - for anno, i in zip(anno_list, range(len(anno_list))): - anno_colums = anno.strip().split(',') - anno_array = np.array(anno_colums) - xy_list = np.reshape(anno_array[:8].astype(float), (4, 2)) - xy_list[:, 0] = xy_list[:, 0] * scale_ratio_w - xy_list[:, 1] = xy_list[:, 1] * scale_ratio_h - xy_list = reorder_vertexes(xy_list) - xy_list_array[i] = xy_list - _, shrink_xy_list, _ = shrink(xy_list, cfg.shrink_ratio) - shrink_1, _, long_edge = shrink(xy_list, cfg.shrink_side_ratio) - if draw_gt_quad: - draw.line([tuple(xy_list[0]), tuple(xy_list[1]), - tuple(xy_list[2]), tuple(xy_list[3]), - tuple(xy_list[0]) - ], - width=2, fill='green') - draw.line([tuple(shrink_xy_list[0]), - tuple(shrink_xy_list[1]), - tuple(shrink_xy_list[2]), - tuple(shrink_xy_list[3]), - tuple(shrink_xy_list[0]) - ], - width=2, fill='blue') - vs = [[[0, 0, 3, 3, 0], [1, 1, 2, 2, 1]], - [[0, 0, 1, 1, 0], [2, 2, 3, 3, 2]]] - for q_th in range(2): - draw.line([tuple(xy_list[vs[long_edge][q_th][0]]), - tuple(shrink_1[vs[long_edge][q_th][1]]), - tuple(shrink_1[vs[long_edge][q_th][2]]), - tuple(xy_list[vs[long_edge][q_th][3]]), - tuple(xy_list[vs[long_edge][q_th][4]])], - width=3, fill='yellow') - if cfg.gen_origin_img: - im.save(os.path.join(train_image_dir, o_img_fname)) - np.save(os.path.join( - train_label_dir, - o_img_fname[:-4] + '.npy'), - xy_list_array) - if draw_gt_quad: - show_gt_im.save(os.path.join(show_gt_image_dir, o_img_fname)) - train_val_set.append('{},{},{}\n'.format(o_img_fname, - d_wight, - d_height)) - - train_img_list = os.listdir(train_image_dir) - print('found %d train images.' % len(train_img_list)) - train_label_list = os.listdir(train_label_dir) - print('found %d train labels.' % len(train_label_list)) - - random.shuffle(train_val_set) - val_count = int(cfg.validation_split_ratio * len(train_val_set)) - with open(os.path.join(data_dir, cfg.val_fname), 'w') as f_val: - f_val.writelines(train_val_set[:val_count]) - with open(os.path.join(data_dir, cfg.train_fname), 'w') as f_train: - f_train.writelines(train_val_set[val_count:]) - - -if __name__ == '__main__': - preprocess() -- Gitee From 0f0c83cc3a7f50cc8a202056bc7391f8c11f57af Mon Sep 17 00:00:00 2001 From: WinnieMa Date: Fri, 8 Jul 2022 08:00:03 +0000 Subject: [PATCH 09/17] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20Te?= =?UTF-8?q?nsorFlow/contrib/cv/AdvancedEast=5FID0130=5Ffor=5FTensorFlow/pr?= =?UTF-8?q?edict.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../predict.py | 201 ------------------ 1 file changed, 201 deletions(-) delete mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/predict.py diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/predict.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/predict.py deleted file mode 100644 index 52f5fc822..000000000 --- a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/predict.py +++ /dev/null @@ -1,201 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================ -# Copyright 2021 Huawei Technologies Co., Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse - -import numpy as np -from PIL import Image, ImageDraw -from tensorflow.keras.applications.vgg16 import preprocess_input -from tensorflow.keras.preprocessing import image - -import cfg -from label import point_inside_of_quad -from network_tensorflow_changeVGG_npu import East -# from network import East -from nms import nms -from preprocess import resize_image - - -def sigmoid(x): - """`y = 1 / (1 + exp(-x))`""" - return 1 / (1 + np.exp(-x)) - - -def cut_text_line(geo, scale_ratio_w, scale_ratio_h, im_array, img_path, s): - geo /= [scale_ratio_w, scale_ratio_h] - p_min = np.amin(geo, axis=0) - p_max = np.amax(geo, axis=0) - min_xy = p_min.astype(int) - max_xy = p_max.astype(int) + 2 - sub_im_arr = im_array[min_xy[1]:max_xy[1], min_xy[0]:max_xy[0], :].copy() - for m in range(min_xy[1], max_xy[1]): - for n in range(min_xy[0], max_xy[0]): - if not point_inside_of_quad(n, m, geo, p_min, p_max): - sub_im_arr[m - min_xy[1], n - min_xy[0], :] = 255 - sub_im = image.array_to_img(sub_im_arr, scale=False) - sub_im.save(img_path + '_subim%d.jpg' % s) - - -def predict(east_detect, img_path, pixel_threshold, quiet=False): - img = image.load_img(img_path) - d_wight, d_height = resize_image(img, cfg.max_predict_img_size) - img = img.resize((d_wight, d_height), Image.NEAREST).convert('RGB') - img = image.img_to_array(img) - img = preprocess_input(img, mode='tf') - x = np.expand_dims(img, axis=0) - print('x.shape', x.shape) - y = east_detect.predict(x) - - y = np.squeeze(y, axis=0) - print('y.shape:', y.shape) - y[:, :, :3] = sigmoid(y[:, :, :3]) - cond = np.greater_equal(y[:, :, 0], pixel_threshold) - activation_pixels = np.where(cond) - quad_scores, quad_after_nms = nms(y, activation_pixels) - # print('quad_scores:',quad_scores,'quad_after_nms', quad_after_nms) - with Image.open(img_path) as im: - im_array = image.img_to_array(im.convert('RGB')) - d_wight, d_height = resize_image(im, cfg.max_predict_img_size) - scale_ratio_w = d_wight / im.width - scale_ratio_h = d_height / im.height - im = im.resize((d_wight, d_height), Image.NEAREST).convert('RGB') - quad_im = im.copy() - draw = ImageDraw.Draw(im) - for i, j in zip(activation_pixels[0], activation_pixels[1]): - px = (j + 0.5) * cfg.pixel_size - py = (i + 0.5) * cfg.pixel_size - line_width, line_color = 1, 'red' - if y[i, j, 1] >= cfg.side_vertex_pixel_threshold: - if y[i, j, 2] < cfg.trunc_threshold: - line_width, line_color = 2, 'yellow' - elif y[i, j, 2] >= 1 - cfg.trunc_threshold: - line_width, line_color = 2, 'green' - draw.line([(px - 0.5 * cfg.pixel_size, py - 0.5 * cfg.pixel_size), - (px + 0.5 * cfg.pixel_size, py - 0.5 * cfg.pixel_size), - (px + 0.5 * cfg.pixel_size, py + 0.5 * cfg.pixel_size), - (px - 0.5 * cfg.pixel_size, py + 0.5 * cfg.pixel_size), - (px - 0.5 * cfg.pixel_size, py - 0.5 * cfg.pixel_size)], - width=line_width, fill=line_color) - im.save(img_path + '_act.jpg') - quad_draw = ImageDraw.Draw(quad_im) - txt_items = [] - for score, geo, s in zip(quad_scores, quad_after_nms, - range(len(quad_scores))): - if np.amin(score) > 0: - quad_draw.line([tuple(geo[0]), - tuple(geo[1]), - tuple(geo[2]), - tuple(geo[3]), - tuple(geo[0])], width=2, fill='red') - if cfg.predict_cut_text_line: - cut_text_line(geo, scale_ratio_w, scale_ratio_h, im_array, - img_path, s) - rescaled_geo = geo / [scale_ratio_w, scale_ratio_h] - rescaled_geo_list = np.reshape(rescaled_geo, (8,)).tolist() - txt_item = ','.join(map(str, rescaled_geo_list)) - txt_items.append(txt_item + '\n') - elif not quiet: - print('quad invalid with vertex num less then 4.') - quad_im.save(img_path + '_predict.jpg') - if cfg.predict_write2txt and len(txt_items) > 0: - with open(img_path[:-4] + '.txt', 'w') as f_txt: - f_txt.writelines(txt_items) - - -def predict_txt(east_detect, img_path, txt_path, pixel_threshold, quiet=False): - img = image.load_img(img_path) - d_wight, d_height = resize_image(img, cfg.max_predict_img_size) - scale_ratio_w = d_wight / img.width - scale_ratio_h = d_height / img.height - img = img.resize((d_wight, d_height), Image.NEAREST).convert('RGB') - img = image.img_to_array(img) - img = preprocess_input(img, mode='tf') - x = np.expand_dims(img, axis=0) - y = east_detect.predict(x) - - y = np.squeeze(y, axis=0) - y[:, :, :3] = sigmoid(y[:, :, :3]) - cond = np.greater_equal(y[:, :, 0], pixel_threshold) - activation_pixels = np.where(cond) - quad_scores, quad_after_nms = nms(y, activation_pixels) - print(quad_scores, quad_after_nms) - - txt_items = [] - for score, geo in zip(quad_scores, quad_after_nms): - if np.amin(score) > 0: - rescaled_geo = geo / [scale_ratio_w, scale_ratio_h] - rescaled_geo_list = np.reshape(rescaled_geo, (8,)).tolist() - txt_item = ','.join(map(str, rescaled_geo_list)) - txt_items.append(txt_item + '\n') - elif not quiet: - print('quad invalid with vertex num less then 4.') - if cfg.predict_write2txt and len(txt_items) > 0: - with open(txt_path, 'w') as f_txt: - f_txt.writelines(txt_items) - - -# def parse_args(): -# parser = argparse.ArgumentParser() -# parser.add_argument('--path', '-p', -# default='demo/012.png', -# help='image path') -# parser.add_argument('--threshold', '-t', -# default=cfg.pixel_threshold, -# help='pixel activation threshold') -# return parser.parse_args() - - -import os - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument('--model', - default='model/weights.h5', - help='model path') - parser.add_argument('--testdata', - default='data/image_test', - help='data path') - parser.add_argument('--threshold', '-t', - default=cfg.pixel_threshold, - help='pixel activation threshold') - args = parser.parse_args() - east = East() - east_detect = east.east_network() - east_detect.load_weights(args.model) - # east_detect.load_weights('model/east_model_weights_%s.h5' \ - # % '3T736') - path = args.testdata - filelist = os.listdir(path) - print(len(filelist)) - for i in range(len(filelist)): - s = path + '/' + filelist[i] - print(i, ':', s) - img_path = s - threshold = float(args.threshold) - print(img_path, threshold) - predict(east_detect, img_path, threshold, quiet=True) -- Gitee From fdc0efc624e31596be3ad47f54f09d2346a708b9 Mon Sep 17 00:00:00 2001 From: WinnieMa Date: Fri, 8 Jul 2022 08:00:09 +0000 Subject: [PATCH 10/17] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20Te?= =?UTF-8?q?nsorFlow/contrib/cv/AdvancedEast=5FID0130=5Ffor=5FTensorFlow/ne?= =?UTF-8?q?twork=5Ftensorflow=5FchangeVGG=5Fnpu.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network_tensorflow_changeVGG_npu.py | 219 ------------------ 1 file changed, 219 deletions(-) delete mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/network_tensorflow_changeVGG_npu.py diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/network_tensorflow_changeVGG_npu.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/network_tensorflow_changeVGG_npu.py deleted file mode 100644 index 545c2d93c..000000000 --- a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/network_tensorflow_changeVGG_npu.py +++ /dev/null @@ -1,219 +0,0 @@ -# coding=utf-8 -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================ -# Copyright 2021 Huawei Technologies Co., Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import tensorflow as tf -from tensorflow.keras import backend as K -from tensorflow.keras.layers import BatchNormalization -# from tensorflow.keras.applications.vgg16 import VGG16 -from tensorflow.keras.layers import Concatenate, UpSampling2D -from tensorflow.keras.layers import Conv2D -from tensorflow.keras.layers import Dense -from tensorflow.keras.layers import Flatten -from tensorflow.keras.layers import GlobalAveragePooling2D -from tensorflow.keras.layers import GlobalMaxPooling2D -from tensorflow.keras.layers import Input -from tensorflow.keras.layers import MaxPooling2D -from tensorflow.keras.models import Model - -import cfg -from image_util import _obtain_input_shape, is_keras_tensor -from image_util import get_source_inputs - -""" -input_shape=(img.height, img.width, 3), height and width must scaled by 32. -So images's height and width need to be pre-processed to the nearest num that -scaled by 32.And the annotations xy need to be scaled by the same ratio -as height and width respectively. -""" - - -def VGG16(include_top=True, weights='imagenet', - input_tensor=None, input_shape=None, - pooling=None, - classes=1000): - # 确定正确的输入形状 - input_shape = _obtain_input_shape(input_shape, - default_size=224, - min_size=48, - data_format=K.image_data_format(), - require_flatten=include_top) - - if input_tensor is None: - img_input = Input(shape=input_shape) - else: - if not is_keras_tensor(input_tensor): - img_input = Input(tensor=input_tensor, shape=input_shape) - else: - img_input = input_tensor - # Block 1 - x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input) - x = BatchNormalization(name='block1_batchnorm1')(x) - x = tf.nn.relu(x) - x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2')(x) - x = BatchNormalization(name='block1_batchnorm2')(x) - x = tf.nn.relu(x) - x = MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x) - - # Block 2 - x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x) - x = BatchNormalization(name='block2_batchnorm1')(x) - x = tf.nn.relu(x) - x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2')(x) - x = BatchNormalization(name='block2_batchnorm2')(x) - x = tf.nn.relu(x) - x = MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x) - - # Block 3 - x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x) - x = BatchNormalization(name='block3_batchnorm1')(x) - x = tf.nn.relu(x) - x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2')(x) - x = BatchNormalization(name='block3_batchnorm2')(x) - x = tf.nn.relu(x) - x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv3')(x) - x = BatchNormalization(name='block3_batchnorm3')(x) - x = tf.nn.relu(x) - x = MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x) - - # Block 4 - x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv1')(x) - x = BatchNormalization(name='block4_batchnorm1')(x) - x = tf.nn.relu(x) - x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2')(x) - x = BatchNormalization(name='block4_batchnorm2')(x) - x = tf.nn.relu(x) - x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv3')(x) - x = BatchNormalization(name='block4_batchnorm3')(x) - x = tf.nn.relu(x) - x = MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x) - - # Block 5 - x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv1')(x) - x = BatchNormalization(name='block5_batchnorm1')(x) - x = tf.nn.relu(x) - x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2')(x) - x = BatchNormalization(name='block5_batchnorm2')(x) - x = tf.nn.relu(x) - x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv3')(x) - x = BatchNormalization(name='block5_batchnorm3')(x) - x = tf.nn.relu(x) - x = MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x) - - # - if include_top: - # 分类 block - x = Flatten(name='flatten')(x) - x = Dense(4096, activation='relu', name='fc1')(x) - x = Dense(4096, activation='relu', name='fc2')(x) - x = Dense(classes, activation='softmax', name='predictions')(x) - else: - # 当 include_top为False时,设置pooling - if pooling == 'avg': - x = GlobalAveragePooling2D()(x) - elif pooling == 'max': - x = GlobalMaxPooling2D()(x) - - # 确保模型考虑了所有的input_tensor - if input_tensor is not None: - inputs = get_source_inputs(input_tensor) - else: - inputs = img_input - # 创建模型. - model = Model(inputs, x, name='vgg16') - - return model - - -class East: - - def __init__(self): - self.input_img = Input(name='input_img', - shape=(None, None, cfg.num_channels), - dtype='float32') - vgg16 = VGG16(input_tensor=self.input_img, - include_top=False) - if cfg.locked_layers: - # locked first two conv layers - locked_layers = [vgg16.get_layer('block1_conv1'), - vgg16.get_layer('block1_conv2')] - for layer in locked_layers: - layer.trainable = False - self.f = [vgg16.get_layer('block%d_pool' % i).output - for i in cfg.feature_layers_range] - self.f.insert(0, None) - self.diff = cfg.feature_layers_range[0] - cfg.feature_layers_num - - def g(self, i): - # i+diff in cfg.feature_layers_range - assert i + self.diff in cfg.feature_layers_range, \ - ('i=%d+diff=%d not in ' % (i, self.diff)) + \ - str(cfg.feature_layers_range) - if i == cfg.feature_layers_num: - bn = BatchNormalization()(self.h(i)) - return Conv2D(32, 3, activation='relu', padding='same')(bn) - else: - return UpSampling2D((2, 2))(self.h(i)) - - def h(self, i): - # i+diff in cfg.feature_layers_range - assert i + self.diff in cfg.feature_layers_range, \ - ('i=%d+diff=%d not in ' % (i, self.diff)) + \ - str(cfg.feature_layers_range) - if i == 1: - return self.f[i] - else: - concat = Concatenate(axis=-1)([self.g(i - 1), self.f[i]]) - bn1 = BatchNormalization()(concat) - conv_1 = Conv2D(128 // 2 ** (i - 2), 1, - activation='relu', padding='same', )(bn1) - bn2 = BatchNormalization()(conv_1) - conv_3 = Conv2D(128 // 2 ** (i - 2), 3, - activation='relu', padding='same', )(bn2) - return conv_3 - - def east_network(self): - before_output = self.g(cfg.feature_layers_num) - inside_score = Conv2D(1, 1, padding='same', name='inside_score' - )(before_output) - side_v_code = Conv2D(2, 1, padding='same', name='side_vertex_code' - )(before_output) - side_v_coord = Conv2D(4, 1, padding='same', name='side_vertex_coord' - )(before_output) - east_detect = Concatenate(axis=-1, - name='east_detect')([inside_score, - side_v_code, - side_v_coord]) - print('east_detect.shape:', east_detect.shape) - return Model(inputs=self.input_img, outputs=east_detect) - - -if __name__ == '__main__': - east = East() - east_network = east.east_network() - east_network.summary() -- Gitee From efb100b2678976e39720581eac771a023e909c43 Mon Sep 17 00:00:00 2001 From: WinnieMa Date: Fri, 8 Jul 2022 08:00:15 +0000 Subject: [PATCH 11/17] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20Te?= =?UTF-8?q?nsorFlow/contrib/cv/AdvancedEast=5FID0130=5Ffor=5FTensorFlow/la?= =?UTF-8?q?bel.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../label.py | 202 ------------------ 1 file changed, 202 deletions(-) delete mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/label.py diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/label.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/label.py deleted file mode 100644 index 1092f0989..000000000 --- a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/label.py +++ /dev/null @@ -1,202 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================ -# Copyright 2021 Huawei Technologies Co., Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import numpy as np -import os -from PIL import Image, ImageDraw -from tqdm import tqdm -import cfg - - -def point_inside_of_quad(px, py, quad_xy_list, p_min, p_max): - if (p_min[0] <= px <= p_max[0]) and (p_min[1] <= py <= p_max[1]): - xy_list = np.zeros((4, 2)) - xy_list[:3, :] = quad_xy_list[1:4, :] - quad_xy_list[:3, :] - xy_list[3] = quad_xy_list[0, :] - quad_xy_list[3, :] - yx_list = np.zeros((4, 2)) - yx_list[:, :] = quad_xy_list[:, -1:-3:-1] - a = xy_list * ([py, px] - yx_list) - b = a[:, 0] - a[:, 1] - if np.amin(b) >= 0 or np.amax(b) <= 0: - return True - else: - return False - else: - return False - - -def point_inside_of_nth_quad(px, py, xy_list, shrink_1, long_edge): - nth = -1 - vs = [[[0, 0, 3, 3, 0], [1, 1, 2, 2, 1]], - [[0, 0, 1, 1, 0], [2, 2, 3, 3, 2]]] - for ith in range(2): - quad_xy_list = np.concatenate(( - np.reshape(xy_list[vs[long_edge][ith][0]], (1, 2)), - np.reshape(shrink_1[vs[long_edge][ith][1]], (1, 2)), - np.reshape(shrink_1[vs[long_edge][ith][2]], (1, 2)), - np.reshape(xy_list[vs[long_edge][ith][3]], (1, 2))), axis=0) - p_min = np.amin(quad_xy_list, axis=0) - p_max = np.amax(quad_xy_list, axis=0) - if point_inside_of_quad(px, py, quad_xy_list, p_min, p_max): - if nth == -1: - nth = ith - else: - nth = -1 - break - return nth - - -def shrink(xy_list, ratio=cfg.shrink_ratio): - if ratio == 0.0: - return xy_list, xy_list - diff_1to3 = xy_list[:3, :] - xy_list[1:4, :] - diff_4 = xy_list[3:4, :] - xy_list[0:1, :] - diff = np.concatenate((diff_1to3, diff_4), axis=0) - dis = np.sqrt(np.sum(np.square(diff), axis=-1)) - # determine which are long or short edges - long_edge = int(np.argmax(np.sum(np.reshape(dis, (2, 2)), axis=0))) - short_edge = 1 - long_edge - # cal r length array - r = [np.minimum(dis[i], dis[(i + 1) % 4]) for i in range(4)] - # cal theta array - diff_abs = np.abs(diff) - diff_abs[:, 0] += cfg.epsilon - theta = np.arctan(diff_abs[:, 1] / diff_abs[:, 0]) - # shrink two long edges - temp_new_xy_list = np.copy(xy_list) - shrink_edge(xy_list, temp_new_xy_list, long_edge, r, theta, ratio) - shrink_edge(xy_list, temp_new_xy_list, long_edge + 2, r, theta, ratio) - # shrink two short edges - new_xy_list = np.copy(temp_new_xy_list) - shrink_edge(temp_new_xy_list, new_xy_list, short_edge, r, theta, ratio) - shrink_edge(temp_new_xy_list, new_xy_list, short_edge + 2, r, theta, ratio) - return temp_new_xy_list, new_xy_list, long_edge - - -def shrink_edge(xy_list, new_xy_list, edge, r, theta, ratio=cfg.shrink_ratio): - if ratio == 0.0: - return - start_point = edge - end_point = (edge + 1) % 4 - long_start_sign_x = np.sign( - xy_list[end_point, 0] - xy_list[start_point, 0]) - new_xy_list[start_point, 0] = \ - xy_list[start_point, 0] + \ - long_start_sign_x * ratio * r[start_point] * np.cos(theta[start_point]) - long_start_sign_y = np.sign( - xy_list[end_point, 1] - xy_list[start_point, 1]) - new_xy_list[start_point, 1] = \ - xy_list[start_point, 1] + \ - long_start_sign_y * ratio * r[start_point] * np.sin(theta[start_point]) - # long edge one, end point - long_end_sign_x = -1 * long_start_sign_x - new_xy_list[end_point, 0] = \ - xy_list[end_point, 0] + \ - long_end_sign_x * ratio * r[end_point] * np.cos(theta[start_point]) - long_end_sign_y = -1 * long_start_sign_y - new_xy_list[end_point, 1] = \ - xy_list[end_point, 1] + \ - long_end_sign_y * ratio * r[end_point] * np.sin(theta[start_point]) - - -def process_label(data_dir=cfg.data_dir): - with open(os.path.join(data_dir, cfg.val_fname), 'r') as f_val: - f_list = f_val.readlines() - with open(os.path.join(data_dir, cfg.train_fname), 'r') as f_train: - f_list.extend(f_train.readlines()) - for line, _ in zip(f_list, tqdm(range(len(f_list)))): - line_cols = str(line).strip().split(',') - img_name, width, height = \ - line_cols[0].strip(), int(line_cols[1].strip()), \ - int(line_cols[2].strip()) - gt = np.zeros((height // cfg.pixel_size, width // cfg.pixel_size, 7)) - train_label_dir = os.path.join(data_dir, cfg.train_label_dir_name) - xy_list_array = np.load(os.path.join(train_label_dir, - img_name[:-4] + '.npy')) - train_image_dir = os.path.join(data_dir, cfg.train_image_dir_name) - with Image.open(os.path.join(train_image_dir, img_name)) as im: - draw = ImageDraw.Draw(im) - for xy_list in xy_list_array: - _, shrink_xy_list, _ = shrink(xy_list, cfg.shrink_ratio) - shrink_1, _, long_edge = shrink(xy_list, cfg.shrink_side_ratio) - p_min = np.amin(shrink_xy_list, axis=0) - p_max = np.amax(shrink_xy_list, axis=0) - # floor of the float - ji_min = (p_min / cfg.pixel_size - 0.5).astype(int) - 1 - # +1 for ceil of the float and +1 for include the end - ji_max = (p_max / cfg.pixel_size - 0.5).astype(int) + 3 - imin = np.maximum(0, ji_min[1]) - imax = np.minimum(height // cfg.pixel_size, ji_max[1]) - jmin = np.maximum(0, ji_min[0]) - jmax = np.minimum(width // cfg.pixel_size, ji_max[0]) - for i in range(imin, imax): - for j in range(jmin, jmax): - px = (j + 0.5) * cfg.pixel_size - py = (i + 0.5) * cfg.pixel_size - if point_inside_of_quad(px, py, - shrink_xy_list, p_min, p_max): - gt[i, j, 0] = 1 - line_width, line_color = 1, 'red' - ith = point_inside_of_nth_quad(px, py, - xy_list, - shrink_1, - long_edge) - vs = [[[3, 0], [1, 2]], [[0, 1], [2, 3]]] - if ith in range(2): - gt[i, j, 1] = 1 - if ith == 0: - line_width, line_color = 2, 'yellow' - else: - line_width, line_color = 2, 'green' - gt[i, j, 2:3] = ith - gt[i, j, 3:5] = \ - xy_list[vs[long_edge][ith][0]] - [px, py] - gt[i, j, 5:] = \ - xy_list[vs[long_edge][ith][1]] - [px, py] - draw.line([(px - 0.5 * cfg.pixel_size, - py - 0.5 * cfg.pixel_size), - (px + 0.5 * cfg.pixel_size, - py - 0.5 * cfg.pixel_size), - (px + 0.5 * cfg.pixel_size, - py + 0.5 * cfg.pixel_size), - (px - 0.5 * cfg.pixel_size, - py + 0.5 * cfg.pixel_size), - (px - 0.5 * cfg.pixel_size, - py - 0.5 * cfg.pixel_size)], - width=line_width, fill=line_color) - act_image_dir = os.path.join(cfg.data_dir, - cfg.show_act_image_dir_name) - if cfg.draw_act_quad: - im.save(os.path.join(act_image_dir, img_name)) - train_label_dir = os.path.join(data_dir, cfg.train_label_dir_name) - np.save(os.path.join(train_label_dir, - img_name[:-4] + '_gt.npy'), gt) - - -if __name__ == '__main__': - process_label() -- Gitee From 2460dcf8ddd49dea727862d2becc092598c54300 Mon Sep 17 00:00:00 2001 From: WinnieMa Date: Fri, 8 Jul 2022 08:00:21 +0000 Subject: [PATCH 12/17] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20Te?= =?UTF-8?q?nsorFlow/contrib/cv/AdvancedEast=5FID0130=5Ffor=5FTensorFlow/cf?= =?UTF-8?q?g.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AdvancedEast_ID0130_for_TensorFlow/cfg.py | 102 ------------------ 1 file changed, 102 deletions(-) delete mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/cfg.py diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/cfg.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/cfg.py deleted file mode 100644 index 4d444a6f9..000000000 --- a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/cfg.py +++ /dev/null @@ -1,102 +0,0 @@ -# Copyright 2017 The TensorFlow Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================ -# Copyright 2021 Huawei Technologies Co., Ltd -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os - -train_task_id = '3T736' -initial_epoch = 0 -epoch_num = 24 -lr = 1e-3 -decay = 5e-4 -# clipvalue = 0.5 # default 0.5, 0 means no clip -patience = 5 -load_weights = False -lambda_inside_score_loss = 4.0 -lambda_side_vertex_code_loss = 1.0 -lambda_side_vertex_coord_loss = 1.0 - -total_img = 10000 -validation_split_ratio = 0.1 -max_train_img_size = int(train_task_id[-3:]) -max_predict_img_size = int(train_task_id[-3:]) # 2400 -assert max_train_img_size in [256, 384, 512, 640, 736], \ - 'max_train_img_size must in [256, 384, 512, 640, 736]' -if max_train_img_size == 256: - batch_size = 8 -elif max_train_img_size == 384: - batch_size = 4 -elif max_train_img_size == 512: - batch_size = 2 -else: - batch_size = 1 -steps_per_epoch = total_img * (1 - validation_split_ratio) // batch_size -validation_steps = total_img * validation_split_ratio // batch_size - -data_dir = 'icpr/' -origin_image_dir_name = 'image_10000/' -origin_txt_dir_name = 'txt_10000/' -train_image_dir_name = 'images_%s/' % train_task_id -train_label_dir_name = 'labels_%s/' % train_task_id -show_gt_image_dir_name = 'show_gt_images_%s/' % train_task_id -show_act_image_dir_name = 'show_act_images_%s/' % train_task_id -gen_origin_img = True -draw_gt_quad = True -draw_act_quad = True -val_fname = 'val_%s.txt' % train_task_id -train_fname = 'train_%s.txt' % train_task_id -# in paper it's 0.3, maybe to large to this problem -shrink_ratio = 0.2 -# pixels between 0.2 and 0.6 are side pixels -shrink_side_ratio = 0.6 -epsilon = 1e-4 - -num_channels = 3 -feature_layers_range = range(5, 1, -1) -# feature_layers_range = range(3, 0, -1) -feature_layers_num = len(feature_layers_range) -# pixel_size = 4 -pixel_size = 2 ** feature_layers_range[-1] -locked_layers = False - -if not os.path.exists('model'): - os.mkdir('model') -if not os.path.exists('saved_model'): - os.mkdir('saved_model') - -model_weights_path = 'model/weights_%s.{epoch:03d}-{val_loss:.3f}.h5' \ - % train_task_id -saved_model_file_path = 'saved_model/east_model_%s.h5' % train_task_id -saved_model_weights_file_path = 'saved_model/east_model_weights_%s.h5' \ - % train_task_id - -pixel_threshold = 0.9 -side_vertex_pixel_threshold = 0.9 -trunc_threshold = 0.1 -predict_cut_text_line = False -predict_write2txt = True -quiet = True -- Gitee From 375f5fa5a29ee817a5278c7a42ebb72ba24b8e7f Mon Sep 17 00:00:00 2001 From: WinnieMa Date: Fri, 8 Jul 2022 08:00:58 +0000 Subject: [PATCH 13/17] update. --- .../advanced_east.py | 70 ++++++++++++ .../AdvancedEast_ID0130_for_TensorFlow/atc.sh | 3 + .../AdvancedEast_ID0130_for_TensorFlow/cfg.py | 102 ++++++++++++++++++ .../cfg_bank.py | 101 +++++++++++++++++ .../clock_wise.py | 64 +++++++++++ 5 files changed, 340 insertions(+) create mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/advanced_east.py create mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/atc.sh create mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/cfg.py create mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/cfg_bank.py create mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/clock_wise.py diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/advanced_east.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/advanced_east.py new file mode 100644 index 000000000..8abd97584 --- /dev/null +++ b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/advanced_east.py @@ -0,0 +1,70 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint +import os + +from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint +from tensorflow.keras.optimizers import Adam + +# from keras.callbacks import EarlyStopping, ModelCheckpoint +# from keras.optimizers import Adam +import cfg +from data_generator import gen +from losses import quad_loss +# from network_tf import East +from network_tensorflow_changeVGG_npu import East + +os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID" +os.environ[ + "CUDA_VISIBLE_DEVICES"] = "1" # 这里是gpu的序号,指定使用的gpu对象config = tf.ConfigProto()config.gpu_options.allow_growth = True + +east = East() +east_network = east.east_network() +east_network.summary() +east_network.compile(loss=quad_loss, optimizer=Adam(lr=cfg.lr, + # clipvalue=cfg.clipvalue, + decay=cfg.decay)) +if cfg.load_weights and os.path.exists(cfg.saved_model_weights_file_path): + east_network.load_weights(cfg.saved_model_weights_file_path) +east_network.fit_generator(generator=gen(), + steps_per_epoch=cfg.steps_per_epoch, + epochs=cfg.epoch_num, + validation_data=gen(is_val=True), + validation_steps=cfg.validation_steps, + verbose=1, + initial_epoch=cfg.initial_epoch, + callbacks=[ + EarlyStopping(patience=cfg.patience, verbose=1), + ModelCheckpoint(filepath=cfg.model_weights_path, + save_best_only=True, + save_weights_only=True, + verbose=1)]) +east_network.save(cfg.saved_model_file_path) +east_network.save_weights(cfg.saved_model_weights_file_path) diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/atc.sh b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/atc.sh new file mode 100644 index 000000000..dcb54cffe --- /dev/null +++ b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/atc.sh @@ -0,0 +1,3 @@ +#!/bin/bash +atc --model=model.pb --input_shape="input_img:1,736,736,3" --framework=3 --output=./om/modelom --soc_version=Ascend310 --input_format=NHWC \ + diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/cfg.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/cfg.py new file mode 100644 index 000000000..4d444a6f9 --- /dev/null +++ b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/cfg.py @@ -0,0 +1,102 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +train_task_id = '3T736' +initial_epoch = 0 +epoch_num = 24 +lr = 1e-3 +decay = 5e-4 +# clipvalue = 0.5 # default 0.5, 0 means no clip +patience = 5 +load_weights = False +lambda_inside_score_loss = 4.0 +lambda_side_vertex_code_loss = 1.0 +lambda_side_vertex_coord_loss = 1.0 + +total_img = 10000 +validation_split_ratio = 0.1 +max_train_img_size = int(train_task_id[-3:]) +max_predict_img_size = int(train_task_id[-3:]) # 2400 +assert max_train_img_size in [256, 384, 512, 640, 736], \ + 'max_train_img_size must in [256, 384, 512, 640, 736]' +if max_train_img_size == 256: + batch_size = 8 +elif max_train_img_size == 384: + batch_size = 4 +elif max_train_img_size == 512: + batch_size = 2 +else: + batch_size = 1 +steps_per_epoch = total_img * (1 - validation_split_ratio) // batch_size +validation_steps = total_img * validation_split_ratio // batch_size + +data_dir = 'icpr/' +origin_image_dir_name = 'image_10000/' +origin_txt_dir_name = 'txt_10000/' +train_image_dir_name = 'images_%s/' % train_task_id +train_label_dir_name = 'labels_%s/' % train_task_id +show_gt_image_dir_name = 'show_gt_images_%s/' % train_task_id +show_act_image_dir_name = 'show_act_images_%s/' % train_task_id +gen_origin_img = True +draw_gt_quad = True +draw_act_quad = True +val_fname = 'val_%s.txt' % train_task_id +train_fname = 'train_%s.txt' % train_task_id +# in paper it's 0.3, maybe to large to this problem +shrink_ratio = 0.2 +# pixels between 0.2 and 0.6 are side pixels +shrink_side_ratio = 0.6 +epsilon = 1e-4 + +num_channels = 3 +feature_layers_range = range(5, 1, -1) +# feature_layers_range = range(3, 0, -1) +feature_layers_num = len(feature_layers_range) +# pixel_size = 4 +pixel_size = 2 ** feature_layers_range[-1] +locked_layers = False + +if not os.path.exists('model'): + os.mkdir('model') +if not os.path.exists('saved_model'): + os.mkdir('saved_model') + +model_weights_path = 'model/weights_%s.{epoch:03d}-{val_loss:.3f}.h5' \ + % train_task_id +saved_model_file_path = 'saved_model/east_model_%s.h5' % train_task_id +saved_model_weights_file_path = 'saved_model/east_model_weights_%s.h5' \ + % train_task_id + +pixel_threshold = 0.9 +side_vertex_pixel_threshold = 0.9 +trunc_threshold = 0.1 +predict_cut_text_line = False +predict_write2txt = True +quiet = True diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/cfg_bank.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/cfg_bank.py new file mode 100644 index 000000000..c7e6f919d --- /dev/null +++ b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/cfg_bank.py @@ -0,0 +1,101 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os + +train_task_id = '3T832' +initial_epoch = 0 +epoch_num = 24 +lr = 1e-3 +decay = 5e-4 +# clipvalue = 0.5 # default 0.5, 0 means no clip +patience = 5 +load_weights = False +lambda_inside_score_loss = 4.0 +lambda_side_vertex_code_loss = 1.0 +lambda_side_vertex_coord_loss = 1.0 + +total_img = 10000 +validation_split_ratio = 0.1 +max_train_img_size = int(train_task_id[-3:]) +max_predict_img_size = int(train_task_id[-3:]) # 2400 +assert max_train_img_size in [256, 384, 512, 640, 736, 832], \ + 'max_train_img_size must in [256, 384, 512, 640, 736, 832]' +if max_train_img_size == 256: + batch_size = 8 +elif max_train_img_size == 384: + batch_size = 4 +elif max_train_img_size == 512: + batch_size = 2 +else: + batch_size = 1 +steps_per_epoch = total_img * (1 - validation_split_ratio) // batch_size +validation_steps = total_img * validation_split_ratio // batch_size + +data_dir = 'dataset/train' +origin_image_dir_name = 'pitures/' +origin_txt_dir_name = 'txts/' +train_image_dir_name = 'images_%s/' % train_task_id +train_label_dir_name = 'labels_%s/' % train_task_id +show_gt_image_dir_name = 'show_gt_images_%s/' % train_task_id +show_act_image_dir_name = 'show_act_images_%s/' % train_task_id +gen_origin_img = True +draw_gt_quad = True +draw_act_quad = True +val_fname = 'val_%s.txt' % train_task_id +train_fname = 'train_%s.txt' % train_task_id +# in paper it's 0.3, maybe to large to this problem +shrink_ratio = 0.2 +# pixels between 0.2 and 0.6 are side pixels +shrink_side_ratio = 0.6 +epsilon = 1e-4 + +num_channels = 3 +feature_layers_range = range(5, 1, -1) +# feature_layers_range = range(3, 0, -1) +feature_layers_num = len(feature_layers_range) +# pixel_size = 4 +pixel_size = 2 ** feature_layers_range[-1] +locked_layers = False + +if not os.path.exists('model'): + os.mkdir('model') +if not os.path.exists('saved_model'): + os.mkdir('saved_model') + +model_weights_path = 'model/weights_%s.{epoch:03d}-{val_loss:.3f}.h5' \ + % train_task_id +saved_model_file_path = 'saved_model/east_model_%s.h5' % train_task_id +saved_model_weights_file_path = 'saved_model/east_model_weights_%s.h5' \ + % train_task_id + +pixel_threshold = 0.7 +side_vertex_pixel_threshold = 0.7 +trunc_threshold = 0.1 +predict_cut_text_line = False +predict_write2txt = True diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/clock_wise.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/clock_wise.py new file mode 100644 index 000000000..ae3709ee9 --- /dev/null +++ b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/clock_wise.py @@ -0,0 +1,64 @@ +from scipy.spatial import distance as dist +import numpy as np +import math + +def cos_dist(a, b): + if len(a) != len(b): + return None + part_up = 0.0 + a_sq = 0.0 + b_sq = 0.0 + for a1, b1 in zip(a,b): + part_up += a1*b1 + a_sq += a1**2 + b_sq += b1**2 + part_down = math.sqrt(a_sq*b_sq) + if part_down == 0.0: + return None + else: + return part_up / part_down + +def order_points(pts): + xSorted = pts[np.argsort(pts[:, 0]), :] + leftMost = xSorted[:2, :] + rightMost = xSorted[2:, :] + + leftMost = leftMost[np.argsort(leftMost[:, 1]), :] + (tl, bl) = leftMost + D = dist.cdist(tl[np.newaxis], rightMost, "euclidean")[0] + (br, tr) = rightMost[np.argsort(D)[::-1], :] + return np.array([tl, tr, br, bl], dtype="int32") + +def order_points_quadrangle(pts): + xSorted = pts[np.argsort(pts[:, 0]), :] + leftMost = xSorted[:2, :] + rightMost = xSorted[2:, :] + leftMost = leftMost[np.argsort(leftMost[:, 1]), :] + (tl, bl) = leftMost + + vector_0 = np.array(bl-tl) + vector_1 = np.array(rightMost[0]-tl) + vector_2 = np.array(rightMost[1]-tl) + angle = [np.arccos(cos_dist(vector_0, vector_1)), np.arccos(cos_dist(vector_0, vector_2))] + (br, tr) = rightMost[np.argsort(angle), :] + return np.array([tl, tr, br, bl], dtype="int32") + +from functools import reduce +import operator +import math +def order_points_tuple(pts): + pts = pts.tolist() + coords = [] + for elem in pts: + coords.append(tuple(elem)) + center = tuple(map(operator,truediv, reduce(lambda x, y:map(operator.add, x, y), coords), [len(coords)] * 2)) + output = sorted(coords, key=lambda coords: (-135 - math.degrees(math.atan2(*tuple(map(operator.sub, coords, center))[::-1]))) % 360, reverse=True) + res = [] + for elem in output: + res.append(list(elem)) + return np.array(res, dtype="int32") +points = np.array([[54,20],[39,48],[117,52],[121,21]]) +print(order_points(points)) +pt = np.array([703,211,754,283,756,223,747,212]).reshape(4,2) +print(order_points(pt)) +print(order_points_tuple(pt)) \ No newline at end of file -- Gitee From 24acebad1bc44555252a63b546a4a8143bfe0941 Mon Sep 17 00:00:00 2001 From: WinnieMa Date: Fri, 8 Jul 2022 08:01:33 +0000 Subject: [PATCH 14/17] update. --- .../h5_to_pb.py | 68 ++++++ .../image2bin.py | 89 +++++++ .../image_util.py | 216 +++++++++++++++++ .../label.py | 202 ++++++++++++++++ .../msame.sh | 6 + .../network_add_bn.py | 219 ++++++++++++++++++ .../AdvancedEast_ID0130_for_TensorFlow/nms.py | 114 +++++++++ 7 files changed, 914 insertions(+) create mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/h5_to_pb.py create mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/image2bin.py create mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/image_util.py create mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/label.py create mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/msame.sh create mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/network_add_bn.py create mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/nms.py diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/h5_to_pb.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/h5_to_pb.py new file mode 100644 index 000000000..fa6c05dad --- /dev/null +++ b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/h5_to_pb.py @@ -0,0 +1,68 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from tensorflow.keras.models import load_model +import tensorflow as tf +import os +import os.path as osp +from tensorflow.keras import backend as K +from network_add_bn import East +from predict import predict_txt +import cfg + +#路径参数 +input_path = './model/' +weight_file = 'east_model_3T832.h5' +weight_file_path = osp.join(input_path,weight_file) +output_graph_name = weight_file[:-3] + '.pb' +#转换函数 +def h5_to_pb(h5_model,output_dir,model_name,out_prefix = "output_",log_tensorboard = True): + if osp.exists(output_dir) == False: + os.mkdir(output_dir) + out_nodes = [] + for i in range(len(h5_model.outputs)): + out_nodes.append(out_prefix + str(i + 1)) + tf.identity(h5_model.output[i],out_prefix + str(i + 1)) + sess = K.get_session() + from tensorflow.python.framework import graph_util,graph_io + init_graph = sess.graph.as_graph_def() + main_graph = graph_util.convert_variables_to_constants(sess,init_graph,out_nodes) + graph_io.write_graph(main_graph,output_dir,name = model_name,as_text = False) + if log_tensorboard: + from tensorflow.python.tools import import_pb_to_tensorboard + import_pb_to_tensorboard.import_to_tensorboard(osp.join(output_dir,model_name),output_dir) +#输出路径 +output_dir = "trans_model" +#加载模型 +east = East() +east_detect = east.east_network() +east_detect.load_weights(cfg.saved_model_weights_file_path) +h5_model =east_detect +h5_to_pb(h5_model,output_dir = output_dir,model_name = output_graph_name) +print('model saved') \ No newline at end of file diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/image2bin.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/image2bin.py new file mode 100644 index 000000000..291e0e844 --- /dev/null +++ b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/image2bin.py @@ -0,0 +1,89 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import cfg +import argparse +import os +import numpy as np +from PIL import Image, ImageDraw +from tensorflow.keras.applications.vgg16 import preprocess_input +from tensorflow.keras.preprocessing import image + +def resize_image(im, max_img_size=cfg.max_train_img_size): + im_width = np.minimum(im.width, max_img_size) + if im_width == max_img_size < im.width: + im_height = int((im_width / im.width) * im.height) + else: + im_height = im.height + o_height = np.minimum(im_height, max_img_size) + if o_height == max_img_size < im_height: + o_width = int((o_height / im_height) * im_width) + else: + o_width = im_width + d_wight = o_width - (o_width % 32) + d_height = o_height - (o_height % 32) + return d_wight, d_height + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + parser.add_argument("--src_path", default="../image_test1", help="path of original pictures") + parser.add_argument("--dst_path", default="../image_test_bin", help="path of output bin files") + parser.add_argument("--pic_num", default=10000, help="picture number") + args = parser.parse_args() + src_path = args.src_path + dst_path = args.dst_path + pic_num = args.pic_num + files = os.listdir(src_path) + files.sort() + n = 0 + for file in files: + src = src_path + "/" + file + print("start to process %s"%src) + img = image.load_img(src) + d_wight, d_height = resize_image(img, cfg.max_predict_img_size) + img = img.resize((d_wight, d_height), Image.NEAREST).convert('RGB') + img = image.img_to_array(img,dtype=np.float32) + print(img.shape) + print(d_wight, d_height) + if d_height != 736: + zero = np.zeros((736 - d_height, d_wight, 3),dtype=np.float32) + img = np.concatenate((img, zero), axis=0) + print(img.shape) + if d_wight != 736: + zero = np.zeros((736, 736 - d_wight, 3),dtype=np.float32) + img = np.concatenate((img, zero), axis=1) + print('img.shape', img.shape) + img = preprocess_input(img, mode='tf') + x = np.expand_dims(img, axis=0) + print('x.shape', x.shape) + print(x.dtype) + x.tofile(dst_path + "/" + file + ".bin") + n += 1 + if int(pic_num) == n: + break \ No newline at end of file diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/image_util.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/image_util.py new file mode 100644 index 000000000..5a2c1f67f --- /dev/null +++ b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/image_util.py @@ -0,0 +1,216 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import warnings +import tensorflow as tf +from tensorflow.python.ops import variables as tf_variables + +def _obtain_input_shape(input_shape, + default_size, + min_size, + data_format, + require_flatten, + weights=None): + """Internal utility to compute/validate a model's input shape. + + # Arguments + input_shape: Either None (will return the default network input shape), + or a user-provided shape to be validated. + default_size: Default input width/height for the model. + min_size: Minimum input width/height accepted by the model. + data_format: Image data format to use. + require_flatten: Whether the model is expected to + be linked to a classifier via a Flatten layer. + weights: One of `None` (random initialization) + or 'imagenet' (pre-training on ImageNet). + If weights='imagenet' input channels must be equal to 3. + + # Returns + An integer shape tuple (may include None entries). + + # Raises + ValueError: In case of invalid argument values. + """ + if weights != 'imagenet' and input_shape and len(input_shape) == 3: + if data_format == 'channels_first': + if input_shape[0] not in {1, 3}: + warnings.warn( + 'This model usually expects 1 or 3 input channels. ' + 'However, it was passed an input_shape with ' + + str(input_shape[0]) + ' input channels.') + default_shape = (input_shape[0], default_size, default_size) + else: + if input_shape[-1] not in {1, 3}: + warnings.warn( + 'This model usually expects 1 or 3 input channels. ' + 'However, it was passed an input_shape with ' + + str(input_shape[-1]) + ' input channels.') + default_shape = (default_size, default_size, input_shape[-1]) + else: + if data_format == 'channels_first': + default_shape = (3, default_size, default_size) + else: + default_shape = (default_size, default_size, 3) + if weights == 'imagenet' and require_flatten: + if input_shape is not None: + if input_shape != default_shape: + raise ValueError('When setting`include_top=True` ' + 'and loading `imagenet` weights, ' + '`input_shape` should be ' + + str(default_shape) + '.') + return default_shape + if input_shape: + if data_format == 'channels_first': + if input_shape is not None: + if len(input_shape) != 3: + raise ValueError( + '`input_shape` must be a tuple of three integers.') + if input_shape[0] != 3 and weights == 'imagenet': + raise ValueError('The input must have 3 channels; got ' + '`input_shape=' + str(input_shape) + '`') + if ((input_shape[1] is not None and input_shape[1] < min_size) or + (input_shape[2] is not None and input_shape[2] < min_size)): + raise ValueError('Input size must be at least ' + + str(min_size) + 'x' + str(min_size) + '; got ' + '`input_shape=' + str(input_shape) + '`') + else: + if input_shape is not None: + if len(input_shape) != 3: + raise ValueError( + '`input_shape` must be a tuple of three integers.') + if input_shape[-1] != 3 and weights == 'imagenet': + raise ValueError('The input must have 3 channels; got ' + '`input_shape=' + str(input_shape) + '`') + if ((input_shape[0] is not None and input_shape[0] < min_size) or + (input_shape[1] is not None and input_shape[1] < min_size)): + raise ValueError('Input size must be at least ' + + str(min_size) + 'x' + str(min_size) + '; got ' + '`input_shape=' + str(input_shape) + '`') + else: + if require_flatten: + input_shape = default_shape + else: + if data_format == 'channels_first': + input_shape = (3, None, None) + else: + input_shape = (None, None, 3) + if require_flatten: + if None in input_shape: + raise ValueError('If `include_top` is True, ' + 'you should specify a static `input_shape`. ' + 'Got `input_shape=' + str(input_shape) + '`') + return input_shape + + + +def get_source_inputs(tensor, layer=None, node_index=None): + """Returns the list of input tensors necessary to compute `tensor`. + + Output will always be a list of tensors + (potentially with 1 element). + + # Arguments + tensor: The tensor to start from. + layer: Origin layer of the tensor. Will be + determined via tensor._keras_history if not provided. + node_index: Origin node index of the tensor. + + # Returns + List of input tensors. + """ + if not hasattr(tensor, '_keras_history'): + return tensor + + if layer is None or node_index: + layer, node_index, _ = tensor._keras_history + if not layer._inbound_nodes: + return [tensor] + else: + node = layer._inbound_nodes[node_index] + if not node.inbound_layers: + # Reached an Input layer, stop recursion. + return node.input_tensors + else: + source_tensors = [] + for i in range(len(node.inbound_layers)): + x = node.input_tensors[i] + layer = node.inbound_layers[i] + node_index = node.node_indices[i] + previous_sources = get_source_inputs(x, + layer, + node_index) + # Avoid input redundancy. + for x in previous_sources: + if x not in source_tensors: + source_tensors.append(x) + return source_tensors + +def is_keras_tensor(x): + """Returns whether `x` is a Keras tensor. + + A "Keras tensor" is a tensor that was returned by a Keras layer, + (`Layer` class) or by `Input`. + + # Arguments + x: A candidate tensor. + + # Returns + A boolean: Whether the argument is a Keras tensor. + + # Raises + ValueError: In case `x` is not a symbolic tensor. + + # Examples + ```python + >>> from keras import backend as K + >>> from keras.layers import Input, Dense + >>> np_var = numpy.array([1, 2]) + >>> K.is_keras_tensor(np_var) # A numpy array is not a symbolic tensor. + ValueError + >>> k_var = tf.placeholder('float32', shape=(1,1)) + >>> K.is_keras_tensor(k_var) # A variable indirectly created outside of keras is not a Keras tensor. + False + >>> keras_var = K.variable(np_var) + >>> K.is_keras_tensor(keras_var) # A variable created with the keras backend is not a Keras tensor. + False + >>> keras_placeholder = K.placeholder(shape=(2, 4, 5)) + >>> K.is_keras_tensor(keras_placeholder) # A placeholder is not a Keras tensor. + False + >>> keras_input = Input([10]) + >>> K.is_keras_tensor(keras_input) # An Input is a Keras tensor. + True + >>> keras_layer_output = Dense(10)(keras_input) + >>> K.is_keras_tensor(keras_layer_output) # Any Keras layer output is a Keras tensor. + True + ``` + """ + if not isinstance(x, (tf.Tensor, + tf_variables.Variable, + tf.SparseTensor)): + raise ValueError('Unexpectedly found an instance of type `' + str(type(x)) + '`. ' + 'Expected a symbolic tensor instance.') + return hasattr(x, '_keras_history') \ No newline at end of file diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/label.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/label.py new file mode 100644 index 000000000..1092f0989 --- /dev/null +++ b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/label.py @@ -0,0 +1,202 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import os +from PIL import Image, ImageDraw +from tqdm import tqdm +import cfg + + +def point_inside_of_quad(px, py, quad_xy_list, p_min, p_max): + if (p_min[0] <= px <= p_max[0]) and (p_min[1] <= py <= p_max[1]): + xy_list = np.zeros((4, 2)) + xy_list[:3, :] = quad_xy_list[1:4, :] - quad_xy_list[:3, :] + xy_list[3] = quad_xy_list[0, :] - quad_xy_list[3, :] + yx_list = np.zeros((4, 2)) + yx_list[:, :] = quad_xy_list[:, -1:-3:-1] + a = xy_list * ([py, px] - yx_list) + b = a[:, 0] - a[:, 1] + if np.amin(b) >= 0 or np.amax(b) <= 0: + return True + else: + return False + else: + return False + + +def point_inside_of_nth_quad(px, py, xy_list, shrink_1, long_edge): + nth = -1 + vs = [[[0, 0, 3, 3, 0], [1, 1, 2, 2, 1]], + [[0, 0, 1, 1, 0], [2, 2, 3, 3, 2]]] + for ith in range(2): + quad_xy_list = np.concatenate(( + np.reshape(xy_list[vs[long_edge][ith][0]], (1, 2)), + np.reshape(shrink_1[vs[long_edge][ith][1]], (1, 2)), + np.reshape(shrink_1[vs[long_edge][ith][2]], (1, 2)), + np.reshape(xy_list[vs[long_edge][ith][3]], (1, 2))), axis=0) + p_min = np.amin(quad_xy_list, axis=0) + p_max = np.amax(quad_xy_list, axis=0) + if point_inside_of_quad(px, py, quad_xy_list, p_min, p_max): + if nth == -1: + nth = ith + else: + nth = -1 + break + return nth + + +def shrink(xy_list, ratio=cfg.shrink_ratio): + if ratio == 0.0: + return xy_list, xy_list + diff_1to3 = xy_list[:3, :] - xy_list[1:4, :] + diff_4 = xy_list[3:4, :] - xy_list[0:1, :] + diff = np.concatenate((diff_1to3, diff_4), axis=0) + dis = np.sqrt(np.sum(np.square(diff), axis=-1)) + # determine which are long or short edges + long_edge = int(np.argmax(np.sum(np.reshape(dis, (2, 2)), axis=0))) + short_edge = 1 - long_edge + # cal r length array + r = [np.minimum(dis[i], dis[(i + 1) % 4]) for i in range(4)] + # cal theta array + diff_abs = np.abs(diff) + diff_abs[:, 0] += cfg.epsilon + theta = np.arctan(diff_abs[:, 1] / diff_abs[:, 0]) + # shrink two long edges + temp_new_xy_list = np.copy(xy_list) + shrink_edge(xy_list, temp_new_xy_list, long_edge, r, theta, ratio) + shrink_edge(xy_list, temp_new_xy_list, long_edge + 2, r, theta, ratio) + # shrink two short edges + new_xy_list = np.copy(temp_new_xy_list) + shrink_edge(temp_new_xy_list, new_xy_list, short_edge, r, theta, ratio) + shrink_edge(temp_new_xy_list, new_xy_list, short_edge + 2, r, theta, ratio) + return temp_new_xy_list, new_xy_list, long_edge + + +def shrink_edge(xy_list, new_xy_list, edge, r, theta, ratio=cfg.shrink_ratio): + if ratio == 0.0: + return + start_point = edge + end_point = (edge + 1) % 4 + long_start_sign_x = np.sign( + xy_list[end_point, 0] - xy_list[start_point, 0]) + new_xy_list[start_point, 0] = \ + xy_list[start_point, 0] + \ + long_start_sign_x * ratio * r[start_point] * np.cos(theta[start_point]) + long_start_sign_y = np.sign( + xy_list[end_point, 1] - xy_list[start_point, 1]) + new_xy_list[start_point, 1] = \ + xy_list[start_point, 1] + \ + long_start_sign_y * ratio * r[start_point] * np.sin(theta[start_point]) + # long edge one, end point + long_end_sign_x = -1 * long_start_sign_x + new_xy_list[end_point, 0] = \ + xy_list[end_point, 0] + \ + long_end_sign_x * ratio * r[end_point] * np.cos(theta[start_point]) + long_end_sign_y = -1 * long_start_sign_y + new_xy_list[end_point, 1] = \ + xy_list[end_point, 1] + \ + long_end_sign_y * ratio * r[end_point] * np.sin(theta[start_point]) + + +def process_label(data_dir=cfg.data_dir): + with open(os.path.join(data_dir, cfg.val_fname), 'r') as f_val: + f_list = f_val.readlines() + with open(os.path.join(data_dir, cfg.train_fname), 'r') as f_train: + f_list.extend(f_train.readlines()) + for line, _ in zip(f_list, tqdm(range(len(f_list)))): + line_cols = str(line).strip().split(',') + img_name, width, height = \ + line_cols[0].strip(), int(line_cols[1].strip()), \ + int(line_cols[2].strip()) + gt = np.zeros((height // cfg.pixel_size, width // cfg.pixel_size, 7)) + train_label_dir = os.path.join(data_dir, cfg.train_label_dir_name) + xy_list_array = np.load(os.path.join(train_label_dir, + img_name[:-4] + '.npy')) + train_image_dir = os.path.join(data_dir, cfg.train_image_dir_name) + with Image.open(os.path.join(train_image_dir, img_name)) as im: + draw = ImageDraw.Draw(im) + for xy_list in xy_list_array: + _, shrink_xy_list, _ = shrink(xy_list, cfg.shrink_ratio) + shrink_1, _, long_edge = shrink(xy_list, cfg.shrink_side_ratio) + p_min = np.amin(shrink_xy_list, axis=0) + p_max = np.amax(shrink_xy_list, axis=0) + # floor of the float + ji_min = (p_min / cfg.pixel_size - 0.5).astype(int) - 1 + # +1 for ceil of the float and +1 for include the end + ji_max = (p_max / cfg.pixel_size - 0.5).astype(int) + 3 + imin = np.maximum(0, ji_min[1]) + imax = np.minimum(height // cfg.pixel_size, ji_max[1]) + jmin = np.maximum(0, ji_min[0]) + jmax = np.minimum(width // cfg.pixel_size, ji_max[0]) + for i in range(imin, imax): + for j in range(jmin, jmax): + px = (j + 0.5) * cfg.pixel_size + py = (i + 0.5) * cfg.pixel_size + if point_inside_of_quad(px, py, + shrink_xy_list, p_min, p_max): + gt[i, j, 0] = 1 + line_width, line_color = 1, 'red' + ith = point_inside_of_nth_quad(px, py, + xy_list, + shrink_1, + long_edge) + vs = [[[3, 0], [1, 2]], [[0, 1], [2, 3]]] + if ith in range(2): + gt[i, j, 1] = 1 + if ith == 0: + line_width, line_color = 2, 'yellow' + else: + line_width, line_color = 2, 'green' + gt[i, j, 2:3] = ith + gt[i, j, 3:5] = \ + xy_list[vs[long_edge][ith][0]] - [px, py] + gt[i, j, 5:] = \ + xy_list[vs[long_edge][ith][1]] - [px, py] + draw.line([(px - 0.5 * cfg.pixel_size, + py - 0.5 * cfg.pixel_size), + (px + 0.5 * cfg.pixel_size, + py - 0.5 * cfg.pixel_size), + (px + 0.5 * cfg.pixel_size, + py + 0.5 * cfg.pixel_size), + (px - 0.5 * cfg.pixel_size, + py + 0.5 * cfg.pixel_size), + (px - 0.5 * cfg.pixel_size, + py - 0.5 * cfg.pixel_size)], + width=line_width, fill=line_color) + act_image_dir = os.path.join(cfg.data_dir, + cfg.show_act_image_dir_name) + if cfg.draw_act_quad: + im.save(os.path.join(act_image_dir, img_name)) + train_label_dir = os.path.join(data_dir, cfg.train_label_dir_name) + np.save(os.path.join(train_label_dir, + img_name[:-4] + '_gt.npy'), gt) + + +if __name__ == '__main__': + process_label() diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/msame.sh b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/msame.sh new file mode 100644 index 000000000..fd27404fb --- /dev/null +++ b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/msame.sh @@ -0,0 +1,6 @@ +MODEL="/home/HwHiAiUser/11my310/ACL/modelom.om" +INPUT="/home/HwHiAiUser/11my310/image_test_bin/" +OUTPUT="/home/HwHiAiUser/11my310/image_test_output" +./msame --model $MODEL --input $INPUT --output $OUTPUT --outfmt BIN + + diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/network_add_bn.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/network_add_bn.py new file mode 100644 index 000000000..545c2d93c --- /dev/null +++ b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/network_add_bn.py @@ -0,0 +1,219 @@ +# coding=utf-8 +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import tensorflow as tf +from tensorflow.keras import backend as K +from tensorflow.keras.layers import BatchNormalization +# from tensorflow.keras.applications.vgg16 import VGG16 +from tensorflow.keras.layers import Concatenate, UpSampling2D +from tensorflow.keras.layers import Conv2D +from tensorflow.keras.layers import Dense +from tensorflow.keras.layers import Flatten +from tensorflow.keras.layers import GlobalAveragePooling2D +from tensorflow.keras.layers import GlobalMaxPooling2D +from tensorflow.keras.layers import Input +from tensorflow.keras.layers import MaxPooling2D +from tensorflow.keras.models import Model + +import cfg +from image_util import _obtain_input_shape, is_keras_tensor +from image_util import get_source_inputs + +""" +input_shape=(img.height, img.width, 3), height and width must scaled by 32. +So images's height and width need to be pre-processed to the nearest num that +scaled by 32.And the annotations xy need to be scaled by the same ratio +as height and width respectively. +""" + + +def VGG16(include_top=True, weights='imagenet', + input_tensor=None, input_shape=None, + pooling=None, + classes=1000): + # 确定正确的输入形状 + input_shape = _obtain_input_shape(input_shape, + default_size=224, + min_size=48, + data_format=K.image_data_format(), + require_flatten=include_top) + + if input_tensor is None: + img_input = Input(shape=input_shape) + else: + if not is_keras_tensor(input_tensor): + img_input = Input(tensor=input_tensor, shape=input_shape) + else: + img_input = input_tensor + # Block 1 + x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input) + x = BatchNormalization(name='block1_batchnorm1')(x) + x = tf.nn.relu(x) + x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2')(x) + x = BatchNormalization(name='block1_batchnorm2')(x) + x = tf.nn.relu(x) + x = MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x) + + # Block 2 + x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x) + x = BatchNormalization(name='block2_batchnorm1')(x) + x = tf.nn.relu(x) + x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2')(x) + x = BatchNormalization(name='block2_batchnorm2')(x) + x = tf.nn.relu(x) + x = MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x) + + # Block 3 + x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x) + x = BatchNormalization(name='block3_batchnorm1')(x) + x = tf.nn.relu(x) + x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2')(x) + x = BatchNormalization(name='block3_batchnorm2')(x) + x = tf.nn.relu(x) + x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv3')(x) + x = BatchNormalization(name='block3_batchnorm3')(x) + x = tf.nn.relu(x) + x = MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x) + + # Block 4 + x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv1')(x) + x = BatchNormalization(name='block4_batchnorm1')(x) + x = tf.nn.relu(x) + x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2')(x) + x = BatchNormalization(name='block4_batchnorm2')(x) + x = tf.nn.relu(x) + x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv3')(x) + x = BatchNormalization(name='block4_batchnorm3')(x) + x = tf.nn.relu(x) + x = MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x) + + # Block 5 + x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv1')(x) + x = BatchNormalization(name='block5_batchnorm1')(x) + x = tf.nn.relu(x) + x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2')(x) + x = BatchNormalization(name='block5_batchnorm2')(x) + x = tf.nn.relu(x) + x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv3')(x) + x = BatchNormalization(name='block5_batchnorm3')(x) + x = tf.nn.relu(x) + x = MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x) + + # + if include_top: + # 分类 block + x = Flatten(name='flatten')(x) + x = Dense(4096, activation='relu', name='fc1')(x) + x = Dense(4096, activation='relu', name='fc2')(x) + x = Dense(classes, activation='softmax', name='predictions')(x) + else: + # 当 include_top为False时,设置pooling + if pooling == 'avg': + x = GlobalAveragePooling2D()(x) + elif pooling == 'max': + x = GlobalMaxPooling2D()(x) + + # 确保模型考虑了所有的input_tensor + if input_tensor is not None: + inputs = get_source_inputs(input_tensor) + else: + inputs = img_input + # 创建模型. + model = Model(inputs, x, name='vgg16') + + return model + + +class East: + + def __init__(self): + self.input_img = Input(name='input_img', + shape=(None, None, cfg.num_channels), + dtype='float32') + vgg16 = VGG16(input_tensor=self.input_img, + include_top=False) + if cfg.locked_layers: + # locked first two conv layers + locked_layers = [vgg16.get_layer('block1_conv1'), + vgg16.get_layer('block1_conv2')] + for layer in locked_layers: + layer.trainable = False + self.f = [vgg16.get_layer('block%d_pool' % i).output + for i in cfg.feature_layers_range] + self.f.insert(0, None) + self.diff = cfg.feature_layers_range[0] - cfg.feature_layers_num + + def g(self, i): + # i+diff in cfg.feature_layers_range + assert i + self.diff in cfg.feature_layers_range, \ + ('i=%d+diff=%d not in ' % (i, self.diff)) + \ + str(cfg.feature_layers_range) + if i == cfg.feature_layers_num: + bn = BatchNormalization()(self.h(i)) + return Conv2D(32, 3, activation='relu', padding='same')(bn) + else: + return UpSampling2D((2, 2))(self.h(i)) + + def h(self, i): + # i+diff in cfg.feature_layers_range + assert i + self.diff in cfg.feature_layers_range, \ + ('i=%d+diff=%d not in ' % (i, self.diff)) + \ + str(cfg.feature_layers_range) + if i == 1: + return self.f[i] + else: + concat = Concatenate(axis=-1)([self.g(i - 1), self.f[i]]) + bn1 = BatchNormalization()(concat) + conv_1 = Conv2D(128 // 2 ** (i - 2), 1, + activation='relu', padding='same', )(bn1) + bn2 = BatchNormalization()(conv_1) + conv_3 = Conv2D(128 // 2 ** (i - 2), 3, + activation='relu', padding='same', )(bn2) + return conv_3 + + def east_network(self): + before_output = self.g(cfg.feature_layers_num) + inside_score = Conv2D(1, 1, padding='same', name='inside_score' + )(before_output) + side_v_code = Conv2D(2, 1, padding='same', name='side_vertex_code' + )(before_output) + side_v_coord = Conv2D(4, 1, padding='same', name='side_vertex_coord' + )(before_output) + east_detect = Concatenate(axis=-1, + name='east_detect')([inside_score, + side_v_code, + side_v_coord]) + print('east_detect.shape:', east_detect.shape) + return Model(inputs=self.input_img, outputs=east_detect) + + +if __name__ == '__main__': + east = East() + east_network = east.east_network() + east_network.summary() diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/nms.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/nms.py new file mode 100644 index 000000000..1b7cbf9c7 --- /dev/null +++ b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/nms.py @@ -0,0 +1,114 @@ +# coding=utf-8 +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np + +import cfg + + +def should_merge(region, i, j): + neighbor = {(i, j - 1)} + return not region.isdisjoint(neighbor) + + +def region_neighbor(region_set): + region_pixels = np.array(list(region_set)) + j_min = np.amin(region_pixels, axis=0)[1] - 1 + j_max = np.amax(region_pixels, axis=0)[1] + 1 + i_m = np.amin(region_pixels, axis=0)[0] + 1 + region_pixels[:, 0] += 1 + neighbor = {(region_pixels[n, 0], region_pixels[n, 1]) for n in + range(len(region_pixels))} + neighbor.add((i_m, j_min)) + neighbor.add((i_m, j_max)) + return neighbor + + +def region_group(region_list): + S = [i for i in range(len(region_list))] + D = [] + while len(S) > 0: + m = S.pop(0) + if len(S) == 0: + # S has only one element, put it to D + D.append([m]) + else: + D.append(rec_region_merge(region_list, m, S)) + return D + + +def rec_region_merge(region_list, m, S): + rows = [m] + tmp = [] + for n in S: + if not region_neighbor(region_list[m]).isdisjoint(region_list[n]) or \ + not region_neighbor(region_list[n]).isdisjoint(region_list[m]): + # 第m与n相交 + tmp.append(n) + for d in tmp: + S.remove(d) + for e in tmp: + rows.extend(rec_region_merge(region_list, e, S)) + return rows + + +def nms(predict, activation_pixels, threshold=cfg.side_vertex_pixel_threshold): + region_list = [] + for i, j in zip(activation_pixels[0], activation_pixels[1]): + merge = False + for k in range(len(region_list)): + if should_merge(region_list[k], i, j): + region_list[k].add((i, j)) + merge = True + # Fixme 重叠文本区域处理,存在和多个区域邻接的pixels,先都merge试试 + # break + if not merge: + region_list.append({(i, j)}) + D = region_group(region_list) + quad_list = np.zeros((len(D), 4, 2)) + score_list = np.zeros((len(D), 4)) + for group, g_th in zip(D, range(len(D))): + total_score = np.zeros((4, 2)) + for row in group: + for ij in region_list[row]: + score = predict[ij[0], ij[1], 1] + if score >= threshold: + ith_score = predict[ij[0], ij[1], 2:3] + if not (cfg.trunc_threshold <= ith_score < 1 - + cfg.trunc_threshold): + ith = int(np.around(ith_score)) + total_score[ith * 2:(ith + 1) * 2] += score + px = (ij[1] + 0.5) * cfg.pixel_size + py = (ij[0] + 0.5) * cfg.pixel_size + p_v = [px, py] + np.reshape(predict[ij[0], ij[1], 3:7], + (2, 2)) + quad_list[g_th, ith * 2:(ith + 1) * 2] += score * p_v + score_list[g_th] = total_score[:, 0] + quad_list[g_th] /= (total_score + cfg.epsilon) + return score_list, quad_list -- Gitee From 5a962ef80f3a1f59eb11131492cf4083b580be76 Mon Sep 17 00:00:00 2001 From: WinnieMa Date: Fri, 8 Jul 2022 08:01:52 +0000 Subject: [PATCH 15/17] update --- .../predict.py | 50 +++++ .../preprocess.py | 208 ++++++++++++++++++ 2 files changed, 258 insertions(+) create mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/predict.py create mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/preprocess.py diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/predict.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/predict.py new file mode 100644 index 000000000..4fcc92e45 --- /dev/null +++ b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/predict.py @@ -0,0 +1,50 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import os +from tqdm import tqdm +from network_add_bn import East +from postprocess import predict_txt +import cfg + +if __name__=='__main__': + east = East() + east_detect = east.east_network() + east_detect.load_weights("./model.h5") + image_test_dir = os.path.join(cfg.data_dir, 'rename_images/') + txt_test_dir = os.path.join(cfg.data_dir, 'txt_test') + test_imgname_list = os.listdir(image_test_dir) + test_imgname_list = sorted(test_imgname_list) + print('found %d test images.' % len(test_imgname_list)) + for test_img_name, _ in zip(test_imgname_list, + tqdm(range(len(test_imgname_list)))): + img_path = os.path.join(image_test_dir, test_img_name) + txt_path = os.path.join(txt_test_dir, 'res_'+test_img_name[:-4] + '.txt') + predict_txt(east_detect, img_path, txt_path, cfg.pixel_threshold, True) + diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/preprocess.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/preprocess.py new file mode 100644 index 000000000..b83c589da --- /dev/null +++ b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/preprocess.py @@ -0,0 +1,208 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +from PIL import Image, ImageDraw +import os +import random +from tqdm import tqdm + +import cfg +from label import shrink + + +def batch_reorder_vertexes(xy_list_array): + reorder_xy_list_array = np.zeros_like(xy_list_array) + for xy_list, i in zip(xy_list_array, range(len(xy_list_array))): + reorder_xy_list_array[i] = reorder_vertexes(xy_list) + return reorder_xy_list_array + + +def reorder_vertexes(xy_list): + reorder_xy_list = np.zeros_like(xy_list) + # determine the first point with the smallest x, + # if two has same x, choose that with smallest y, + ordered = np.argsort(xy_list, axis=0) + xmin1_index = ordered[0, 0] + xmin2_index = ordered[1, 0] + if xy_list[xmin1_index, 0] == xy_list[xmin2_index, 0]: + if xy_list[xmin1_index, 1] <= xy_list[xmin2_index, 1]: + reorder_xy_list[0] = xy_list[xmin1_index] + first_v = xmin1_index + else: + reorder_xy_list[0] = xy_list[xmin2_index] + first_v = xmin2_index + else: + reorder_xy_list[0] = xy_list[xmin1_index] + first_v = xmin1_index + # connect the first point to others, the third point on the other side of + # the line with the middle slope + others = list(range(4)) + others.remove(first_v) + k = np.zeros((len(others),)) + for index, i in zip(others, range(len(others))): + k[i] = (xy_list[index, 1] - xy_list[first_v, 1]) \ + / (xy_list[index, 0] - xy_list[first_v, 0] + cfg.epsilon) + k_mid = np.argsort(k)[1] + third_v = others[k_mid] + reorder_xy_list[2] = xy_list[third_v] + # determine the second point which on the bigger side of the middle line + others.remove(third_v) + b_mid = xy_list[first_v, 1] - k[k_mid] * xy_list[first_v, 0] + second_v, fourth_v = 0, 0 + for index, i in zip(others, range(len(others))): + # delta = y - (k * x + b) + delta_y = xy_list[index, 1] - (k[k_mid] * xy_list[index, 0] + b_mid) + if delta_y > 0: + second_v = index + else: + fourth_v = index + reorder_xy_list[1] = xy_list[second_v] + reorder_xy_list[3] = xy_list[fourth_v] + # compare slope of 13 and 24, determine the final order + k13 = k[k_mid] + k24 = (xy_list[second_v, 1] - xy_list[fourth_v, 1]) / ( + xy_list[second_v, 0] - xy_list[fourth_v, 0] + cfg.epsilon) + if k13 < k24: + tmp_x, tmp_y = reorder_xy_list[3, 0], reorder_xy_list[3, 1] + for i in range(2, -1, -1): + reorder_xy_list[i + 1] = reorder_xy_list[i] + reorder_xy_list[0, 0], reorder_xy_list[0, 1] = tmp_x, tmp_y + return reorder_xy_list + + +def resize_image(im, max_img_size=cfg.max_train_img_size): + im_width = np.minimum(im.width, max_img_size) + if im_width == max_img_size < im.width: + im_height = int((im_width / im.width) * im.height) + else: + im_height = im.height + o_height = np.minimum(im_height, max_img_size) + if o_height == max_img_size < im_height: + o_width = int((o_height / im_height) * im_width) + else: + o_width = im_width + d_wight = o_width - (o_width % 32) + d_height = o_height - (o_height % 32) + return d_wight, d_height + + +def preprocess(): + data_dir = cfg.data_dir + origin_image_dir = os.path.join(data_dir, cfg.origin_image_dir_name) + origin_txt_dir = os.path.join(data_dir, cfg.origin_txt_dir_name) + train_image_dir = os.path.join(data_dir, cfg.train_image_dir_name) + train_label_dir = os.path.join(data_dir, cfg.train_label_dir_name) + if not os.path.exists(train_image_dir): + os.mkdir(train_image_dir) + if not os.path.exists(train_label_dir): + os.mkdir(train_label_dir) + draw_gt_quad = cfg.draw_gt_quad + show_gt_image_dir = os.path.join(data_dir, cfg.show_gt_image_dir_name) + if not os.path.exists(show_gt_image_dir): + os.mkdir(show_gt_image_dir) + show_act_image_dir = os.path.join(cfg.data_dir, cfg.show_act_image_dir_name) + if not os.path.exists(show_act_image_dir): + os.mkdir(show_act_image_dir) + + o_img_list = os.listdir(origin_image_dir) + print('found %d origin images.' % len(o_img_list)) + train_val_set = [] + for o_img_fname, _ in zip(o_img_list, tqdm(range(len(o_img_list)))): + with Image.open(os.path.join(origin_image_dir, o_img_fname)) as im: + # d_wight, d_height = resize_image(im) + d_wight, d_height = cfg.max_train_img_size, cfg.max_train_img_size + scale_ratio_w = d_wight / im.width + scale_ratio_h = d_height / im.height + im = im.resize((d_wight, d_height), Image.NEAREST).convert('RGB') + show_gt_im = im.copy() + # draw on the img + draw = ImageDraw.Draw(show_gt_im) + with open(os.path.join(origin_txt_dir, + o_img_fname[:-4] + '.txt'), 'r', encoding='UTF-8') as f: + anno_list = f.readlines() + xy_list_array = np.zeros((len(anno_list), 4, 2)) + for anno, i in zip(anno_list, range(len(anno_list))): + anno_colums = anno.strip().split(',') + anno_array = np.array(anno_colums) + xy_list = np.reshape(anno_array[:8].astype(float), (4, 2)) + xy_list[:, 0] = xy_list[:, 0] * scale_ratio_w + xy_list[:, 1] = xy_list[:, 1] * scale_ratio_h + xy_list = reorder_vertexes(xy_list) + xy_list_array[i] = xy_list + _, shrink_xy_list, _ = shrink(xy_list, cfg.shrink_ratio) + shrink_1, _, long_edge = shrink(xy_list, cfg.shrink_side_ratio) + if draw_gt_quad: + draw.line([tuple(xy_list[0]), tuple(xy_list[1]), + tuple(xy_list[2]), tuple(xy_list[3]), + tuple(xy_list[0]) + ], + width=2, fill='green') + draw.line([tuple(shrink_xy_list[0]), + tuple(shrink_xy_list[1]), + tuple(shrink_xy_list[2]), + tuple(shrink_xy_list[3]), + tuple(shrink_xy_list[0]) + ], + width=2, fill='blue') + vs = [[[0, 0, 3, 3, 0], [1, 1, 2, 2, 1]], + [[0, 0, 1, 1, 0], [2, 2, 3, 3, 2]]] + for q_th in range(2): + draw.line([tuple(xy_list[vs[long_edge][q_th][0]]), + tuple(shrink_1[vs[long_edge][q_th][1]]), + tuple(shrink_1[vs[long_edge][q_th][2]]), + tuple(xy_list[vs[long_edge][q_th][3]]), + tuple(xy_list[vs[long_edge][q_th][4]])], + width=3, fill='yellow') + if cfg.gen_origin_img: + im.save(os.path.join(train_image_dir, o_img_fname)) + np.save(os.path.join( + train_label_dir, + o_img_fname[:-4] + '.npy'), + xy_list_array) + if draw_gt_quad: + show_gt_im.save(os.path.join(show_gt_image_dir, o_img_fname)) + train_val_set.append('{},{},{}\n'.format(o_img_fname, + d_wight, + d_height)) + + train_img_list = os.listdir(train_image_dir) + print('found %d train images.' % len(train_img_list)) + train_label_list = os.listdir(train_label_dir) + print('found %d train labels.' % len(train_label_list)) + + random.shuffle(train_val_set) + val_count = int(cfg.validation_split_ratio * len(train_val_set)) + with open(os.path.join(data_dir, cfg.val_fname), 'w') as f_val: + f_val.writelines(train_val_set[:val_count]) + with open(os.path.join(data_dir, cfg.train_fname), 'w') as f_train: + f_train.writelines(train_val_set[val_count:]) + + +if __name__ == '__main__': + preprocess() -- Gitee From 651216c04a346a5e4f97d35b06d95ea06877f38c Mon Sep 17 00:00:00 2001 From: WinnieMa Date: Fri, 8 Jul 2022 08:02:18 +0000 Subject: [PATCH 16/17] update. --- .../README.md | 105 +++++++++++ .../postprocess.py | 178 ++++++++++++++++++ 2 files changed, 283 insertions(+) create mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/README.md create mode 100644 TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/postprocess.py diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/README.md b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/README.md new file mode 100644 index 000000000..abe6c8faf --- /dev/null +++ b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/README.md @@ -0,0 +1,105 @@ +# ID0130_AdvancedEAST +AdvancedEAST 是一种用于场景图像文本检测的算法,主要基于 EAST:An Efficient and Accurate Scene Text Detector,并进行了重大改进,使长文本预测更加准确。参考项目:https://github.com/huoyijie/AdvancedEAST + +## 训练环境 + +* TensorFlow 1.15.0+ +* Python 3.7.0+ + +## 代码及路径解释 + +``` +AdvancedEAST_ID0130_for_ACL +├── nms.py 预测用到的一个函数 +├── cfg.py 参数配置 +├── cfg_bank.py 参数配置 +├── advanced_east.py 参数配置 +├── image_util.py 参数配置 +├── label.py 参数配置 +├── network_add_bn.py 参数配置 +├── icpr 数据集位置 +│ └── image_10000 图像文件 +│ └── txt_10000 标签文件 +├── demo 样例图片 +│ └── 001.png +├── image_test_bin 图片转为bin存放位置 +├── image_test_output msame推理结果bin文件存放位置 +├── preprocess.py 图片预处理 +├── image2bin.py 推理数据预处理:将image_test中的image文件转换为bin并进行其他图片预处理 +├── h5_to_pb.py h5模型固化为pb +├── atc.sh act工具 pb==》om 转换命令 +├── msame.sh msame工具:om离线推理命令 +├── postprocess.py 后处理 +├── predict.py 精度预测 +``` + + +## 数据集 tianchi ICPR MTWI 2018 + +测试集下载地址:链接: 提取码:1234 + +精度验证链接: https://tianchi.aliyun.com/competition/entrance/231685/rankingList + +## 图片预处理 +```shell +python3.7.5 preprocess.py +``` + +## 将测试集图片转为bin文件 + +```shell +python3.7.5 image2bin.py +``` + +## 模型文件 +包括初始h5文件,固化pb文件,以及推理om文件 +h5模型下载地址:链接: 提取码: +pb模型下载地址:链接: 提取码: + +## pb模型 + +模型固化 +```shell +python3.7.5 h5_to_pb.py +``` +## 生成om模型 + +使用ATC模型转换工具进行模型转换时可参考如下指令 atc.sh: +```shell +atc --model=model.pb --input_shape="input_img:1,736,736,3" --framework=3 --output=model --soc_version=Ascend310 --input_format=NHWC +``` +具体参数使用方法请查看官方文档。 + +## 使用msame工具推理 + +使用msame工具进行推理时可参考如下指令 msame.sh +```shell +./msame --model $MODEL --input $INPUT --output $OUTPUT --outfmt BIN +``` +参考 https://gitee.com/ascend/tools/tree/master/msame, 获取msame推理工具及使用方法。 + +## 执行predict +```shell +python3.7.5 predict.py +``` + +## 精度 +* 论文精度: + +| Score | Precision | Recall | +| :--------: | ---------- | ------ | +| 0.611 | 0.809 | 0.492 | + +* GPU目标精度: + +| Score | Precision | Recall | +| :--------: | ---------- | ------ | +| 0.554 | 0.760 | 0.436 | + +* Ascend推理精度: + +| Score | Precision | Recall | +| :--------: | ---------- | ------ | +| 0.632 | 0.849 | 0.513 | + + diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/postprocess.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/postprocess.py new file mode 100644 index 000000000..5281ef160 --- /dev/null +++ b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/postprocess.py @@ -0,0 +1,178 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse +import os +import numpy as np +from PIL import Image, ImageDraw +from keras.preprocessing import image +from keras.applications.vgg16 import preprocess_input + +import cfg_bank as cfg +from label import point_inside_of_quad +from network_add_bn import East +from preprocess import resize_image +from nms import nms +from clock_wise import* + + +def sigmoid(x): + """`y = 1 / (1 + exp(-x))`""" + return 1 / (1 + np.exp(-x)) + +def cut_text_line(geo,scale_ratio_w, scale_ratio_h, imarry, img_path, s): + geo /= [scale_ratio_w, scale_ratio_h] + p_min = np.amin(geo, axis=0) + p_max = np.amax(geo, axis=0) + min_xy = p_min.astype(int) + max_xy = p_max.astype(int) + 2 + sub_im_arr = im_array[min_xy[1]:max_xy[1], min_xy[0]:max_xy[0], :].copy() + for m in range(min_xy[1], max_xy[1]): + for n in range(min_xy[1], max_xy[1]): + if not point_inside_of_quad(n, m, geo, p_min, p_max): + sub_im_arr[m - min_xy[1], n - min_xy[0], :] = 255 + sub_im = image.array_to_img(sub_im_arr, scale=False) + sub_im.save(img_path + '_subim%d.jpg' % s) + +def predict(east_detect, img_path, pixel_threshold, quiet=False): + img = image.load_img(img_path) + d_weight, d_height = resize_image(img, cfg.max_predict_img_size) + img = img.resize((d_weight, d_height), Image.NEAREST).convert('RGB') + img = image.img_to_array(img) + #img = img/255 + img = preprocess_input(img, mode='tf') + x = np.expand_dims(img, axis=0) + y =east_detect.predict(x) + + y = np.squeeze(y, axis=0) + y[:, :, :3] = sigmoid(y[:, :, :3]) + cond = np.greater_equal(y[:, :, 0], pixel_threshold) + activation_pixels = np.where(cond) + quad_scores, quad_after_nms = nms(y, activation_pixels) + with Image.open(img_path) as im: + im_array = image.img_to_array(im.convert('RGB')) + d_wight, d_height = resize_image(im, cfg.max_predict_img_size) + scale_ratio_w = d_wight / im.width + scale_ratio_h = d_height / im.height + im = im.resize((d_wight, d_height), Image.NEAREST).convert('RGB') + quad_im = im.copy() + draw = ImageDraw.Draw(im) + for i, j in zip(activation_pixels[0], activation_pixels[1]): + px = (j + 0.5) * cfg.pixel_size + py = (i + 0.5) * cfg.pixel_size + line_width, line_color = 1, 'red' + if y[i, j, 1] >= cfg.side_vertex_pixel_threshold: + if y[i, j, 2] < cfg.trunc_threshold: + line_width, line_color = 2, 'yellow' + elif y[i, j, 2] >= 1 - cfg.trunc_threshold: + line_width, line_color = 2, 'green' + draw.line([(px - 0.5 * cfg.pixel_size, py - 0.5 * cfg.pixel_size), + (px + 0.5 * cfg.pixel_size, py - 0.5 * cfg.pixel_size), + (px + 0.5 * cfg.pixel_size, py + 0.5 * cfg.pixel_size), + (px - 0.5 * cfg.pixel_size, py + 0.5 * cfg.pixel_size), + (px - 0.5 * cfg.pixel_size, py - 0.5 * cfg.pixel_size)], + width=line_width, fill=line_color) + im.save(img_path + '_act.jpg') + quad_draw = ImageDraw.Draw(quad_im) + txt_items = [] + for score, geo, s in zip(quad_scores, quad_after_nms, + range(len(quad_scores))): + if np.amin(score) > 0: + quad_draw.line([tuple(geo[0]), + tuple(geo[1]), + tuple(geo[2]), + tuple(geo[3]), + tuple(geo[0])], width=2, fill='red') + if cfg.predict_cut_text_line: + cut_text_line(geo, scale_ratio_w, scale_ratio_h, im_array, + img_path, s) + rescaled_geo = geo / [scale_ratio_w, scale_ratio_h] + rescaled_geo_list = np.reshape(rescaled_geo, (8,)).tolist() + txt_item = ','.join(map(str, rescaled_geo_list)) + txt_items.append(txt_item + '\n') + elif not quiet: + print('quad invalid with vertex num less then 4.') + quad_im.save(img_path + '_predict.jpg') + if cfg.predict_write2txt and len(txt_items) > 0: + with open(img_path[:-4] + '.txt', 'w') as f_txt: + f_txt.writelines(txt_items) + +def predict_txt(east_detect, img_path, txt_path, pixel_threshold, quiet=False): + img = image.load_img(img_path) + d_weight, d_height = cfg.max_predict_img_size, cfg.max_predict_img_size + scale_ratio_w = d_weight / img.width + scale_ratio_h = d_height / img.height + img = img.resize((d_weight, d_height), Image.NEAREST).convert('RGB') + img = image.img_to_array(img) + img = preprocess_input(img, mode='tf') + x = np.expand_dims(img, axis=0) + y =east_detect.predict(x) + y = np.squeeze(y, axis=0) + y[:, :, :3] = sigmoid(y[:, :, :3]) + cond = np.greater_equal(y[:, :, 0], pixel_threshold) + activation_pixels = np.where(cond) + quad_scores, quad_after_nms = nms(y, activation_pixels) + + txt_items = [] + for score, geo in zip(quad_scores, quad_after_nms): + if np.amin(score) > 0: + rescaled_geo = geo / [scale_ratio_w, scale_ratio_h] + rescaled_geo = np.round(rescaled_geo,decimals=0).astype(np.int32) + rescaled_geo = order_points_tuple(rescaled_geo) + rescaled_geo_list = np.reshape(rescaled_geo, (8,)).tolist() + txt_item = ','.join(map(str, rescaled_geo_list)) + txt_items.append(txt_item + '\n') + elif not quiet: + print('quad invalid with vertex num less than 4.') + if cfg.predict_write2txt and len(txt_items) > 0: + with open(txt_path, 'w') as f_txt: + f_txt.writelines(txt_items) + +def parse_args(): + parser = argparse.ArgumentParser() + parser.add_argument('--path', '-p', + default='demo/012.png', + help='image path') + parser.add_argument('--threshold', '-t', + default=cfg.pixel_threshold, + help='pixel activation threshold') + return parser.parse_args() + + +if __name__=='__main__': + args = parse_args() + img_path = args.path + threshold = float(args.threshold) + print(img_path, threshold) + + east = East() + east_detect = east.east_network() + east_detect.load_weights(cfg.saved_model_weights_file_path) + predict(east_detect, img_path, threshold) + east_detect.save("saved_model/AdvancedEast_model.h5") + \ No newline at end of file -- Gitee From 5c069f839be5b7d8bc88aa3dcf92b03c427b8205 Mon Sep 17 00:00:00 2001 From: WinnieMa Date: Fri, 8 Jul 2022 08:03:04 +0000 Subject: [PATCH 17/17] update TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/clock_wise.py. --- .../clock_wise.py | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/clock_wise.py b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/clock_wise.py index ae3709ee9..aa03f94b4 100644 --- a/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/clock_wise.py +++ b/TensorFlow/contrib/cv/AdvancedEast_ID0130_for_TensorFlow/clock_wise.py @@ -1,3 +1,31 @@ +# Copyright 2017 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================================ +# Copyright 2021 Huawei Technologies Co., Ltd +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from scipy.spatial import distance as dist import numpy as np import math -- Gitee