利用opencv调用tensorflow的pb模型对jpg图片进行分类

利用的是opencv中的dnn模块进行调用的,之所以标题是对jpg的图片进行分类,主要的原因是我对bmp格式的图片分类还没有成功,成功之后再更新,

使用比较常用的花卉分类图片进行分类,因为只是为了实验,并没有对图片分类精度进行追求,代码中有许多问题,比如有很多没用的,也没有删掉,也只是对花进行了二分类

对这两种花进行二分类,daisy标签为0 dandelion为1

首先进行分类,分类使用python3.5+tensorflow-gpu1.4.0+ubuntu16.04

整个过程有3个py文件,input_data.py是对图片的读取处理

train_model.py是进行训练  t_model.py是在python中测试图片

input_data.py文件

import input_data
#from tensorflow.python.framework import graph_util
from skimage import io, transform
import glob
import os
import tensorflow as tf
import numpy as np
import time

NG_path='/home/dyf/PycharmProjects/classifer_flower/flower_photos/daisy/'
OK_path='/home/dyf/PycharmProjects/classifer_flower/flower_photos/dandelion/'

#读取图片
def _dense_to_one_hot(labels_dense, num_classes):
  """Convert class labels from scalars to one-hot vectors."""
  num_labels = labels_dense.shape[0]
  index_offset = np.arange(num_labels) * num_classes
  labels_one_hot = np.zeros((num_labels, num_classes))
  labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1
  return labels_one_hot

#读取图片
def read_img():
    imgs = []
    label = []
    #for k in range(1,10):
    #path1= os.path.join(os.path.abspath(NG_path), '1'+format(str(k)))
    #path2=os.path.join(os.path.abspath(labels_path), 'NG'+format(str(k)+'.txt'))
    piclist = os.listdir(NG_path)
    for pic in piclist:
        if pic.endswith(".jpg"):
            old_path = os.path.join(os.path.abspath(NG_path), pic)
            img=io.imread(old_path)
            img=transform.resize(img,(500,500))
            #print(img)
            # img=img.reshape(100,100,3)
            imgs.append(img)
            label.append(0);

    piclist = os.listdir(OK_path)
    for pic in piclist:
        if pic.endswith(".jpg"):
            old_path = os.path.join(os.path.abspath(OK_path), pic)
            img = io.imread(old_path)
            img = transform.resize(img, (500, 500))
            # img=img.reshape(100,100,3)
            imgs.append(img)
            label.append(1);

    # for i in range(2180):
    #     new_path = os.path.join(os.path.abspath(OK_path), '1(' + format(str(i + 1)) + ').bmp')
    #
    #     img = io.imread(new_path)
    #     img = transform.resize(img, (100, 100))
    #     #img=img.reshape(100, 100, 3)
    #     imgs.append(img)
    #     label.append(1);
    #         #labels.append(idx)

    return np.asarray(imgs, np.float32), np.asarray(label, np.int32)


def train_test_split(ratio):
    data, label = read_img()
    #print(data.shape)
    print(data.shape)
    # data = np.array(data).reshape(-1, 200, 200,3);
    # print(data.shape)
    #打乱顺序
    num_example=data.shape[0]
    arr=np.arange(num_example)
    np.random.shuffle(arr)
    data=data[arr]
    label=label[arr]
    label=_dense_to_one_hot(label,2)

    #将所有数据分为训练集和验证集
    ratio=0.8
    s=np.int(num_example*ratio)
    x_train=data[:s]
    y_train=label[:s]
    x_test=data[s:]
    y_test=label[s:]
    return x_train,x_test,y_train,y_test

#定义一个函数,按批次取数据
def minibatches(inputs=None, targets=None, batch_size=None, shuffle=False):
    assert len(inputs) == len(targets)
    if shuffle:
        indices = np.arange(len(inputs))
        np.random.shuffle(indices)
    for start_idx in range(0, len(inputs) - batch_size + 1, batch_size):
        if shuffle:
            excerpt = indices[start_idx:start_idx + batch_size]
        else:
            excerpt = slice(start_idx, start_idx + batch_size)
        yield inputs[excerpt], targets[excerpt]

def _test():
    x_train,x_test,y_train,y_test = train_test_split(0.8)

    print("dataset.train.images.shape:", x_train.shape)
    print("dataset.train.labels.shape:", y_train.shape)
    print("dataset.test.images.shape:", x_test.shape)
    print("dataset.test.labels.shape:",y_test.shape)

train_model.py

import input_data
from tensorflow.python.framework import graph_util
import tensorflow as tf


def build_network(height, width):
    """
    Function:构建网络模型。

    Parameters
    ----------
        height: Mnist图像的宽。
        width: Mnist图像的宽。

    """

    x = tf.placeholder(tf.float32, [None, 500, 500,3], name='input')

    y_placeholder = tf.placeholder(tf.float32, shape=[None,2], name='labels_placeholder')

    #keep_prob_placeholder = tf.placeholder(tf.float32, name='keep_prob_placeholder')

    def weight_variable(shape):
        initial = tf.truncated_normal(shape, stddev=0.1)
        return tf.Variable(initial)

    def bias_variable(shape):
        initial = tf.constant(0.1, shape=shape)
        return tf.Variable(initial)

    def conv2d(x, W):
        return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

    def max_pool_2x2(x):
        return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID')

    #x_image = tf.reshape(x, [-1, height, width, 3])

    # First Convolutional Layer
    W_conv1 = weight_variable([5, 5, 3, 16])
    b_conv1 = bias_variable([16])

    h_conv1 = tf.nn.relu(conv2d(x, W_conv1) + b_conv1)
    h_pool1 = max_pool_2x2(h_conv1)

    # Second Convolutional Layer
    W_conv2 = weight_variable([5, 5, 16, 32])
    b_conv2 = bias_variable([32])

    h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
    h_pool2 = max_pool_2x2(h_conv2)
    # #
    W_conv3 = weight_variable([5, 5, 32, 64])
    b_conv3 = bias_variable([64])

    h_conv3 = tf.nn.relu(conv2d(h_pool2, W_conv3) + b_conv3)
    h_pool3 = max_pool_2x2(h_conv3)

    W_conv4 = weight_variable([5, 5, 64, 128])
    b_conv4 = bias_variable([128])

    h_conv4 = tf.nn.relu(conv2d(h_pool3, W_conv4) + b_conv4)
    h_pool4 = max_pool_2x2(h_conv4)

    W_conv5 = weight_variable([5, 5, 128, 256])
    b_conv5 = bias_variable([256])

    h_conv5 = tf.nn.relu(conv2d(h_pool4, W_conv5) + b_conv5)
    h_pool5 = max_pool_2x2(h_conv5)

    W_conv6 = weight_variable([5, 5, 256, 512])
    b_conv6 = bias_variable([512])

    h_conv6 = tf.nn.relu(conv2d(h_pool5, W_conv6) + b_conv6)
    h_pool6 = max_pool_2x2(h_conv6)
    # #
    # W_conv3 = weight_variable([5, 5, 64, 128])
    # b_conv3 = bias_variable([128])
    #
    # h_conv3 = tf.nn.relu(conv2d(h_pool2, W_conv3) + b_conv3)
    # h_pool3 = max_pool_2x2(h_conv3)
    #
    # W_conv4 = weight_variable([5, 5,128, 256])
    # b_conv4 = bias_variable([256])
    #
    # h_conv4 = tf.nn.relu(conv2d(h_pool3, W_conv4) + b_conv4)
    # h_pool4 = max_pool_2x2(h_conv4)

    # Densely Connected Layer
    W_fc1 = weight_variable([7 * 7 * 512,2])
    b_fc1 = bias_variable([2])

    h_pool4_flat = tf.reshape(h_pool6, [-1, 7* 7 * 512])
    # h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
    #
    # # Dropout
    # h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob_placeholder)
    #
    # # Readout Layer
    # W_fc2 = weight_variable([64, 2])
    # b_fc2 = bias_variable([2])

    logits = tf.matmul(h_pool4_flat, W_fc1) + b_fc1

    sofmax_out = tf.nn.softmax(logits, name="out_softmax")

    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=y_placeholder))

    optimize = tf.train.AdamOptimizer(learning_rate=1e-4).minimize(cost)

    prediction_labels = tf.argmax(sofmax_out, axis=1)
    real_labels = tf.argmax(y_placeholder, axis=1)

    correct_prediction = tf.equal(prediction_labels, real_labels)
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    # 一个Batch中预测正确的次数
    correct_times_in_batch = tf.reduce_sum(tf.cast(correct_prediction, tf.int32))

    return dict(
        #keep_prob_placeholder=keep_prob_placeholder,
        x_placeholder=x,
        y_placeholder=y_placeholder,
        optimize=optimize,
        logits=logits,
        prediction_labels=prediction_labels,
        real_labels=real_labels,
        correct_prediction=correct_prediction,
        correct_times_in_batch=correct_times_in_batch,
        cost=cost,
        accuracy=accuracy,
    )


def train_network(graph,
                  batch_size,
                  num_epochs,
                  pb_file_path, ):
    """
    Function:训练网络。

    Parameters
    ----------
        graph: 一个dict,build_network函数的返回值。
        dataset: 数据集
        batch_size:
        num_epochs: 训练轮数。
        pb_file_path:要生成的pb文件的存放路径。
    """
    x_train,x_test,y_train,y_test=input_data.train_test_split(0.8)
    config = tf.ConfigProto(allow_soft_placement=True)
    tf.GPUOptions(per_process_gpu_memory_fraction=0.9)
    config.gpu_options.allow_growth = True
    with tf.Session(config=config) as sess:

        sess.run(tf.global_variables_initializer())

        print("batch size:", batch_size)

        # 用于控制每epoch_delta轮在train set和test set上计算一下accuracy和cost
        epoch_delta = 2
        for epoch_index in range(num_epochs):

            #################################
            #    获取TRAIN set,开始训练网络
            #################################
            for (batch_xs, batch_ys) in input_data.minibatches(x_train,y_train,batch_size,shuffle=True):
                sess.run([graph['optimize']], feed_dict={
                    graph['x_placeholder']: batch_xs,
                    graph['y_placeholder']: batch_ys,
                    #graph['keep_prob_placeholder']: 0.5,
                })

            # 每epoch_delta轮在train set和test set上计算一下accuracy和cost
            if epoch_index % epoch_delta == 0:
                #################################
                #    开始在 train set上计算一下accuracy和cost
                #################################
                # 记录训练集中有多少个batch
                total_batches_in_train_set = 0
                # 记录在训练集中预测正确的次数
                total_correct_times_in_train_set = 0
                # 记录在训练集中的总cost
                total_cost_in_train_set = 0.
                for (train_batch_xs, train_batch_ys) in input_data.minibatches(x_train, y_train, batch_size, shuffle=True):
                    return_correct_times_in_batch = sess.run(graph['correct_times_in_batch'], feed_dict={
                        graph['x_placeholder']: train_batch_xs,
                        graph['y_placeholder']: train_batch_ys,
                        #graph['keep_prob_placeholder']: 1.0,
                    })
                    mean_cost_in_batch = sess.run(graph['cost'], feed_dict={
                        graph['x_placeholder']: train_batch_xs,
                        graph['y_placeholder']: train_batch_ys,
                        #graph['keep_prob_placeholder']: 1.0,
                    })

                    total_batches_in_train_set += 1
                    total_correct_times_in_train_set += return_correct_times_in_batch
                    total_cost_in_train_set += (mean_cost_in_batch * batch_size)

                #################################
                # 开始在 test set上计算一下accuracy和cost
                #################################
                # 记录测试集中有多少个batch
                total_batches_in_test_set = 0
                # 记录在测试集中预测正确的次数
                total_correct_times_in_test_set = 0
                # 记录在测试集中的总cost
                total_cost_in_test_set = 0.
                for (test_batch_xs, test_batch_ys) in input_data.minibatches(x_test, y_test, batch_size, shuffle=False):
                    return_correct_times_in_batch = sess.run(graph['correct_times_in_batch'], feed_dict={
                        graph['x_placeholder']: test_batch_xs,
                        graph['y_placeholder']: test_batch_ys,
                        #graph['keep_prob_placeholder']: 1.0,
                    })
                    mean_cost_in_batch = sess.run(graph['cost'], feed_dict={
                        graph['x_placeholder']: test_batch_xs,
                        graph['y_placeholder']: test_batch_ys,
                        #graph['keep_prob_placeholder']: 1.0,
                    })

                    total_batches_in_test_set += 1
                    total_correct_times_in_test_set += return_correct_times_in_batch
                    total_cost_in_test_set += (mean_cost_in_batch * batch_size)

                ### summary and print
                acy_on_test = total_correct_times_in_test_set / float(total_batches_in_test_set * batch_size)
                acy_on_train = total_correct_times_in_train_set / float(total_batches_in_train_set * batch_size)
                print(
                    'Epoch - {:2d} , acy_on_test:{:6.2f}%({}/{}),loss_on_test:{:6.2f}, acy_on_train:{:6.2f}%({}/{}),loss_on_train:{:6.2f}'.
                    format(epoch_index, acy_on_test * 100.0, total_correct_times_in_test_set,
                           total_batches_in_test_set * batch_size, total_cost_in_test_set, acy_on_train * 100.0,
                           total_correct_times_in_train_set, total_batches_in_train_set * batch_size,
                           total_cost_in_train_set))

                # 每轮训练完后就保存为pb文件
            constant_graph = graph_util.convert_variables_to_constants(sess, sess.graph_def, ["out_softmax"])  # out_softmax
            with tf.gfile.FastGFile(pb_file_path, mode='wb') as f:
                f.write(constant_graph.SerializeToString())


def main():
    batch_size = 20
    num_epochs =10

    # pb文件保存路径
    pb_file_path = "/home/dyf/PycharmProjects/classifer_flower/output/model.pb"

    g = build_network(height=500, width=500)
    train_network(g, batch_size, num_epochs, pb_file_path)


main()

t_model.py

import tensorflow as tf
import numpy as np
import PIL.Image as Image
from skimage import io, transform
import os

path1="/home/dyf/PycharmProjects/classifer_flower/flower_photos/test/daisy/"
path2="/home/dyf/PycharmProjects/classifer_flower/flower_photos/test/denlian/"
def read_img():
    imgs = []
    # for k in range(1,10):
    # path1= os.path.join(os.path.abspath(NG_path), '1'+format(str(k)))
    # path2=os.path.join(os.path.abspath(labels_path), 'NG'+format(str(k)+'.txt'))
    piclist = os.listdir(path1)
    for pic in piclist:
        if pic.endswith(".jpg"):
            old_path = os.path.join(os.path.abspath(path1), pic)
            img = io.imread(old_path)
            img = transform.resize(img, (500, 500))
            # img=img.reshape(100,100,3)
            imgs.append(img)

    piclist = os.listdir(path2)
    for pic in piclist:
        if pic.endswith(".jpg"):
            old_path = os.path.join(os.path.abspath(path2), pic)
            img = io.imread(old_path)
            img = transform.resize(img, (500, 500))
            # img=img.reshape(100,100,3)
            imgs.append(img)
           # label.append(0);

    return np.asarray(imgs, np.float32)

def recognize(png_path, pb_file_path):
    """
    Function:使用训练完的网络模型进行预测。

    Parameters
    ----------
        png_path:要预测的图片的路径。
        pb_file_path: pb文件的路径。

    """
    imgs=[]
    with tf.Graph().as_default():
        output_graph_def = tf.GraphDef()

        with open(pb_file_path, "rb") as f:
            output_graph_def.ParseFromString(f.read())  # rb
            _ = tf.import_graph_def(output_graph_def, name="")

        config = tf.ConfigProto(allow_soft_placement=True)
        tf.GPUOptions(per_process_gpu_memory_fraction=0.9)
        config.gpu_options.allow_growth = True
        with tf.Session(config=config) as sess:
            tf.global_variables_initializer().run()

            input_x = sess.graph.get_tensor_by_name("input:0")
            print(input_x)
            out_softmax = sess.graph.get_tensor_by_name("out_softmax:0")
            print(out_softmax)
            # keep_prob = sess.graph.get_tensor_by_name("keep_prob_placeholder:0")
            # print(keep_prob)
            # out_label = sess.graph.get_tensor_by_name("output:0")
            # print(out_label)

            #img_datas = np.array(Image.open(png_path).convert('L'))
            #img_datas = np.array(Image.open(png_path))
            #new_path = os.path.join(os.path.abspath(NG_path), '1 (' + format(str(i + 1)) + ').bmp')

            imgs = read_img()
            #imgs = np.array(imgs).reshape(-1, 200, 200, 3);
            # data = np.multiply(imgs, 1.0 / 255.0)
            img_out_softmax = sess.run(out_softmax, feed_dict={
                input_x: imgs,
                # keep_prob: 1.0,
            })
            c = 0.0
            for i in range(13):
                prediction_label = np.argmax(img_out_softmax[i].reshape(1,2,1), axis=1)
                print(img_out_softmax[i])
                if prediction_label[0] == 0:
                    c = c + 1
                #print(prediction_label[0])
            for i in range(13, 22):
                prediction_label = np.argmax(img_out_softmax[i].reshape(1,2,1), axis=1)
                print(img_out_softmax[i])
                #print(img_out_softmax[i].reshape(1,2,1))
                if prediction_label[0] == 1:
                    c = c + 1
                    print(prediction_label[0])
            print("acc:", c / 22)

recognize("/home/dyf/PycharmProjects/classifer_flower/flower_photos/test/",
          "/home/dyf/PycharmProjects/classifer_flower/output/model.pb")

使用opencv调用pb模型,该代码参考了网上的代码,具体的网址现在想找又没有找到

#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <fstream>
#include <iostream>
#include <cstdlib>
using namespace cv;
using namespace cv::dnn;
using namespace std;

//自己新建一个txt文件,写入分类的标签(一行写一个标签,例如二分类)
String labels_txt_file = "/home/dyf/Documents/数字图像处理/opencv/pb/graph.txt";
String tf_pb_file = "/home/dyf/Documents/数字图像处理/opencv/pb/model.pb";
String picture="/home/dyf/Documents/数字图像处理/opencv/pb/test/daisy/5794839_200acd910c_n.jpg";
vector <String> readClassNames();
int main()
{
    Mat src = imread(picture);
    int w = 500;
    int h = 500;
    Net net = readNetFromTensorflow(tf_pb_file);
    if (net.empty()) {
        cout << "error:no model" << endl;
    }
    Mat inputBlob = blobFromImage(src, 1.0/255. , Size(w, h), Scalar(), true, false);
    vector<String> labels = readClassNames();
    //执行图像分类
    Mat prob;
    net.setInput(inputBlob, "input");
    prob = net.forward("out_softmax");
    cout << prob << endl;

    Mat probMat = prob.reshape(1, 1);
    Point classNumber;
    double classProb;
    minMaxLoc(probMat, NULL, &classProb, NULL, &classNumber);
    int classidx = classNumber.x;
    cout << classidx << endl;
    cout<<"分类结果为:"<<labels[classidx]<<endl;

    return 0;

}

vector <String>readClassNames()
{
    vector <String>classNames;
    fstream fp(labels_txt_file);
    if (!fp.is_open())
    {
        cout << "does not open"<<endl;
        exit(-1);
    }
    string name;
    while (!fp.eof())
    {
        getline(fp, name);
        if (name.length())
            classNames.push_back(name);
    }
    fp.close();
    return classNames;
}

执行效果如下:

https://download.csdn.net/download/u013263891/10849045 

包括图片我已经上传到这个资源,图片数据在网上也是可以免费下载到了,如果想更方便一点儿 从这下载就可以了,代码应该是可以直接运行的,windows下可能需要稍作修改

猜你喜欢

转载自blog.csdn.net/u013263891/article/details/84994834