Я пытался реализовать модель тензорного потока в 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.