OpenCV: невозможно создать слой «карта / форма» типа «форма» в функции «getLayerInstance» - PullRequest
0 голосов
/ 24 марта 2020

Я пытался реализовать модель тензорного потока в opencv dnn.

модель тензорного потока: https://github.com/yinguobing/cnn-facial-landmark

Сначала я заморозил предварительно обученная модель

предварительно обученная модель: https://github.com/yinguobing/head-pose-estimation/tree/master/assets/pose_model

Во-вторых, я оптимизировал "frozen_graph.pb" до "frozen_inference_graph.pb" инструмент 'using' optimize for inference.py '

В-третьих, я загрузил модель, используя' cv2.dnn.readNetFromTensorflow 'и' net .setInput (image_np) '

image_np = np.array ([img]): 1x128x128x3

, и это ошибка, которую я получил, используя 'net .forward ()':

cv2 .error: OpenCV (4.2.0) /io/opencv/modules/dnn/src/dnn.cpp:562: ошибка: (-2: неопределенная ошибка) Невозможно создать слой "map / Shape" типа " Форма "в функции" getLayerInstance "

Я думаю, что эта ошибка вызвана 'image = tf.map_fn (_preprocess_image, image_bytes_list, dtype = tf.float32, back_prop = False)'

это код: landmark.py

"""
Convolutional Neural Network for facial landmarks detection.
"""
import argparse

import cv2
import numpy as np
import tensorflow as tf

from model import LandmarkModel

# Add arguments parser to accept user specified arguments.
parser = argparse.ArgumentParser()
parser.add_argument('--train_record', default='train.record', type=str,
                    help='Training record file')
parser.add_argument('--val_record', default='validation.record', type=str,
                    help='validation record file')
parser.add_argument('--model_dir', default='train', type=str,
                    help='training model directory')
parser.add_argument('--export_dir', default=None, type=str,
                    help='directory to export the saved model')
parser.add_argument('--train_steps', default=1000, type=int,
                    help='training steps')
parser.add_argument('--num_epochs', default=None, type=int,
                    help='epochs of training dataset')
parser.add_argument('--batch_size', default=16, type=int,
                    help='training batch size')
parser.add_argument('--raw_input', default=False, type=bool,
                    help='Use raw tensor as model input.')


# CAUTION: The image width, height and channels should be consist with your
# training data. Here they are set as 128 to be complied with the tutorial.
# Mismatching of the image size will cause error of mismatching tensor shapes.
IMG_WIDTH = 128
IMG_HEIGHT = 128
IMG_CHANNEL = 3


def cnn_model_fn(features, labels, mode):
    """
    The model function for the network.
    """
    # Construct the network.
    model = LandmarkModel(output_size=68*2)
    logits = model(features)

    # Make prediction for PREDICATION mode.
    predictions = logits
    if mode == tf.estimator.ModeKeys.PREDICT:
        return tf.estimator.EstimatorSpec(
            mode=mode,
            predictions=predictions,
            export_outputs={
                'predict': tf.estimator.export.PredictOutput(predictions)
            })

    # Calculate loss using mean squared error.
    loss = tf.losses.mean_squared_error(labels=labels, predictions=predictions)

    # Create a tensor logging purposes.
    tf.identity(loss, name='loss')
    tf.summary.scalar('loss', loss)

    # Configure the train OP for TRAIN mode.
    if mode == tf.estimator.ModeKeys.TRAIN:
        optimizer = tf.train.AdamOptimizer(learning_rate=0.001)

        train_op = optimizer.minimize(
            loss=loss,
            global_step=tf.train.get_global_step())
    else:
        train_op = None

    # Create a metric.
    rmse_metrics = tf.metrics.root_mean_squared_error(
        labels=labels,
        predictions=predictions)
    metrics = {'eval_mse': rmse_metrics}

    # A tensor for metric logging
    tf.identity(rmse_metrics[1], name='root_mean_squared_error')
    tf.summary.scalar('root_mean_squared_error', rmse_metrics[1])

    # Generate a summary node for the images
    tf.summary.image('images', features, max_outputs=6)

    return tf.estimator.EstimatorSpec(
        mode=mode,
        predictions=predictions,
        loss=loss,
        train_op=train_op,
        eval_metric_ops=metrics
    )


def _parse_function(record):
    """
    Extract data from a `tf.Example` protocol buffer.
    """
    # Defaults are not specified since both keys are required.
    keys_to_features = {
        'image/filename': tf.FixedLenFeature([], tf.string),
        'image/encoded': tf.FixedLenFeature([], tf.string),
        'label/marks': tf.FixedLenFeature([136], tf.float32),
    }
    parsed_features = tf.parse_single_example(record, keys_to_features)

    # Extract features from single example
    image_decoded = tf.image.decode_image(parsed_features['image/encoded'])
    image_reshaped = tf.reshape(
        image_decoded, [IMG_HEIGHT, IMG_WIDTH, IMG_CHANNEL])
    points = tf.cast(parsed_features['label/marks'], tf.float32)

    return image_reshaped, points


def input_fn(record_file, batch_size, num_epochs=None, shuffle=True):
    """
    Input function required for TensorFlow Estimator.
    """
    dataset = tf.data.TFRecordDataset(record_file)

    # Use `Dataset.map()` to build a pair of a feature dictionary and a label
    # tensor for each example.
    dataset = dataset.map(_parse_function)
    if shuffle is True:
        dataset = dataset.shuffle(buffer_size=10000)
    dataset = dataset.batch(batch_size)
    dataset = dataset.repeat(num_epochs)

    # Make dataset iterator.
    iterator = dataset.make_one_shot_iterator()

    # Return the feature and label.
    image, label = iterator.get_next()
    return image, label


def serving_input_receiver_fn():
    """An input function for TensorFlow Serving."""

    def _preprocess_image(image_bytes):
        """Preprocess a single raw image."""
        image = tf.image.decode_jpeg(image_bytes, channels=IMG_CHANNEL)
        image.set_shape((None, None, IMG_CHANNEL))
        image = tf.image.resize_images(image, [IMG_HEIGHT, IMG_WIDTH],
                                       method=tf.image.ResizeMethod.BILINEAR,
                                       align_corners=False)
        return image
    image_bytes_list = tf.compat.v1.placeholder(
        shape=[None], dtype=tf.string,
        name='encoded_image_string_tensor')
    image = tf.map_fn(_preprocess_image, image_bytes_list,
                      dtype=tf.float32, back_prop=False)

    return tf.estimator.export.TensorServingInputReceiver(
        features=image,
        receiver_tensors={'image_bytes': image_bytes_list})


def tensor_input_receiver_fn():
    """An input function accept raw tensors."""
    def _preprocess_image(image_tensor):
        """Preprocess a single raw image tensor."""
        image = tf.image.resize_images(image_tensor, [IMG_HEIGHT, IMG_WIDTH],
                                       method=tf.image.ResizeMethod.BILINEAR,
                                       align_corners=False)
        return image

    image_tensor = tf.compat.v1.placeholder(
        shape=[None, None, None, 3], dtype=tf.uint8,
        name='image_tensor')
    image = tf.map_fn(_preprocess_image, image_tensor,
                      dtype=tf.float32, back_prop=False)

    return tf.estimator.export.TensorServingInputReceiver(
        features=image,
        receiver_tensors={'image': image_tensor})


def main(unused_argv):
    """Train, eval and export the model."""
    # Parse the arguments.
    args = parser.parse_args(unused_argv[1:])

    # Create the Estimator
    estimator = tf.estimator.Estimator(
        model_fn=cnn_model_fn, model_dir=args.model_dir)

    # Train for N steps.
    tf.logging.info('Starting to train.')
    estimator.train(
        input_fn=lambda: input_fn(record_file=args.train_record,
                                  batch_size=args.batch_size,
                                  num_epochs=args.num_epochs,
                                  shuffle=True),
        steps=args.train_steps)

    # Do evaluation after training.
    tf.logging.info('Starting to evaluate.')
    evaluation = estimator.evaluate(
        input_fn=lambda: input_fn(record_file=args.val_record,
                                  batch_size=1,
                                  num_epochs=1,
                                  shuffle=False))
    print(evaluation)

    # Export trained model as SavedModel.
    receiver_fn = tensor_input_receiver_fn if args.raw_input else serving_input_receiver_fn
    if args.export_dir is not None:
        estimator.export_savedmodel(args.export_dir, receiver_fn)


if __name__ == '__main__':
    tf.logging.set_verbosity(tf.logging.INFO)
    tf.app.run(main)

мес del.py

import tensorflow as tf


class LandmarkModel(object):
    def __init__(self, output_size):
        self.output_size = output_size

    def __call__(self, input_tensor):
        # |== Layer 0: input layer ==|
        # Input feature x should be of shape (batch_size, image_width, image_height,
        # color_channels). As we will directly using the decoded image tensor of
        # data type int8, a convertion should be performed.
        inputs = tf.cast(input_tensor, tf.float32)

        # |== Layer 1 ==|

        with tf.variable_scope('layer1'):
            # Convolutional layer.
            # Computes 32 features using a 3x3 filter with ReLU activation.
            conv1 = tf.layers.conv2d(
                inputs=inputs,
                filters=32,
                kernel_size=[3, 3],
                strides=(1, 1),
                padding='valid',
                activation=tf.nn.relu)

            # Pooling layer.
            # First max pooling layer with a 2x2 filter and stride of 2.
            pool1 = tf.layers.max_pooling2d(
                inputs=conv1,
                pool_size=[2, 2],
                strides=(2, 2),
                padding='valid')

        # |== Layer 2 ==|

        with tf.variable_scope('layer2'):
            # Convolutional layer
            # Computes 64 features using a 3x3 filter with ReLU activation.
            conv2 = tf.layers.conv2d(
                inputs=pool1,
                filters=64,
                kernel_size=[3, 3],
                strides=(1, 1),
                padding='valid',
                activation=tf.nn.relu)

            # Convolutional layer
            # Computes 64 features using a 3x3 filter with ReLU activation.
            conv3 = tf.layers.conv2d(
                inputs=conv2,
                filters=64,
                kernel_size=[3, 3],
                strides=(1, 1),
                padding='valid',
                activation=tf.nn.relu)

            # Pooling layer
            # Second max pooling layer with a 2x2 filter and stride of 2.
            pool2 = tf.layers.max_pooling2d(
                inputs=conv3,
                pool_size=[2, 2],
                strides=(2, 2),
                padding='valid')

        # |== Layer 3 ==|

        with tf.variable_scope('layer3'):
            # Convolutional layer
            # Computes 64 features using a 3x3 filter with ReLU activation.
            conv4 = tf.layers.conv2d(
                inputs=pool2,
                filters=64,
                kernel_size=[3, 3],
                strides=(1, 1),
                padding='valid',
                activation=tf.nn.relu)

            # Convolutional layer
            # Computes 64 features using a 3x3 filter with ReLU activation.
            conv5 = tf.layers.conv2d(
                inputs=conv4,
                filters=64,
                kernel_size=[3, 3],
                strides=(1, 1),
                padding='valid',
                activation=tf.nn.relu)

            # Pooling layer
            # Third max pooling layer with a 2x2 filter and stride of 2.
            pool3 = tf.layers.max_pooling2d(
                inputs=conv5,
                pool_size=[2, 2],
                strides=(2, 2),
                padding='valid')

        # |== Layer 4 ==|

        with tf.variable_scope('layer4'):
            # Convolutional layer
            # Computes 128 features using a 3x3 filter with ReLU activation.
            conv6 = tf.layers.conv2d(
                inputs=pool3,
                filters=128,
                kernel_size=[3, 3],
                strides=(1, 1),
                padding='valid',
                activation=tf.nn.relu)

            # Convolutional layer
            # Computes 128 features using a 3x3 filter with ReLU activation.
            conv7 = tf.layers.conv2d(
                inputs=conv6,
                filters=128,
                kernel_size=[3, 3],
                strides=(1, 1),
                padding='valid',
                activation=tf.nn.relu)

            # Pooling layer
            # Fourth max pooling layer with a 2x2 filter and stride of 2.
            pool4 = tf.layers.max_pooling2d(
                inputs=conv7,
                pool_size=[2, 2],
                strides=(1, 1),
                padding='valid')

        # |== Layer 5 ==|

        with tf.variable_scope('layer5'):
            # Convolutional layer
            conv8 = tf.layers.conv2d(
                inputs=pool4,
                filters=256,
                kernel_size=[3, 3],
                strides=(1, 1),
                padding='valid',
                activation=tf.nn.relu)

        # |== Layer 6 ==|

        with tf.variable_scope('layer6'):
            # Flatten tensor into a batch of vectors
            flatten = tf.layers.flatten(inputs=conv8)

            # Dense layer 1, a fully connected layer.
            dense1 = tf.layers.dense(
                inputs=flatten,
                units=1024,
                activation=tf.nn.relu,
                use_bias=True)

            # Dense layer 2, also known as the output layer.
            logits = tf.layers.dense(
                inputs=dense1,
                units=self.output_size,
                activation=None,
                use_bias=True,
                name="logits")
            logits = tf.identity(logits, 'final_dense')

        return logits

тензорная доска: я не могу загрузить изображение

https://github.com/JunTae90/tensorboard

Я не сделал пока не нашел решения. Мой вопрос: что еще мне нужно сделать, чтобы загрузить модель в opencv.

...