爆款云主机2核4G限时秒杀,88元/年起!
查看详情

活动

天翼云最新优惠活动,涵盖免费试用,产品折扣等,助您降本增效!
热门活动
  • 618智算钜惠季 爆款云主机2核4G限时秒杀,88元/年起!
  • 免费体验DeepSeek,上天翼云息壤 NEW 新老用户均可免费体验2500万Tokens,限时两周
  • 云上钜惠 HOT 爆款云主机全场特惠,更有万元锦鲤券等你来领!
  • 算力套餐 HOT 让算力触手可及
  • 天翼云脑AOne NEW 连接、保护、办公,All-in-One!
  • 中小企业应用上云专场 产品组合下单即享折上9折起,助力企业快速上云
  • 息壤高校钜惠活动 NEW 天翼云息壤杯高校AI大赛,数款产品享受线上订购超值特惠
  • 天翼云电脑专场 HOT 移动办公新选择,爆款4核8G畅享1年3.5折起,快来抢购!
  • 天翼云奖励推广计划 加入成为云推官,推荐新用户注册下单得现金奖励
免费活动
  • 免费试用中心 HOT 多款云产品免费试用,快来开启云上之旅
  • 天翼云用户体验官 NEW 您的洞察,重塑科技边界

智算服务

打造统一的产品能力,实现算网调度、训练推理、技术架构、资源管理一体化智算服务
智算云(DeepSeek专区)
科研助手
  • 算力商城
  • 应用商城
  • 开发机
  • 并行计算
算力互联调度平台
  • 应用市场
  • 算力市场
  • 算力调度推荐
一站式智算服务平台
  • 模型广场
  • 体验中心
  • 服务接入
智算一体机
  • 智算一体机
大模型
  • DeepSeek-R1-昇腾版(671B)
  • DeepSeek-R1-英伟达版(671B)
  • DeepSeek-V3-昇腾版(671B)
  • DeepSeek-R1-Distill-Llama-70B
  • DeepSeek-R1-Distill-Qwen-32B
  • Qwen2-72B-Instruct
  • StableDiffusion-V2.1
  • TeleChat-12B

应用商城

天翼云精选行业优秀合作伙伴及千余款商品,提供一站式云上应用服务
进入甄选商城进入云市场创新解决方案
办公协同
  • WPS云文档
  • 安全邮箱
  • EMM手机管家
  • 智能商业平台
财务管理
  • 工资条
  • 税务风控云
企业应用
  • 翼信息化运维服务
  • 翼视频云归档解决方案
工业能源
  • 智慧工厂_生产流程管理解决方案
  • 智慧工地
建站工具
  • SSL证书
  • 新域名服务
网络工具
  • 翼云加速
灾备迁移
  • 云管家2.0
  • 翼备份
资源管理
  • 全栈混合云敏捷版(软件)
  • 全栈混合云敏捷版(一体机)
行业应用
  • 翼电子教室
  • 翼智慧显示一体化解决方案

合作伙伴

天翼云携手合作伙伴,共创云上生态,合作共赢
天翼云生态合作中心
  • 天翼云生态合作中心
天翼云渠道合作伙伴
  • 天翼云代理渠道合作伙伴
天翼云服务合作伙伴
  • 天翼云集成商交付能力认证
天翼云应用合作伙伴
  • 天翼云云市场合作伙伴
  • 天翼云甄选商城合作伙伴
天翼云技术合作伙伴
  • 天翼云OpenAPI中心
  • 天翼云EasyCoding平台
天翼云培训认证
  • 天翼云学堂
  • 天翼云市场商学院
天翼云合作计划
  • 云汇计划
天翼云东升计划
  • 适配中心
  • 东升计划
  • 适配互认证

开发者

开发者相关功能入口汇聚
技术社区
  • 专栏文章
  • 互动问答
  • 技术视频
资源与工具
  • OpenAPI中心
开放能力
  • EasyCoding敏捷开发平台
培训与认证
  • 天翼云学堂
  • 天翼云认证
魔乐社区
  • 魔乐社区

支持与服务

为您提供全方位支持与服务,全流程技术保障,助您轻松上云,安全无忧
文档与工具
  • 文档中心
  • 新手上云
  • 自助服务
  • OpenAPI中心
定价
  • 价格计算器
  • 定价策略
基础服务
  • 售前咨询
  • 在线支持
  • 在线支持
  • 工单服务
  • 建议与反馈
  • 用户体验官
  • 服务保障
  • 客户公告
  • 会员中心
增值服务
  • 红心服务
  • 首保服务
  • 客户支持计划
  • 专家技术服务
  • 备案管家

了解天翼云

天翼云秉承央企使命,致力于成为数字经济主力军,投身科技强国伟大事业,为用户提供安全、普惠云服务
品牌介绍
  • 关于天翼云
  • 智算云
  • 天翼云4.0
  • 新闻资讯
  • 天翼云APP
基础设施
  • 全球基础设施
  • 信任中心
最佳实践
  • 精选案例
  • 超级探访
  • 云杂志
  • 分析师和白皮书
  • 天翼云·创新直播间
市场活动
  • 2025智能云生态大会
  • 2024智算云生态大会
  • 2023云生态大会
  • 2022云生态大会
  • 天翼云中国行
天翼云
  • 活动
  • 智算服务
  • 产品
  • 解决方案
  • 应用商城
  • 合作伙伴
  • 开发者
  • 支持与服务
  • 了解天翼云
      • 文档
      • 控制中心
      • 备案
      • 管理中心

      TensorFlow模型导出到OpenCV调用

      首页 知识中心 物联网 文章详情页

      TensorFlow模型导出到OpenCV调用

      2025-03-12 09:34:29 阅读次数:9

      OpenCV,文件,模型,训练

      引言

      本人因之前学习的c++,所以对c++的界面编程以及对OpenCV的使用较为熟悉,之前也学习过使用OpenCV调用face_detection基于tensorflow平台的模型文件(pb文件,pbtxt)文件,最近也在学习TensorFlow用来训练自己的分类模型,但对如何将已经训练好的模型进行导出,并应用于OpenCV这方面不是很了解,所以查阅了大量资料,总算能够将其实现。

      1.模型训练

      参考文章: 手把手教你训练分类自己的图片(车辆分类).

      (1)些许改进

      • 该文章整体架构很清晰,因为要使用此训练的模型,故在其中加入了模型加载及保存功能,使其变为增量训练模型,这样可以进行多次训练,将上次训练的模型加载进来,在此基础上进行训练,可以保存训练结果。
      • 因为使用的训练集的分类只有7类,故将其最后一层全连接层的输出改为7,此处是多加了一层使其输出变为7。
      • 在此架构中加入了with _scope(‘name’): ,这是为了后面使用tensorboard查看整体架构时清晰一些。
      • 还在最后一层的位置加入了softmax层,这一层不与后面发生关系,因为后面已经有sparse_softmax_cross_entropy了,此softmax仅仅是为了后面用来导出pb文件来使用的,softmax的节点名称是output。
      • 此架构本身具有将读入图片变为特定大小的功能,将img = transform.resize(img, (w, h))前的注释去掉即可。
      • 当我们想要训练自己的模型时,直接在此架构的基础上将训练模型改成自己想要训练的模型即可。
      1. 模型训练所用到的数据
        直接使用上方参考文章中的数据即可(数据量并不大,可以自己在百度爬取一些图片加入)
        其中black-car有123张,blue-truck有33张,green-bus有22张,red-bus有18张,red-car有114张,white-car有76张,white-truck有36张。总共422张图片。

      (2)整体训练模型的代码如下:

      1-car_cnn1.py

      import os
      import glob
      import time
      import numpy as np
      import tensorflow as tf
      from skimage import io, transform
      
      # os.environ["TF_CPP_MIN_LOG_LEVEL"] = '1'
      # 这是默认的显示等级,显示所有信息
      # os.environ["TF_CPP_MIN_LOG_LEVEL"] = '2'
      # 只显示 warning 和 Error
      os.environ["TF_CPP_MIN_LOG_LEVEL"] = '3'
      # 只显示 Error
      
      
      # 读取图片
      def read_img(path, w, h):
          cate = [path + x for x in os.listdir(path) if os.path.isdir(path + x)]
          # print(cate)
      
          imgs = []
          labels = []
      
          print('Start read the image ...')
      
          for index, folder in enumerate(cate):
              # print(index, folder)
              for im in glob.glob(folder + '/*.jpg'):
                  # print('Reading The Image: %s' % im)
                  img = io.imread(im)
                  img = transform.resize(img, (w, h))
                  imgs.append(img)
                  # print(index)
                  labels.append(index)                    # 每个子文件夹是一个label
                  # print(len(labels))
      
          print('Finished ...')
          print(len(imgs))
          print(len(labels))
      
          return np.asarray(imgs, np.float32), np.asarray(labels, np.float32)
      
      
      # 打乱顺序 为了均匀取数据
      def messUpOrder(data, label):
          num_example = data.shape[0]
          arr = np.arange(num_example)
          np.random.shuffle(arr)
          data = data[arr]
          label = label[arr]
      
          return data, label
      
      
      # 将所有数据分为训练集和验证集
      def segmentation(data, label, ratio=0.8):
          num_example = data.shape[0]
          s = np.int(num_example * ratio)
          x_train = data[:s]
          y_train = label[:s]
          x_val = data[s:]
          y_val = label[s:]
      
          return x_train, y_train, x_val, y_val
      
      
      # 构建网络
      def buildCNN(w, h, c):
          # 占位符
          with tf.name_scope('input'):
              x = tf.placeholder(tf.float32, shape=[None, w, h, c], name='x-input')
              y_ = tf.placeholder(tf.int32, shape=[None, ], name='y_')
      
          # 第一个卷积层 + 池化层(100——>50)
          with tf.name_scope('conv2d-pool-1'):
              conv1 = tf.layers.conv2d(
                  inputs=x,
                  filters=32,
                  kernel_size=[5, 5],
                  padding="same",
                  activation=tf.nn.relu,
                  kernel_initializer=tf.truncated_normal_initializer(stddev=0.01))
              pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2], strides=2)
      
          # 第二个卷积层 + 池化层 (50->25)
          with tf.name_scope('conv2d-pool-2'):
              conv2 = tf.layers.conv2d(
                  inputs=pool1,
                  filters=64,
                  kernel_size=[5, 5],
                  padding="same",
                  activation=tf.nn.relu,
                  kernel_initializer=tf.truncated_normal_initializer(stddev=0.01))
              pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2], strides=2)
      
          # 第三个卷积层 + 池化层 (25->12)
          with tf.name_scope('conv2d-pool-3'):
              conv3 = tf.layers.conv2d(
                  inputs=pool2,
                  filters=128,
                  kernel_size=[3, 3],
                  padding="same",
                  activation=tf.nn.relu,
                  kernel_initializer=tf.truncated_normal_initializer(stddev=0.01))
              pool3 = tf.layers.max_pooling2d(inputs=conv3, pool_size=[2, 2], strides=2)
      
          # 第四个卷积层 + 池化层 (12->6)
          with tf.name_scope('conv2d-pool-4'):
              conv4 = tf.layers.conv2d(
                  inputs=pool3,
                  filters=128,
                  kernel_size=[3, 3],
                  padding="same",
                  activation=tf.nn.relu,
                  kernel_initializer=tf.truncated_normal_initializer(stddev=0.01))
              pool4 = tf.layers.max_pooling2d(inputs=conv4, pool_size=[2, 2], strides=2)
      
          re1 = tf.reshape(pool4, [-1, 6 * 6 * 128])
      
          # 全连接层
          with tf.name_scope('layer-1'):
              dense1 = tf.layers.dense(inputs=re1,
                                       units=1024,
                                       activation=tf.nn.relu,
                                       kernel_initializer=tf.truncated_normal_initializer(stddev=0.01),
                                       kernel_regularizer=tf.contrib.layers.l2_regularizer(0.003))
          with tf.name_scope('layer-2'):
              dense2 = tf.layers.dense(inputs=dense1,
                                       units=512,
                                       activation=tf.nn.relu,
                                       kernel_initializer=tf.truncated_normal_initializer(stddev=0.01),
                                       kernel_regularizer=tf.contrib.layers.l2_regularizer(0.003))
          with tf.name_scope('layer-3'):
              dense3 = tf.layers.dense(inputs=dense2,
                                       units=32,
                                       activation=None,
                                       kernel_initializer=tf.truncated_normal_initializer(stddev=0.01),
                                       kernel_regularizer=tf.contrib.layers.l2_regularizer(0.003))
          with tf.name_scope('layer-4'):
              logits = tf.layers.dense(inputs=dense3,
                                       units=7,
                                       activation=None,
                                       kernel_initializer=tf.truncated_normal_initializer(stddev=0.01),
                                       kernel_regularizer=tf.contrib.layers.l2_regularizer(0.003))
          # 定义最后一层以此(此层只是用来挤压最后一个全连接层,得到概率,这个层次并未在后面的优化器中使用,只是为了)
          #为了得到pb文件,或者在tensorboard可视化,以及用于导入OpenCV中使用
          output = tf.nn.softmax(logits, name='output')
          return logits, x, y_
      
      
      # 返回损失函数的值,准确值等参数
      def accCNN(logits, y_):
          with tf.name_scope('cross_entropy'):
              loss = tf.losses.sparse_softmax_cross_entropy(labels=y_, logits=logits)
          with tf.name_scope('AdamOptimizer'):
              train_op = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)   #优化器
          with tf.name_scope('acc'):
              correct_prediction = tf.equal(tf.cast(tf.argmax(logits, 1), tf.int32), y_)
              acc = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
      
          return loss, train_op, correct_prediction, acc
      
      
      # 定义一个函数,按批次取数据
      def minibatches(inputs=None, targets=None, batch_size=None, shuffle=False):
          assert len(inputs) == len(targets), 'len(inputs) != len(targets)'
          if shuffle:
              indices = np.arange(len(inputs))   # [0, 1, 2, ..., 422]
              np.random.shuffle(indices)     # 打乱下标顺序
          #从0开始,到结束,步长为batch_size
          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 runable(x_train, y_train, train_op, loss, acc, x, y_, x_val, y_val):
          # 训练和测试数据,可将n_epoch设置更大一些
          n_epoch = 10              #之前是100轮,有点多,改成增量训练模型后就可以多轮次增加训练了
          batch_size = 30             #20是每批读取数据的数量
      
          ###创建saver对象用于模型保存和加载
          saver = tf.train.Saver()
      
          sess = tf.InteractiveSession()                          #手动启动session对话,还需关闭(也可使用with)
          sess.run(tf.global_variables_initializer())             #对全局变量初始化先
      
          ###训练之前,检查是否存在已经训练的模型(要在初始化后进行判断)
          # 如果存在则加载进来,进行增量训练
          if os.path.exists("./model/checkpoint"):  # 判断此文件是否存在
              saver.restore(sess, "./model/")  # 将此模型加载到sess中,sess就有了经过训练的参数了,如权重和偏执,经过梯度下降训练了一段时间的
              print("模型加载成功")
      
          for epoch in range(n_epoch):
              print('epoch: ', epoch)             #打印轮次
              # training
              train_loss, train_acc, n_batch = 0, 0, 0
              for x_train_a, y_train_a in minibatches(x_train, y_train, batch_size, shuffle=True):        #定义每轮的训练批次
                  # print('x_val_a: ', x_val_a.shape())
                  # print('y_val_a: ', y_val_a.shape())
                  _, err, ac = sess.run([train_op, loss, acc], feed_dict={x: x_train_a, y_: y_train_a}) #执行操作并返回参数
                  train_loss += err
                  train_acc += ac
                  n_batch += 1
              print("train loss: %f" % (train_loss / n_batch))
              print("train acc: %f" % (train_acc / n_batch))
      
              # validation
              val_loss, val_acc, n_batch = 0, 0, 0
              for x_val_a, y_val_a in minibatches(x_val, y_val, batch_size, shuffle=False):
                  # print('x_val_a: ', x_val_a)
                  # print('y_val_a: ', y_val_a)
                  err, ac = sess.run([loss, acc], feed_dict={x: x_val_a, y_: y_val_a})
                  val_loss += err
                  val_acc += ac
                  n_batch += 1
              print("validation loss: %f" % (val_loss / n_batch))
              print("validation acc: %f" % (val_acc / n_batch))
              print('*' * 50)
      
          ###训练完成后保存模型
          saver.save(sess, "./model/")
      
          sess.close()            #关闭会话
      
      
      if __name__ == '__main__':
          imgpath = 'dataset/'
      
          w = 100
          h = 100
          c = 3
      
          ratio = 0.8  # 选取训练集的比例
      
          data, label = read_img(path=imgpath, w=w, h=h)#读取图片
          print(0)
      
          data, label = messUpOrder(data=data, label=label)#打乱顺序
          print(1)
      
          x_train, y_train, x_val, y_val = segmentation(data=data, label=label, ratio=ratio)  #分为训练集和验证集
          print('x_train: ', len(x_train))
          print('y_train: ', len(y_train))
          print(2)
      
          logits, x, y_ = buildCNN(w=w, h=h, c=c)     #构建网络返回最后一层结果,此时还不执行,只是操作
          print(3)
          print(logits)
      
          loss, train_op, correct_prediction, acc = accCNN(logits=logits, y_=y_)      #评估网络,返回损失函数,训练,预测值,准确率
          #返回损失函数,优化器,预测值,准确率等操作,需在后面的训练函数中执行操作
          print(4)
      
          runable(x_train=x_train, y_train=y_train, train_op=train_op, loss=loss, acc=acc, x=x, y_=y_, x_val=x_val, y_val=y_val)
      

      (3)生成模型

      会生成四个文件,在后面导出成pb文件时会用到

      (4)控制台结果

      运行了10多次,每次差不多10轮(epoch),总共100轮,最终训练结果的准确率达到100%。在其本身的训练集下,当然其训练集本身图片数量并不多,所得的模型在此训练集表现良好,可以在其数据集下再增加一些图片,这样训练得到的模型会更好一些。

      2.使用tensorboard查看模型架构,找出输入输出(可跳过)

      实际中此使用tensorboard步骤可以忽略,因为在之前的代码中已经将节点的输出名称命名好了,直接在后面的导出成pb文件的代码中就可以使用了。

      (1)生成事件文件

      先执行以下代码,生成事件文件,此事件文件会导入到tensorboard,可以在浏览器中查看
      2-check_meta_tensor.py

      import tensorflow as tf
      
      sess = tf.Session()
      tf.train.import_meta_graph("./model/.meta")
      tf.summary.FileWriter("./summary", sess.graph)
      

      生成的事件文件如下

      (2)在cmd中执行以下语句

      • 进入到python创建的项目的scripts文件下
        C:\Users\zhaocai>G:
        G:>cd G:\AILearning\AID2002\venv\Scripts
      • 执行以下操作
        G:\AILearning\AID2002\venv\Scripts>tensorboard --logdir=“G:\AILearning\AID2002\Neural_network-master\summary”

      (3)执行结果

      (4)在浏览器中查看

      • 在浏览器输入http://localhost:6006/
        下方就是该模型的架构,上面的节点名称有的是通过with _scope(‘name’)命名的,而有的是直接在操作中命名的,如softmax中的output名称。可以在tensorboard中清晰的看到模型的结构。

      3.导出为pb文件

      参考链接:从TensorFlow模型导出到OpenCV部署详解.

      (1)注意事项

      • 此处要注意的是输出层的名称,在之前训练模型的代码中加入了softmax层,并为其命名为‘output’,就是为了在此导出pb文件而使用的。
      • 此处为了适应本地文件,在此代码中做了一些调整

      (2)代码如下:

      3-out_pb.py

      #转换成pb文件
      import tensorflow as tf
      import os.path
      import argparse
      from tensorflow.python.framework import graph_util
      
      
      def freeze_graph(output_node_names):
          #checkpoint = tf.train.get_checkpoint_state(model_folder)
          #input_checkpoint = checkpoint.model_checkpoint_path
      
          saver = tf.train.import_meta_graph('./model/.meta', clear_devices=True)
          graph = tf.get_default_graph()
          input_graph_def = graph.as_graph_def()
      
          with tf.Session() as sess:
              saver.restore(sess, './model/')
              for node in input_graph_def.node:
                  if node.op == 'RefSwitch':
                      node.op = 'Switch'
                      for index in range(len(node.input)):
                          if 'moving_' in node.input[index]:
                              node.input[index] = node.input[index] + '/read'
                  elif node.op == 'AssignSub':
                      node.op = 'Sub'
                      if 'use_locking' in node.attr: del node.attr['use_locking']
      
              output_graph_def = graph_util.convert_variables_to_constants(
                  sess,
                  input_graph_def,
                  output_node_names
              )
              with tf.gfile.GFile('classify-car.pb', "wb") as f:
                  f.write(output_graph_def.SerializeToString())
      
      
      if __name__ == '__main__':
          freeze_graph(['output'])
      

      (3)执行结果如下

      4.查看pb文件的节点名称(可跳过)

      参考链接: TensorFlow查看输入节点和输出节点名称.

      (1)代码如下:

      4-checkPB.py

      import tensorflow as tf
      import os
      
      # model_dir = './'
      out_path = './'
      model_name = 'classify-car.pb'
      
      def create_graph():
          with tf.gfile.FastGFile(os.path.join(out_path + model_name), 'rb') as f:
              graph_def = tf.GraphDef()
              graph_def.ParseFromString(f.read())
              tf.import_graph_def(graph_def, name='')
      
      create_graph()
      tensor_name_list = [tensor.name for tensor in tf.get_default_graph().as_graph_def().node]
      for tensor_name in tensor_name_list:
          print(tensor_name)
      

      (2)执行结果如下:

      input/x-input
      conv2d/kernel
      conv2d/kernel/read
      conv2d/bias
      conv2d/bias/read
      conv2d-pool-1/conv2d/Conv2D
      conv2d-pool-1/conv2d/BiasAdd
      conv2d-pool-1/conv2d/Relu
      conv2d-pool-1/max_pooling2d/MaxPool
      conv2d_1/kernel
      conv2d_1/kernel/read
      conv2d_1/bias
      conv2d_1/bias/read
      conv2d-pool-2/conv2d/Conv2D
      conv2d-pool-2/conv2d/BiasAdd
      conv2d-pool-2/conv2d/Relu
      conv2d-pool-2/max_pooling2d/MaxPool
      conv2d_2/kernel
      conv2d_2/kernel/read
      conv2d_2/bias
      conv2d_2/bias/read
      conv2d-pool-3/conv2d/Conv2D
      conv2d-pool-3/conv2d/BiasAdd
      conv2d-pool-3/conv2d/Relu
      conv2d-pool-3/max_pooling2d/MaxPool
      conv2d_3/kernel
      conv2d_3/kernel/read
      conv2d_3/bias
      conv2d_3/bias/read
      conv2d-pool-4/conv2d/Conv2D
      conv2d-pool-4/conv2d/BiasAdd
      conv2d-pool-4/conv2d/Relu
      conv2d-pool-4/max_pooling2d/MaxPool
      Reshape/shape
      Reshape
      dense/kernel
      dense/kernel/read
      dense/bias
      dense/bias/read
      layer-1/dense/MatMul
      layer-1/dense/BiasAdd
      layer-1/dense/Relu
      dense_1/kernel
      dense_1/kernel/read
      dense_1/bias
      dense_1/bias/read
      layer-2/dense/MatMul
      layer-2/dense/BiasAdd
      layer-2/dense/Relu
      dense_2/kernel
      dense_2/kernel/read
      dense_2/bias
      dense_2/bias/read
      layer-3/dense/MatMul
      layer-3/dense/BiasAdd
      dense_3/kernel
      dense_3/kernel/read
      dense_3/bias
      dense_3/bias/read
      layer-4/dense/MatMul
      layer-4/dense/BiasAdd
      output
      

      很明显,从输入到输出的节点都已经包括在其内了

      5.使用OpenCV查看其网络信息(可跳过)

      此处加载网络并未用到pbtxt文件,网上也有将pb文件导出为pbtxt文件的代码,但当将pb导出为pbtxt时,无法也将pbtxt加载到网络中,具体原因暂不明确。
      不过此处只加载pb文件就能够使用了

      (1)代码如下:

      #include <opencv2/opencv.hpp>
      #include <opencv2/dnn.hpp>			//包含dnn模块的头文件
      #include <iostream>
      #include <fstream>				//文件流进行txt文件读取
      
      using namespace cv;
      using namespace cv::dnn;			//包含dnn的命名空间
      using namespace std;
      
      int main() {
      	//车辆分类,输入模型的地址
      	string bin_model = "G:/AILearning/models/classify-car/classify-car.pb";
      
      	//加载模型
      	Net net = readNetFromTensorflow(bin_model);
      
      	//获取各层信息
      	vector<string> layer_names = net.getLayerNames();		//此时我们就可以获取所有层的名称了,有了这些可以将其ID取出
      	for (int i = 0; i < layer_names.size(); i++) {
      		int id = net.getLayerId(layer_names[i]);			//通过name获取其id
      		auto layer = net.getLayer(id);						//通过id获取layer
      		printf("layer id:%d,type:%s,name:%s\n", id, layer->type.c_str(), layer->name.c_str());	//将每一层的id,类型,姓名打印出来(可以明白此网络有哪些结构信息了)
      	}
      	waitKey(0);
      	return 0;
      }
      

      (2)结果如下

      6.使用OpenCV调用模型,输入图片测试分类结果

      (1)代码如下:

      #include <opencv2/opencv.hpp>
      #include <opencv2/dnn.hpp>			//包含dnn模块的头文件
      #include <iostream>
      #include <fstream>				//文件流进行txt文件读取
      
      using namespace cv;
      using namespace cv::dnn;			//包含dnn的命名空间
      using namespace std;
      
      //定义名称,用于后面的显示操作
      String objNames[] = { 
      	"black-car","blue-truck",
      	"green-bus","red-bus","red-car",
      	"white-car","white-truck" };
      
      int main() {
      
      	//模型的pb文件
      	string bin_model = "G:/AILearning/models/classify-car/classify-car3.pb";
      
      	load DNN model
      	Net net = readNetFromTensorflow(bin_model);
      
      	//获取各层信息
      	//vector<string> layer_names = net.getLayerNames();		//此时我们就可以获取所有层的名称了,有了这些可以将其ID取出
      	//for (int i = 0; i < layer_names.size(); i++) {
      	//	int id = net.getLayerId(layer_names[i]);			//通过name获取其id
      	//	auto layer = net.getLayer(id);						//通过id获取layer
      	//	printf("layer id:%d,type:%s,name:%s\n", id, layer->type.c_str(), layer->name.c_str());	//将每一层的id,类型,姓名打印出来(可以明白此网络有哪些结构信息了)
      	//}
      
      	Mat src = imread("G:/AILearning/testImage/2-21.jpg");	//G:\AILearning\testImage
      															//2-20,2-21,2-11,2-1
      	if (src.empty()) {
      		cout << "could not load image.." << endl;
      		getchar();
      		return -1;
      	}
      	imshow("src", src);
      
      	//构建输入(根据建立的网络模型时的输入)
      	Mat inputBlob = blobFromImage(src, 1.0, Size(100, 100), Scalar(), true, false);	//我们要将图像resize成100*100的才是我们神经网络可以接受的宽高
      	//参数1:输入图像,参数2:默认1.0表示0-255范围的,参数3:设置输出的大小,参数4:均值对所有数据中心化预处理,参数5:是否进行通道转换(需要),参数6:,参数7:默认深度为浮点型
      
      	//上方得到的inputBlob是4维的(在变量窗口看dim),所以在imagewatch中无法查看
      
      	//设置输入
      	//现在要将其输入到创建的网络中
      	net.setInput(inputBlob);
      
      	//进行推断得到输出
      	//让网络执行得到output,调用forward可以得到一个结果
      	//此处不给参数,得到的是最后一层的结果,也可以输入层数得到任何一层的输出结果
      	Mat probMat = net.forward();	//通过前面的输出层看最后一层,可以知道输出7个分类
      	
      	对数据进行序列化(变成1行n列的,可以在后面进行方便的知道是哪个index了)
      	Mat prob = probMat.reshape(1, 1);		//reshape函数可以进行序列化,(输出为1通道1行的数据,参数1:1个通道,参数2:1行)将输出结果变成1行n列的,但前面probMat本身就是7*1*1
      	//										//实际结果probMat和prob相同
      	//										//当其他网络probMat需要序列化的时候,reshape就可以了
      
      	此时找到最大的那个
      	Point classNum;
      	double classProb;
      	minMaxLoc(prob, NULL, &classProb, NULL, &classNum);//此时只获取最大值及最大值位置,最小值不管他
      	int index = classNum.x;		//此时得到的是最大值的列坐标。就是其类的索引值,就可以知道其类名了
      	printf("\n current index=%d,possible:%2f,name=%s\n", index, classProb, objNames[index].c_str());	
      	此时可以将名称打印到图片上去
      	putText(src, objNames[index].c_str(), Point(50, 50), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 255), 2, 8);
      	imshow("result", src);
      
      	waitKey(0);
      	return 0;
      }
      

      (2)结果如下所示

      结论

      • 从数据集中随机挑选了10张图片,全部分类正确。但从网上再次下载新的图片对其分类时,有一部分分类出现了错误,这说明我们的训练的模型还不够完善,尽管在422张的数据集上达到了100%的准确率,但这些数据还不够,需要下载更多的图片对其进行训练。
      • 可以使用爬虫工具批量爬取图片,使得数据集每个类下的数据达到200张以上即可,当然越多越好,但数量越多,所需的计算时间也会越多,根据具体情况,自己自行确定。
      • 本文主要提供了一种从TensorFlow模型训练到使用OpenCV调用的一种方式,这样大家可以将自己训练好的模型能够结合OpenCV真实应用出来,可以训练好模型部署到实际项目中。
      • 因为本文章参考了大量网上的公开的文章,故也将此文章公开,希望能对大家有所帮助。
      版权声明:本文内容来自第三方投稿或授权转载,原文地址:https://zhaocai-l.blog.csdn.net/article/details/108592530,作者:吾名招财,版权归原作者所有。本网站转在其作品的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如因作品内容、版权等问题需要同本网站联系,请发邮件至ctyunbbs@chinatelecom.cn沟通。

      上一篇:【大模型认识】警惕AI幻觉,利用插件+微调来增强GPT模型

      下一篇:Docker网络模型深度解析

      相关文章

      2025-05-19 09:05:01

      项目更新到公网服务器的操作步骤

      项目更新到公网服务器的操作步骤

      2025-05-19 09:05:01
      公网 , 数据库 , 文件 , 更新 , 服务器
      2025-05-19 09:04:38

      js本地上传图片后实现预览与删除功能

      js本地上传图片后实现预览与删除功能

      2025-05-19 09:04:38
      js , 上传 , 删除 , 文件
      2025-05-19 09:04:30

      判断dmp文件的导出方式是exp or expdp

      判断dmp文件的导出方式是exp or expdp

      2025-05-19 09:04:30
      expdp , 导出 , 文件
      2025-05-19 09:04:30

      开源与闭源:AI模型发展的两条路径

      开源与闭源:AI模型发展的两条路径

      2025-05-19 09:04:30
      开源 , 模型 , 用户
      2025-05-16 09:15:17

      Linux系统基础-文件系统

      Linux系统基础-文件系统

      2025-05-16 09:15:17
      hello , 写入 , 文件 , 输出
      2025-05-14 10:33:25

      webpack5基础--01_基本使用

      webpack5基础--01_基本使用

      2025-05-14 10:33:25
      json , main , package , Webpack , 打包 , 文件 , 编译
      2025-05-14 10:33:25

      webpack5基础--02_基本配置( 5 大核心概念)

      webpack5基础--02_基本配置( 5 大核心概念)

      2025-05-14 10:33:25
      config , loader , webpack , Webpack , 文件 , 模式 , 配置文件
      2025-05-14 10:33:16

      30天拿下Python之文件操作

      Python是一种高级编程语言,它提供了许多内置函数和模块来处理文件操作,主要包括:打开文件、读取文件、写入文件、关闭文件、获取目录列表等。

      2025-05-14 10:33:16
      Python , 使用 , 函数 , 文件 , 权限 , 目录
      2025-05-14 10:07:38

      30天拿下Rust之箱、包和模块

      Rust语言使用模块系统来组织工程和代码。模块系统允许我们将相关的函数、类型、常量等组织在一起,形成一个逻辑上的单元。通过模块系统,我们可以隐藏实现细节,只暴露必要的接口,从而提高代码的可读性和可维护性。

      2025-05-14 10:07:38
      Rust , 关键字 , 文件 , 模块 , 访问
      2025-05-14 10:03:05

      30天拿下Python之模块和包

      Python的模块(Module)和包(Package)是Python的两个主要概念,它们都是用来组织和封装代码的机制。

      2025-05-14 10:03:05
      Python , 代码 , 函数 , 导入 , 文件 , 模块
      查看更多
      推荐标签

      作者介绍

      天翼云小翼
      天翼云用户

      文章

      33561

      阅读量

      5227280

      查看更多

      最新文章

      开源与闭源:AI模型发展的两条路径

      2025-05-19 09:04:30

      python 加载 TensorFlow 模型

      2025-05-14 09:51:21

      Transformer模型:Position Embedding实现

      2025-05-14 09:51:21

      django从入门到精通(五)——表单与模型

      2025-04-18 08:02:02

      diffusionAI从入门到精通——基本组件介绍

      2025-04-18 08:02:02

      python 无监督生成模型

      2025-04-09 09:13:17

      查看更多

      热门文章

      Django入门:第五章、模型建立与迁移

      2023-03-22 09:02:52

      PyTorch 06: PyTorch保存和加载模型

      2023-05-06 08:59:26

      AIGC从入门到大神:解锁人工智能生成内容的奥秘

      2024-12-17 08:34:36

      什么是模型

      2024-04-18 09:42:00

      深度学习TensorFlow---保存和加载 Keras 模型

      2025-03-05 09:22:35

      数学建模系列(1/4):数学建模简介

      2024-10-30 08:59:10

      查看更多

      热门标签

      模型 生成 学习 django python 图像 训练
      查看更多

      相关产品

      弹性云主机

      随时自助获取、弹性伸缩的云服务器资源

      天翼云电脑(公众版)

      便捷、安全、高效的云电脑服务

      对象存储

      高品质、低成本的云上存储服务

      云硬盘

      为云上计算资源提供持久性块存储

      查看更多

      随机文章

      统计学习方法——机器学习和统计学习介绍及基本入门

      MATLAB入门指南:从零开始进行数学建模竞赛

      【知识科普】关于领域模型设计的一些思考

      深度学习从入门到精通——pytorch实现生成手写数字

      数学建模系列(2/4):建模入门

      python梯度提升决策树

      • 7*24小时售后
      • 无忧退款
      • 免费备案
      • 专家服务
      售前咨询热线
      400-810-9889转1
      关注天翼云
      • 旗舰店
      • 天翼云APP
      • 天翼云微信公众号
      服务与支持
      • 备案中心
      • 售前咨询
      • 智能客服
      • 自助服务
      • 工单管理
      • 客户公告
      • 涉诈举报
      账户管理
      • 管理中心
      • 订单管理
      • 余额管理
      • 发票管理
      • 充值汇款
      • 续费管理
      快速入口
      • 天翼云旗舰店
      • 文档中心
      • 最新活动
      • 免费试用
      • 信任中心
      • 天翼云学堂
      云网生态
      • 甄选商城
      • 渠道合作
      • 云市场合作
      了解天翼云
      • 关于天翼云
      • 天翼云APP
      • 服务案例
      • 新闻资讯
      • 联系我们
      热门产品
      • 云电脑
      • 弹性云主机
      • 云电脑政企版
      • 天翼云手机
      • 云数据库
      • 对象存储
      • 云硬盘
      • Web应用防火墙
      • 服务器安全卫士
      • CDN加速
      热门推荐
      • 云服务备份
      • 边缘安全加速平台
      • 全站加速
      • 安全加速
      • 云服务器
      • 云主机
      • 智能边缘云
      • 应用编排服务
      • 微服务引擎
      • 共享流量包
      更多推荐
      • web应用防火墙
      • 密钥管理
      • 等保咨询
      • 安全专区
      • 应用运维管理
      • 云日志服务
      • 文档数据库服务
      • 云搜索服务
      • 数据湖探索
      • 数据仓库服务
      友情链接
      • 中国电信集团
      • 189邮箱
      • 天翼企业云盘
      • 天翼云盘
      ©2025 天翼云科技有限公司版权所有 增值电信业务经营许可证A2.B1.B2-20090001
      公司地址:北京市东城区青龙胡同甲1号、3号2幢2层205-32室
      • 用户协议
      • 隐私政策
      • 个人信息保护
      • 法律声明
      备案 京公网安备11010802043424号 京ICP备 2021034386号