From 52523a4f9b177a3e0ed1bc3d69094f60ad5d398d Mon Sep 17 00:00:00 2001 From: Pascal Iwohn Date: Fri, 15 Oct 2021 10:54:06 +0200 Subject: [PATCH 1/3] Added Resizing_helper --- keras2ncnn/keras_converter.py | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/keras2ncnn/keras_converter.py b/keras2ncnn/keras_converter.py index 812c4fe..190bb15 100644 --- a/keras2ncnn/keras_converter.py +++ b/keras2ncnn/keras_converter.py @@ -504,6 +504,46 @@ def BatchNormalization_helper( bn_params['bn_moving_variance'], bn_params['bn_beta']]}) + def Resizing_helper( + self, + layer, + keras_graph_helper, + ncnn_graph_helper, + ncnn_helper): + if layer.crop_to_aspect_ratio: + print(f'[ERROR] Crop to aspect ratio is currently not supported for Resizing layers.') + frameinfo = inspect.getframeinfo(inspect.currentframe()) + print('Failed to convert at %s:%d %s()' % + (frameinfo.filename, frameinfo.lineno, frameinfo.function)) + sys.exit(-1) + # Set the interpolation type and make sure it is supported. + if layer.interpolation.lower() == "bilinear": + resize_type = 2 + elif layer.interpolation.lower() == "nearest": + resize_type = 1 + else: + print(f'[ERROR] Activation type {layer.interpolation} is is not supported yet. ' + f'Currently, only bilinear and nearest are supported as Resizing layer interpolation types.') + frameinfo = inspect.getframeinfo(inspect.currentframe()) + print('Failed to convert at %s:%d %s()' % + (frameinfo.filename, frameinfo.lineno, frameinfo.function)) + sys.exit(-1) + height_scale = layer.target_height / layer.input_shape[1] + width_scale = layer.target_width / layer.input_shape[2] + output_height = layer.target_height + output_width = layer.target_width + ncnn_graph_attr = ncnn_helper.dump_args( + 'Interp', resize_type=resize_type, height_scale=height_scale, width_scale=width_scale, + output_height=output_height, output_width=output_width + ) + ncnn_graph_helper.node( + layer['layer']['name'], + keras_graph_helper.get_node_inbounds( + layer['layer']['name'])) + ncnn_graph_helper.set_node_attr( + layer['layer']['name'], { + 'type': 'Interp', 'param': ncnn_graph_attr, 'binary': []}) + def Add_helper( self, layer, From 3fdc8a522a044a62fbba1e9d5716181ac3612d8b Mon Sep 17 00:00:00 2001 From: Pascal Iwohn Date: Fri, 15 Oct 2021 15:47:45 +0200 Subject: [PATCH 2/3] Finalised support for Resizing Op --- keras2ncnn/h5df_parser.py | 46 +++++++++++++++++++++++++++++------ keras2ncnn/keras_converter.py | 23 ++++++++++++------ 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/keras2ncnn/h5df_parser.py b/keras2ncnn/h5df_parser.py index 96a2f8d..dee830f 100644 --- a/keras2ncnn/h5df_parser.py +++ b/keras2ncnn/h5df_parser.py @@ -39,6 +39,24 @@ def __init__(self, h5_file): self.model_config = json.loads(self.__decode(model_config_raw)) self.keras_version = self.get_keras_version() + try: + import tensorflow.keras as keras + except ModuleNotFoundError: + try: + import keras + except ModuleNotFoundError: + pass + + try: + model = keras.models.load_model(h5_file) + self.layer_input_shapes = {layer.name: layer.input_shape for layer in model.layers} + except NameError: + self.layer_input_shapes = None + except Exception as e: + print(f"Exception {e} occurred when attempting to load model in keras. Will attempt conversion without " + f"additional information.") + self.layer_input_shapes = None + if self.keras_version != '1': weight_layers = self.f['model_weights'] else: @@ -124,10 +142,16 @@ def parse_graph(self, graph_helper): inbound_nodes = graph_helper.get_graph_tail() graph_helper.node(layer_name, inbound_nodes) - graph_helper.set_node_attr( - layer_name, { - 'layer': layers, 'weight': self.find_weights_root( - layer_name)}) + if self.layer_input_shapes is None: + graph_helper.set_node_attr( + layer_name, { + 'layer': layers, 'weight': self.find_weights_root( + layer_name)}) + else: + graph_helper.set_node_attr( + layer_name, { + 'layer': layers, 'weight': self.find_weights_root( + layer_name), 'input_shape': self.layer_input_shapes[layer_name]}) def parse_model_graph(self, model_layers, graph_helper): for layer in model_layers: @@ -136,7 +160,13 @@ def parse_model_graph(self, model_layers, graph_helper): inbound_nodes = graph_helper.get_graph_tail() graph_helper.node(layer['name'], inbound_nodes) - graph_helper.set_node_attr( - layer['name'], { - 'layer': layer, 'weight': self.find_weights_root( - layer['name'])}) + if self.layer_input_shapes is None: + graph_helper.set_node_attr( + layer['name'], { + 'layer': layer, 'weight': self.find_weights_root( + layer['name'])}) + else: + graph_helper.set_node_attr( + layer['name'], { + 'layer': layer, 'weight': self.find_weights_root( + layer['name']), 'input_shape': self.layer_input_shapes[layer['name']]}) diff --git a/keras2ncnn/keras_converter.py b/keras2ncnn/keras_converter.py index 190bb15..e27d262 100644 --- a/keras2ncnn/keras_converter.py +++ b/keras2ncnn/keras_converter.py @@ -510,16 +510,17 @@ def Resizing_helper( keras_graph_helper, ncnn_graph_helper, ncnn_helper): - if layer.crop_to_aspect_ratio: + if "crop_to_aspect_ratio" in layer["layer"]["config"] and \ + layer["layer"]["config"]["crop_to_aspect_ratio"]: print(f'[ERROR] Crop to aspect ratio is currently not supported for Resizing layers.') frameinfo = inspect.getframeinfo(inspect.currentframe()) print('Failed to convert at %s:%d %s()' % (frameinfo.filename, frameinfo.lineno, frameinfo.function)) sys.exit(-1) # Set the interpolation type and make sure it is supported. - if layer.interpolation.lower() == "bilinear": + if layer["layer"]["config"]["interpolation"].lower() == "bilinear": resize_type = 2 - elif layer.interpolation.lower() == "nearest": + elif layer["layer"]["config"]["interpolation"].lower() == "nearest": resize_type = 1 else: print(f'[ERROR] Activation type {layer.interpolation} is is not supported yet. ' @@ -528,10 +529,18 @@ def Resizing_helper( print('Failed to convert at %s:%d %s()' % (frameinfo.filename, frameinfo.lineno, frameinfo.function)) sys.exit(-1) - height_scale = layer.target_height / layer.input_shape[1] - width_scale = layer.target_width / layer.input_shape[2] - output_height = layer.target_height - output_width = layer.target_width + if "input_shape" in layer: + height_scale = layer["layer"]["config"]["height"] / layer["input_shape"][1] + width_scale = layer["layer"]["config"]["width"] / layer["input_shape"][2] + output_height = layer["layer"]["config"]["height"] + output_width = layer["layer"]["config"]["width"] + else: + print(f'[ERROR] Could not find input shape for Resizing layer. Please make sure you have either tensorflow ' + f'or keras installed.') + frameinfo = inspect.getframeinfo(inspect.currentframe()) + print('Failed to convert at %s:%d %s()' % + (frameinfo.filename, frameinfo.lineno, frameinfo.function)) + sys.exit(-1) ncnn_graph_attr = ncnn_helper.dump_args( 'Interp', resize_type=resize_type, height_scale=height_scale, width_scale=width_scale, output_height=output_height, output_width=output_width From 5890388e98a26b36d8f4170cc6b0b818ded9ebd5 Mon Sep 17 00:00:00 2001 From: Pascal Iwohn Date: Fri, 15 Oct 2021 15:54:43 +0200 Subject: [PATCH 3/3] Added Resizing to supported ops --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index db36482..54f0b13 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ python3 -m keras2ncnn -i SOME_H5DF_FILE.h5 -o DIR_TO_SAVE_NCNN_PARAM --plot_grap - Maximum - TensorFlowOpLayer (Mul with constant) - Permute (Need more testing) +- Resizing (Requires tensorflow/keras for conversion) ## Ops that will be dropped by converter - Dropout