Tensorflow use trained model for detection

时间:2019-04-23 15:20:09

标签: python-3.x tensorflow

I'm working on a waste/garbage detector for a personal project. I rely on Tensorflow (in Python 3) to train my own dataset.

I have a script that creates and trains a model from scratch. Then, I freeze the checkpoints to get a PB file for detection.

The code I have for the detection (found here) requires two files to work: the previous PB file and a labelmap.txt.

# Path to frozen detection graph. This is the actual model that is used for the object detection.
PATH_TO_CKPT = 'frozen_inference_graph.pb'

# List of the strings that is used to add correct label for each box.
PATH_TO_LABELS = 'label_map.pbtxt'

I know how a labelmap.txt looks like and it is quite simple to write it myself actually, but I don't know how to generate it because it links each class to an ID and the ID is unknown to me.

I tried to search on the Internet, when people mention the labelmap.txt, it involves Tfrecords. However, I don't use Tf records for my project, I extract each region of interest and save them in subfolders, one subfolder for a class (can, bottle...).

As I am new to Tensorflow, I may have misunderstood something in the training process. Do you have any lead so I can see if my model is accurate by testing it ? I can provide some codes if you need it.

Thanking you in advance,

2 个答案:

答案 0 :(得分:0)

labelmap.pbtxt文件将网络内部使用的ID映射到标签名称。您不能在训练后简单地生成一个。您需要确保在培训期间使用相同的ID标签映射,否则可能会得到错误的结果。

如果您使用tensorflow object_detection模型的训练说明,那么您将在某个时候生成此labelmap文件,并且可以重复使用它。

查看您用来训练网络的步骤或在此处发布。

答案 1 :(得分:0)

在训练之前,我收集并标记了数千张图像,提取了每个标记的区域,调整了每个图像的大小,然后根据它们的类别,将它们分成了不同的文件夹。

培训步骤中涉及多个文件。我最初从此repository中检索了代码,并增加了恢复培训的可能性。

trainer.py

import os
import tensorflow as tf
import model_architecture

from utils import utils
from build_model import model_tools

# Images directory.
data_path = os.path.join('dataset' + os.sep)# contains subfolders, one per item
all_classes = os.listdir(data_path)
number_of_classes = len(all_classes)

# Images dimensions.
height = 64
width = 64

# Checkpoints directory.
output_dir = os.path.join(os.pardir + os.sep, 'checkpoints' + os.sep)
model_pattern = 'model.ckpt'
model_base_path = os.path.join(output_dir, model_pattern)
meta_file_path = model_base_path + '.meta'

# Training params.
color_channels = 3
start = 0
epochs = 5
batch_size = 10
batch_counter = 0

# Create Placeholders for images and labels.
images_ph = tf.placeholder(tf.float32, shape=[None, height, width, color_channels])
labels_ph = tf.placeholder(tf.float32, shape=[None, number_of_classes])


def trainer(network, number_of_images):
    cross_entropy = tf.nn.softmax_cross_entropy_with_logits_v2(logits=network, labels=labels_ph)
    cost = tf.reduce_mean(cross_entropy)
    optimizer = tf.train.AdamOptimizer().minimize(cost)
    tf.summary.scalar('cost', cost)
    tf.add_to_collection('optimizer', optimizer)

    global_step = tf.Variable(0, name='global_step', trainable=False)
    saver = tf.train.Saver()

    # Launch the graph in a session
    with tf.Session() as sess:
        # Initialize all variables.
        tf.global_variables_initializer().run()

        # Read checkpoints directory.
        ckpt = tf.train.get_checkpoint_state(output_dir)

        if ckpt and ckpt.model_checkpoint_path:
            saver.restore(sess, ckpt.model_checkpoint_path)
            print('Reloading existing model.')
        else:
            init = tf.global_variables_initializer()
            sess.run(init)
            print('Creating a new model.')

        # Get last epoch index.
        start = global_step.eval()

        writer = tf.summary.FileWriter(output_dir, graph=tf.get_default_graph())
        merged = tf.summary.merge_all()
        saver = tf.train.Saver(write_version=tf.train.SaverDef.V2, max_to_keep=5)
        counter = 0

        # Training.
        for epoch in range(start, epochs):
            tools = utils()
            for batch in range(int(number_of_images / batch_size)):
                counter += 1
                images, labels = tools.batch_dispatch()
                if images is None:
                    break
                loss, summary = sess.run([cost, merged], feed_dict={images_ph: images, labels_ph: labels})
                sess.run(optimizer, feed_dict={images_ph: images, labels_ph: labels})
                print('Epoch number {epoch} batch {batch} complete - loss {loss}'.format(
                    epoch=epoch, batch=batch, loss=loss))
                writer.add_summary(summary, counter)
            global_step.assign(epoch).eval()

            # Save progression.
            saver.save(sess, model_base_path, global_step=epoch)


# Main program.
if __name__ == '__main__':
    tools = utils()
    model = model_tools()
    network = model_architecture.generate_model(images_ph, number_of_classes)
    number_of_images = sum([len(files) for r, d, files in os.walk('dataset')])
    trainer(network, number_of_images)

model_tools.py

class model_tools:

    def add_weights(self, shape):
        return tf.Variable(tf.truncated_normal(shape=shape, stddev=0.05))

    def add_biases(self, shape):
        return tf.Variable(tf.constant(0.05, shape=shape))

    def conv_layer(self, layer, kernel, input_shape, output_shape, stride_size):
        weights = self.add_weights([kernel, kernel, input_shape, output_shape])
        biases = self.add_biases([output_shape])
        stride = [1, stride_size, stride_size, 1]
        layer = tf.nn.conv2d(layer, weights, strides=stride, padding='SAME') + biases
        return layer

    def pooling_layer(self, layer, kernel_size, stride_size):
        kernel = [1, kernel_size, kernel_size, 1]
        stride = [1, stride_size, stride_size, 1]
        return tf.nn.max_pool(layer, ksize=kernel, strides=stride, padding='SAME')

    def flattening_layer(self, layer):
        input_size = layer.get_shape().as_list()
        new_size = input_size[-1] * input_size[-2] * input_size[-3]
        return tf.reshape(layer, [-1, new_size]), new_size

    def fully_connected_layer(self, layer, input_shape, output_shape):
        weights = self.add_weights([input_shape, output_shape])
        biases = self.add_biases([output_shape])
        layer = tf.matmul(layer, weights) + biases
        return layer

    def activation_layer(self, layer):
        return tf.nn.relu(layer)

utils.py

import cv2
import random    

class utils:
    image_count = []
    count_buffer = []
    class_buffer = all_classes[:]

    def __init__(self):
        self.image_count = []
        self.count_buffer = []
        for i in os.walk(data_path):
            if len(i[2]):
                self.image_count.append(len(i[2]))
        self.count_buffer = self.image_count[:]

    def batch_dispatch(self, batch_size=batch_size):
        global batch_counter
        if sum(self.count_buffer):

            class_name = random.choice(self.class_buffer)
            choice_index = all_classes.index(class_name)
            choice_count = self.count_buffer[choice_index]
            if choice_count == 0:
                class_name = all_classes[self.count_buffer.index(max(self.count_buffer))]
                choice_index = all_classes.index(class_name)
                choice_count = self.count_buffer[choice_index]

            slicer = batch_size if batch_size < choice_count else choice_count
            img_ind = self.image_count[choice_index] - choice_count
            indices = [img_ind, img_ind + slicer]
            images = self.generate_images(class_name, indices)
            labels = self.generate_labels(class_name, slicer)

            self.count_buffer[choice_index] = self.count_buffer[choice_index] - slicer
        else:
            images, labels = (None,) * 2
        return images, labels

    def generate_labels(self, class_name, number_of_samples):
        one_hot_labels = [0] * number_of_classes
        one_hot_labels[all_classes.index(class_name)] = 1
        one_hot_labels = [one_hot_labels] * number_of_samples
        return one_hot_labels

    def generate_images(self, class_name, indices):
        batch_images = []
        choice_folder = os.path.join(data_path, class_name)
        selected_images = os.listdir(choice_folder)[indices[0]:indices[1]]
        for image in selected_images:
            img = cv2.imread(os.path.join(choice_folder, image))
            batch_images.append(img)
        return batch_images

model_architecture.py包含3层图像分类器的结构。

当我运行trainer.py时,我得到一个充满了元文件和索引文件的checkpoints文件夹。看来是正确的。

关于导出模型,我很尴尬,因为我不知道为管道配置路径提供什么作为参数。

python3 export_inference_graph.py \     --input_type image_tensor \     --trained_checkpoint_prefix“ /home/user/model/model.ckpt-4” \     --pipeline_config_path ???? \     --output_directory / home / user / exports /

要获取PB文件,我使用了以下方法:

checkpoint_location = 'checkpoints/model.ckpt-0' 
export_dir = 'frozen/'
loaded_graph = tf.Graph()
with tf.Session(graph=loaded_graph) as sess:
    loader = tf.train.import_meta_graph(checkpoint_location+ '.meta')
    loader.restore(sess, checkpoint_location)

    builder = tf.saved_model.builder.SavedModelBuilder(export_dir)
    builder.add_meta_graph_and_variables(sess,
                                         [tf.saved_model.tag_constants.TRAINING],
                                         strip_default_attrs=True)
builder.add_meta_graph([tf.saved_model.tag_constants.SERVING], strip_default_attrs=True)
builder.save()

它将创建一个save_model.pb文件,但不会创建labelmap.pbtxt。

我应该完全改变训练模型的方式吗?