关于siamfc tensorflow1

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/StayFoolish_Fan/article/details/80467907

说明:该系列博客源码链接为:https://github.com/bilylee/SiamFC-TensorFlow,是实验室同小组的师兄用TensorFlow实现SiameseFC算法的最终公开版本,经过了长时间的打磨,各个模块功能明确,整体可读性和可移植性极好,我相信这对做Tracking的小伙伴来说,是个入门SiameseFC Tracker的特别好的选择。哈哈,觉得代码很棒的小伙伴们可以点个Star哦,也欢迎交流学习和指教。

这篇博客主要的目的就是简单地跑一下实验,让下载的代码能用预训练的模型去测试单个视频,并对结果可视化,从视觉上感受一下这个跟踪算法的效果,至于如果要自己训练自己的模型该如何准备训练数据,如何设计自己的模型,如何训练自己的模型,以及如何评估自己的模型等,这些问题都将在后面的系列博客中慢慢道来。

1: SiameseFC-TensorFlow环境配置

可参考源码中的说明,这里将截图放在这里,大家自行准备可运行的环境。


2:预训练模型下载转换和测试

可参考源代码中的说明,这里也给个截图,然后主要对一些文件做一些详细一点的注解。内容主要有预训练模型和测试视频的下载,模型转换以及转换前后的模型对比检验,视频的测试和结果的可视化。


2.1  预训练模型和测试视频下载

核心文件:scripts/download_assets.py

核心功能:下载SiameseFC的matlab版本预训练模型,同时下载用于测试的单个视频。


   
   
  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Copyright © 2017 bily Huazhong University of Science and Technology
  5. #
  6. # Distributed under terms of the MIT license.
  7. import os.path as osp
  8. import sys
  9. import zipfile
  10. import six.moves.urllib as urllib # 数据下载相关库 , urllib
  11. CURRENT_DIR = osp.dirname(__file__) # 返回当前.py脚本文件的路径
  12. ROOT_DIR = osp.join(CURRENT_DIR, '..')
  13. sys.path.append(ROOT_DIR) # 增加模块的搜索路径
  14. from utils.misc_utils import mkdir_p # 自己编写的makir_p函数,生成路径
  15. def download_or_skip(download_url, save_path): # 数据下载函数
  16. if not osp.exists(save_path): # 判断数据是否已经下载,避免重复下载
  17. print( 'Downloading: {}'.format(download_url))
  18. opener = urllib.request.URLopener()
  19. opener.retrieve(download_url, save_path)
  20. else:
  21. print( 'File {} exists, skip downloading.'.format(save_path))
  22. if __name__ == '__main__': # 数据下载准备 主函数
  23. assets_dir = osp.join(ROOT_DIR, 'assets') # 添加数据资源保存的路径assets_dir
  24. # Make assets directory
  25. mkdir_p(assets_dir) # 生成路径,存储数据资源
  26. # Download the pretrained color model # 下载SiameseFC-color pretrained 模型
  27. download_base = 'https://www.robots.ox.ac.uk/~luca/stuff/siam-fc_nets/'
  28. model_name = '2016-08-17.net.mat'
  29. download_or_skip(download_base + model_name, osp.join(assets_dir, model_name))
  30. # Download the pretrained gray model # 下载SiameseFC-color-gray pretrained 模型
  31. download_base = 'https://www.robots.ox.ac.uk/~luca/stuff/siam-fc_nets/'
  32. model_name = '2016-08-17_gray025.net.mat'
  33. download_or_skip(download_base + model_name, osp.join(assets_dir, model_name))
  34. # Download one test sequence # 下载一个测试视频,供测试和显示
  35. download_base = "http://cvlab.hanyang.ac.kr/tracker_benchmark/seq_new/"
  36. seq_name = 'KiteSurf.zip'
  37. download_or_skip(download_base + seq_name, osp.join(assets_dir, seq_name))
  38. # Unzip the test sequence # 将下载的视频.zip文件解压缩
  39. with zipfile.ZipFile(osp.join(assets_dir, seq_name), 'r') as zip_ref:
  40. zip_ref.extractall(assets_dir)

2.2  模型转换

核心文件:experiments/SiamFC-3s-color-pretrained.py、SiamFC-3s-gray-pretrained.py

相关文件:scripts/convert_pretrained_model.py,utils/train_utils.py

核心功能:将siameseFC的color和gray模型由matlab格式转换成tensorflow方便读取的格式。

就从最外边的实验封装文件慢慢往里看吧:experiments/SiamFC-3s-color-pretrained.py


   
   
  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Copyright © 2017 bily Huazhong University of Science and Technology
  5. #
  6. # Distributed under terms of the MIT license.
  7. """Load pretrained color model in the SiamFC paper and save it in the TensorFlow format"""
  8. from __future__ import absolute_import
  9. from __future__ import division
  10. from __future__ import print_function
  11. import os.path as osp
  12. import sys
  13. CURRENT_DIR = osp.dirname(__file__)
  14. sys.path.append(osp.join(CURRENT_DIR, '..'))
  15. print( osp.join(CURRENT_DIR, '..')) # 添加搜索路径
  16. from configuration import LOG_DIR # 从配置文件中导入log存储的路径
  17. from scripts.convert_pretrained_model import ex # 导入对应的experiment
  18. # 这里只是实验的表皮,具体实验还得看scripts.convert_pretrained_model详细内容
  19. if __name__ == '__main__':
  20. RUN_NAME = 'SiamFC-3s-color-pretrained'
  21. ex.run(config_updates={ 'model_config': { 'embed_config': { 'embedding_checkpoint_file': '/workspace/czx/Projects/SiamFC-TensorFlow/assets/2016-08-17.net.mat',
  22. 'train_embedding': False, },
  23. },
  24. 'train_config': { 'train_dir': osp.join(LOG_DIR, 'track_model_checkpoints', RUN_NAME), },
  25. 'track_config': { 'log_dir': osp.join(LOG_DIR, 'track_model_inference', RUN_NAME), }
  26. }, # 实验运行管理,这里的话就是根据需要更新一些配置文件中的参数
  27. options={ '--name': RUN_NAME,
  28. '--force': True,
  29. '--enforce_clean': False,
  30. })

模型转换实验文件:scripts/convert_pretrained_model.py


   
   
  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Copyright © 2017 bily Huazhong University of Science and Technology
  5. #
  6. # Distributed under terms of the MIT license.
  7. """Convert the matlab-pretrained model into TensorFlow format"""
  8. from __future__ import absolute_import
  9. from __future__ import division
  10. from __future__ import print_function
  11. import logging
  12. import os
  13. import os.path as osp
  14. import sys
  15. import numpy as np
  16. import tensorflow as tf
  17. CURRENT_DIR = osp.dirname(__file__)
  18. sys.path.append(osp.join(CURRENT_DIR, '..')) # 添加搜索路径
  19. import configuration
  20. import siamese_model
  21. from utils.misc_utils import auto_select_gpu, save_cfgs
  22. # Set GPU
  23. os.environ[ 'CUDA_VISIBLE_DEVICES'] = auto_select_gpu() # 自动选择GPU
  24. tf.logging.set_verbosity(tf.logging.DEBUG)
  25. from sacred import Experiment # 更好地进行实验管理
  26. ex = Experiment(configuration.RUN_NAME)
  27. @ex.config # 加载参数配置
  28. def configurations():
  29. # Add configurations for current script, for more details please see the documentation of `sacred`.
  30. model_config = configuration.MODEL_CONFIG
  31. train_config = configuration.TRAIN_CONFIG
  32. track_config = configuration.TRACK_CONFIG
  33. @ex.automain # 主函数
  34. def main(model_config, train_config, track_config):
  35. # Create training directory
  36. train_dir = train_config[ 'train_dir'] # 创建训练路径
  37. if not tf.gfile.IsDirectory(train_dir):
  38. tf.logging.info( 'Creating training directory: %s', train_dir)
  39. tf.gfile.MakeDirs(train_dir)
  40. # Build the Tensorflow graph
  41. g = tf.Graph()
  42. with g.as_default(): # 默认graph
  43. # Set fixed seed
  44. np.random.seed(train_config[ 'seed'])
  45. tf.set_random_seed(train_config[ 'seed'])
  46. # 实际上单纯地转换这样的一个预训练模型格式是不需要在这里调用siameseFC构建的,但是整份代码,将这样的
  47. # 一种预训练模型加载看成是模型训练的一个初始化,而模型转换根据配置参数进行的一个初始化方式。
  48. model = siamese_model.SiameseModel(model_config, train_config, mode= 'inference')
  49. model.build()
  50. # Save configurations for future reference
  51. save_cfgs(train_dir, model_config, train_config, track_config)
  52. saver = tf.train.Saver(tf.global_variables(),
  53. max_to_keep=train_config[ 'max_checkpoints_to_keep'])
  54. # Dynamically allocate GPU memory
  55. gpu_options = tf.GPUOptions(allow_growth= True)
  56. sess_config = tf.ConfigProto(gpu_options=gpu_options)
  57. sess = tf.Session(config=sess_config)
  58. model_path = tf.train.latest_checkpoint(train_config[ 'train_dir'])
  59. if not model_path:
  60. # Initialize all variables
  61. sess.run(tf.global_variables_initializer())
  62. sess.run(tf.local_variables_initializer())
  63. start_step = 0
  64. # 因为在这里我们转换预训练模型的格式的话只需要设置if后面的参数即可
  65. # Load pretrained embedding model if needed
  66. if model_config[ 'embed_config'][ 'embedding_checkpoint_file']:
  67. model.init_fn(sess) # 这是模型初始化的一个方法,后面的给出具体调用了啥函数
  68. else:
  69. logging.info( 'Restore from last checkpoint: {}'.format(model_path))
  70. sess.run(tf.local_variables_initializer())
  71. saver.restore(sess, model_path)
  72. start_step = tf.train.global_step(sess, model.global_step.name) + 1
  73. checkpoint_path = osp.join(train_config[ 'train_dir'], 'model.ckpt')
  74. saver.save(sess, checkpoint_path, global_step=start_step) # 保存为.ckpt

这里贴出model.init_fn的内容吧,且先不要深究siamese_model.py里面的其他内容


   
   
  1. def setup_embedding_initializer(self):
  2. """Sets up the function to restore embedding variables from checkpoint."""
  3. embed_config = self.model_config[ 'embed_config']
  4. if embed_config[ 'embedding_checkpoint_file']: # 上面说过模型转换的时候是有设置matlab文件路径的
  5. # Restore Siamese FC models from .mat model files # 这才是加载.mat model的函数
  6. initialize = load_mat_model(embed_config[ 'embedding_checkpoint_file'],
  7. 'convolutional_alexnet/', 'detection/')
  8. def restore_fn(sess): # 初始化方式,下面赋值给self.init_fn了
  9. tf.logging.info( "Restoring embedding variables from checkpoint file %s",
  10. embed_config[ 'embedding_checkpoint_file'])
  11. sess.run([initialize])
  12. self.init_fn = restore_fn

所以到这里,我们就真正进入到如何转换.mat为.ckpt文件了:

load_mat_model函数在utils/train_utils.py文件里,这里还是贴一下这个文件里的内容吧。


   
   
  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Copyright © 2017 bily Huazhong University of Science and Technology
  5. #
  6. # Distributed under terms of the MIT license.
  7. """Utilities for model construction"""
  8. from __future__ import absolute_import
  9. from __future__ import division
  10. from __future__ import print_function
  11. import re
  12. import numpy as np
  13. import tensorflow as tf
  14. from scipy import io as sio
  15. from utils.misc_utils import get_center
  16. # 在训练过程中构建groudtruth用到,用返回的结果和siamese网络得到的score map计算loss
  17. def construct_gt_score_maps(response_size, batch_size, stride, gt_config=None):
  18. """Construct a batch of groundtruth score maps
  19. Args:
  20. response_size: A list or tuple with two elements [ho, wo]
  21. batch_size: An integer e.g., 16
  22. stride: Embedding stride e.g., 8
  23. gt_config: Configurations for groundtruth generation
  24. Return:
  25. A float tensor of shape [batch_size] + response_size
  26. """
  27. with tf.name_scope( 'construct_gt'):
  28. ho = response_size[ 0]
  29. wo = response_size[ 1]
  30. y = tf.cast(tf.range( 0, ho), dtype=tf.float32) - get_center(ho)
  31. x = tf.cast(tf.range( 0, wo), dtype=tf.float32) - get_center(wo)
  32. [Y, X] = tf.meshgrid(y, x)
  33. def _logistic_label(X, Y, rPos, rNeg): # 构建一个高斯的二值groundtruth响应图
  34. # dist_to_center = tf.sqrt(tf.square(X) + tf.square(Y)) # L2 metric
  35. dist_to_center = tf.abs(X) + tf.abs(Y) # Block metric
  36. Z = tf.where(dist_to_center <= rPos,
  37. tf.ones_like(X),
  38. tf.where(dist_to_center < rNeg,
  39. 0.5 * tf.ones_like(X),
  40. tf.zeros_like(X)))
  41. return Z
  42. # 且先留意这里构建的groundtruth和siamese网络的stride有关
  43. rPos = gt_config[ 'rPos'] / stride
  44. rNeg = gt_config[ 'rNeg'] / stride
  45. gt = _logistic_label(X, Y, rPos, rNeg)
  46. # Duplicate a batch of maps
  47. gt_expand = tf.reshape(gt, [ 1] + response_size)
  48. gt = tf.tile(gt_expand, [batch_size, 1, 1])
  49. return gt
  50. # 从matlab模型文件存储路径读取模型参数
  51. def get_params_from_mat(matpath):
  52. """Get parameter from .mat file into parms(dict)"""
  53. def squeeze(vars_):
  54. # Matlab save some params with shape (*, 1)
  55. # However, we don't need the trailing dimension in TensorFlow.
  56. if isinstance(vars_, (list, tuple)):
  57. return [np.squeeze(v, 1) for v in vars_]
  58. else:
  59. return np.squeeze(vars_, 1)
  60. netparams = sio.loadmat(matpath)[ "net"][ "params"][ 0][ 0]
  61. params = dict() # 将模型数据以dict形式存储起来
  62. # 既然看到了这里,自己也不防单独将matlab模型加载起来,看看里面都是什么样的形式
  63. for i in range(netparams.size):
  64. param = netparams[ 0][i]
  65. name = param[ "name"][ 0]
  66. value = param[ "value"]
  67. value_size = param[ "value"].shape[ 0]
  68. match = re.match( r"([a-z]+)([0-9]+)([a-z]+)", name, re.I)
  69. if match:
  70. items = match.groups()
  71. elif name == 'adjust_f':
  72. params[ 'detection/weights'] = squeeze(value)
  73. continue
  74. elif name == 'adjust_b':
  75. params[ 'detection/biases'] = squeeze(value)
  76. continue
  77. else:
  78. raise Exception( 'unrecognized layer params')
  79. op, layer, types = items
  80. layer = int(layer)
  81. if layer in [ 1, 3]:
  82. if op == 'conv': # convolution
  83. if types == 'f':
  84. params[ 'conv%d/weights' % layer] = value
  85. elif types == 'b':
  86. value = squeeze(value)
  87. params[ 'conv%d/biases' % layer] = value
  88. elif op == 'bn': # batch normalization
  89. if types == 'x':
  90. m, v = squeeze(np.split(value, 2, 1))
  91. params[ 'conv%d/BatchNorm/moving_mean' % layer] = m
  92. params[ 'conv%d/BatchNorm/moving_variance' % layer] = np.square(v)
  93. elif types == 'm':
  94. value = squeeze(value)
  95. params[ 'conv%d/BatchNorm/gamma' % layer] = value
  96. elif types == 'b':
  97. value = squeeze(value)
  98. params[ 'conv%d/BatchNorm/beta' % layer] = value
  99. else:
  100. raise Exception
  101. elif layer in [ 2, 4]:
  102. if op == 'conv' and types == 'f':
  103. b1, b2 = np.split(value, 2, 3)
  104. else:
  105. b1, b2 = np.split(value, 2, 0)
  106. if op == 'conv':
  107. if types == 'f':
  108. params[ 'conv%d/b1/weights' % layer] = b1
  109. params[ 'conv%d/b2/weights' % layer] = b2
  110. elif types == 'b':
  111. b1, b2 = squeeze(np.split(value, 2, 0))
  112. params[ 'conv%d/b1/biases' % layer] = b1
  113. params[ 'conv%d/b2/biases' % layer] = b2
  114. elif op == 'bn':
  115. if types == 'x':
  116. m1, v1 = squeeze(np.split(b1, 2, 1))
  117. m2, v2 = squeeze(np.split(b2, 2, 1))
  118. params[ 'conv%d/b1/BatchNorm/moving_mean' % layer] = m1
  119. params[ 'conv%d/b2/BatchNorm/moving_mean' % layer] = m2
  120. params[ 'conv%d/b1/BatchNorm/moving_variance' % layer] = np.square(v1)
  121. params[ 'conv%d/b2/BatchNorm/moving_variance' % layer] = np.square(v2)
  122. elif types == 'm':
  123. params[ 'conv%d/b1/BatchNorm/gamma' % layer] = squeeze(b1)
  124. params[ 'conv%d/b2/BatchNorm/gamma' % layer] = squeeze(b2)
  125. elif types == 'b':
  126. params[ 'conv%d/b1/BatchNorm/beta' % layer] = squeeze(b1)
  127. params[ 'conv%d/b2/BatchNorm/beta' % layer] = squeeze(b2)
  128. else:
  129. raise Exception
  130. elif layer in [ 5]:
  131. if op == 'conv' and types == 'f':
  132. b1, b2 = np.split(value, 2, 3)
  133. else:
  134. b1, b2 = squeeze(np.split(value, 2, 0))
  135. assert op == 'conv', 'layer5 contains only convolution'
  136. if types == 'f':
  137. params[ 'conv%d/b1/weights' % layer] = b1
  138. params[ 'conv%d/b2/weights' % layer] = b2
  139. elif types == 'b':
  140. params[ 'conv%d/b1/biases' % layer] = b1
  141. params[ 'conv%d/b2/biases' % layer] = b2
  142. return params
  143. # .mat模型数据加载转换为.ckpt格式进行存储
  144. def load_mat_model(matpath, embed_scope, detection_scope=None):
  145. """Restore SiameseFC models from .mat model files"""
  146. params = get_params_from_mat(matpath)
  147. assign_ops = []
  148. def _assign(ref_name, params, scope=embed_scope):
  149. var_in_model = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES,
  150. scope + ref_name)[ 0]
  151. var_in_mat = params[ref_name]
  152. op = tf.assign(var_in_model, var_in_mat)
  153. assign_ops.append(op)
  154. for l in range( 1, 6):
  155. if l in [ 1, 3]:
  156. _assign( 'conv%d/weights' % l, params)
  157. # _assign('conv%d/biases' % l, params)
  158. _assign( 'conv%d/BatchNorm/beta' % l, params)
  159. _assign( 'conv%d/BatchNorm/gamma' % l, params)
  160. _assign( 'conv%d/BatchNorm/moving_mean' % l, params)
  161. _assign( 'conv%d/BatchNorm/moving_variance' % l, params)
  162. elif l in [ 2, 4]:
  163. # Branch 1
  164. _assign( 'conv%d/b1/weights' % l, params)
  165. # _assign('conv%d/b1/biases' % l, params)
  166. _assign( 'conv%d/b1/BatchNorm/beta' % l, params)
  167. _assign( 'conv%d/b1/BatchNorm/gamma' % l, params)
  168. _assign( 'conv%d/b1/BatchNorm/moving_mean' % l, params)
  169. _assign( 'conv%d/b1/BatchNorm/moving_variance' % l, params)
  170. # Branch 2
  171. _assign( 'conv%d/b2/weights' % l, params)
  172. # _assign('conv%d/b2/biases' % l, params)
  173. _assign( 'conv%d/b2/BatchNorm/beta' % l, params)
  174. _assign( 'conv%d/b2/BatchNorm/gamma' % l, params)
  175. _assign( 'conv%d/b2/BatchNorm/moving_mean' % l, params)
  176. _assign( 'conv%d/b2/BatchNorm/moving_variance' % l, params)
  177. elif l in [ 5]:
  178. # Branch 1
  179. _assign( 'conv%d/b1/weights' % l, params)
  180. _assign( 'conv%d/b1/biases' % l, params)
  181. # Branch 2
  182. _assign( 'conv%d/b2/weights' % l, params)
  183. _assign( 'conv%d/b2/biases' % l, params)
  184. else:
  185. raise Exception( 'layer number must below 5')
  186. if detection_scope:
  187. _assign(detection_scope + 'biases', params, scope= '')
  188. initialize = tf.group(*assign_ops)
  189. return initialize

上面代码中的一些语句的具体含义可以自己利用.mat数据慢慢体会,琢磨一会应该就ok了。

到此为止,我们的模型算是已经转换为.ckpt格式的了,按理说就可以用着个模型直接进行测试评估了,但在此之前,我们往往还需要做的一件事就是确定我们转换得到的.ckpt是没有问题的,进入下一节验证.ckpt没有问题之前把.mat格式的模型截个图看看长什么样,更具体的细节这里就不展开了。


2.3  模型转换验证

核心文件:tests/test_converted_model.py 

核心功能:输入同一张图片01.jpg,SiameseFC-TensorFlow代码加载.mat和转换后的.ckpt模型时运算得到01.jpg的feature map均和原作者matlab版本代码计算得到的feature map相同(差异及其的微小),如此一来既验证了网络设计没问题,同时也验证了.mat模型转换为.ckpt模型时没有问题。


   
   
  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Copyright © 2017 bily Huazhong University of Science and Technology
  5. #
  6. # Distributed under terms of the MIT license.
  7. """Tests for track model"""
  8. from __future__ import absolute_import
  9. from __future__ import division
  10. from __future__ import print_function
  11. import os.path as osp
  12. import sys
  13. import numpy as np
  14. import scipy.io as sio
  15. import tensorflow as tf
  16. from scipy.misc import imread # Only pillow 2.x is compatible with matlab 2016R
  17. CURRENT_DIR = osp.dirname(__file__)
  18. PARENT_DIR = osp.join(CURRENT_DIR, '..')
  19. sys.path.append(PARENT_DIR)
  20. import siamese_model
  21. import configuration
  22. from utils.misc_utils import load_cfgs
  23. # 直接通过model.init_fn加载.mat格式的模型数据计算01.jpg的feature map
  24. # 用这个feature map和作者matlab的结果
  25. def test_load_embedding_from_mat():
  26. """Test if the embedding model loaded from .mat
  27. produces the same features as the original MATLAB implementation"""
  28. matpath = osp.join(PARENT_DIR, 'assets/2016-08-17.net.mat')
  29. test_im = osp.join(CURRENT_DIR, '01.jpg')
  30. gt_feat = osp.join(CURRENT_DIR, 'result.mat')
  31. model_config = configuration.MODEL_CONFIG
  32. model_config[ 'embed_config'][ 'embedding_name'] = 'convolutional_alexnet'
  33. model_config[ 'embed_config'][ 'embedding_checkpoint_file'] = matpath # For SiameseFC
  34. model_config[ 'embed_config'][ 'train_embedding'] = False
  35. g = tf.Graph()
  36. with g.as_default():
  37. model = siamese_model.SiameseModel(model_config, configuration.TRAIN_CONFIG, mode= 'inference')
  38. model.build() # 模型的构建,这里不用深究,后续博客会细说
  39. with tf.Session() as sess:
  40. # Initialize models
  41. init = tf.global_variables_initializer()
  42. sess.run(init)
  43. # Load model here
  44. model.init_fn(sess)
  45. # Load image
  46. im = imread(test_im)
  47. im_batch = np.expand_dims(im, 0)
  48. # Feed image
  49. feature = sess.run([model.exemplar_embeds], feed_dict={model.examplar_feed: im_batch})
  50. # Compare with features computed from original source code
  51. ideal_feature = sio.loadmat(gt_feat)[ 'r'][ 'z_features'][ 0][ 0]
  52. diff = feature - ideal_feature
  53. diff = np.sqrt(np.mean(np.square(diff)))
  54. print( 'Feature computation difference: {}'.format(diff))
  55. print( 'You should get something like: 0.00892720464617')
  56. def test_load_embedding_from_converted_TF_model():
  57. """Test if the embedding model loaded from converted TensorFlow checkpoint
  58. produces the same features as the original implementation"""
  59. checkpoint = osp.join(PARENT_DIR, 'Logs/SiamFC/track_model_checkpoints/SiamFC-3s-color-pretrained')
  60. test_im = osp.join(CURRENT_DIR, '01.jpg')
  61. gt_feat = osp.join(CURRENT_DIR, 'result.mat')
  62. if not osp.exists(checkpoint):
  63. raise Exception( 'SiamFC-3s-color-pretrained is not generated yet.')
  64. model_config, train_config, track_config = load_cfgs(checkpoint)
  65. # Build the model
  66. g = tf.Graph()
  67. with g.as_default():
  68. model = siamese_model.SiameseModel(model_config, train_config, mode= 'inference')
  69. model.build()
  70. with tf.Session() as sess:
  71. # Load model here
  72. saver = tf.train.Saver(tf.global_variables())
  73. if osp.isdir(checkpoint):
  74. model_path = tf.train.latest_checkpoint(checkpoint)
  75. else:
  76. model_path = checkpoint
  77. saver.restore(sess, model_path)
  78. # Load image
  79. im = imread(test_im)
  80. im_batch = np.expand_dims(im, 0)
  81. # Feed image
  82. feature = sess.run([model.exemplar_embeds], feed_dict={model.examplar_feed: im_batch})
  83. # Compare with features computed from original source code
  84. ideal_feature = sio.loadmat(gt_feat)[ 'r'][ 'z_features'][ 0][ 0]
  85. diff = feature - ideal_feature
  86. diff = np.sqrt(np.mean(np.square(diff)))
  87. print( 'Feature computation difference: {}'.format(diff))
  88. print( 'You should get something like: 0.00892720464617')
  89. def test():
  90. test_load_embedding_from_mat()
  91. test_load_embedding_from_converted_TF_model()
  92. if __name__ == '__main__':
  93. test()

上面验证代码大体逻辑很清晰,至于模型构建的内容在此可以先跳过,后面再详细讲讲,下面是运行该测试脚本的结果截图,上面是.mat结果,下面是.ckpt结果,可以看到这两个结果是一样的:

2.4  用预训练模型在视频上进行测试

核心文件:scripts/run_tracking.py

核心功能:用预训练模型在新的视频上进行测试,视频是上面下载过测KiteSurf。

这份代码涉及到后面的视频测试,这里先只需要会用该脚本就好,你只要会到对应的log 路径下找到你对应视频测试的一些保存结果就好,因为这些结果都是后面可视化的数据,至于保存的数据是什么,保存数据的这个代码在哪个文件里后面自然会涉及到。


   
   
  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Copyright © 2017 bily Huazhong University of Science and Technology
  5. #
  6. # Distributed under terms of the MIT license.
  7. r"""Generate tracking results for videos using Siamese Model"""
  8. from __future__ import absolute_import
  9. from __future__ import division
  10. from __future__ import print_function
  11. import logging
  12. import os
  13. import os.path as osp
  14. import sys
  15. from glob import glob
  16. import tensorflow as tf
  17. from sacred import Experiment
  18. CURRENT_DIR = osp.dirname(__file__)
  19. sys.path.append(osp.join(CURRENT_DIR, '..'))
  20. from inference import inference_wrapper
  21. from inference.tracker import Tracker
  22. from utils.infer_utils import Rectangle
  23. from utils.misc_utils import auto_select_gpu, mkdir_p, sort_nicely, load_cfgs
  24. ex = Experiment()
  25. @ex.config # 模型和测试视频
  26. def configs():
  27. checkpoint = '/workspace/czx/Projects/SiamFC-TensorFlow/Logs/SiamFC/track_model_checkpoints/SiamFC-3s-color-pretrained'
  28. input_files = '/workspace/czx/Projects/SiamFC-TensorFlow/assets/KiteSurf'
  29. @ex.automain
  30. def main(checkpoint, input_files):
  31. os.environ[ 'CUDA_VISIBLE_DEVICES'] = auto_select_gpu()
  32. model_config, _, track_config = load_cfgs(checkpoint)
  33. track_config[ 'log_level'] = 1
  34. g = tf.Graph()
  35. with g.as_default(): # 模型测试时候需要构建的,且先不要深究
  36. model = inference_wrapper.InferenceWrapper()
  37. restore_fn = model.build_graph_from_config(model_config, track_config, checkpoint)
  38. g.finalize()
  39. # 这一块就是你存储测试视频结果数据的路径,记得去看看都有哪些数据。
  40. if not osp.isdir(track_config[ 'log_dir']):
  41. logging.info( 'Creating inference directory: %s', track_config[ 'log_dir'])
  42. mkdir_p(track_config[ 'log_dir'])
  43. video_dirs = []
  44. for file_pattern in input_files.split( ","):
  45. video_dirs.extend(glob(file_pattern))
  46. logging.info( "Running tracking on %d videos matching %s", len(video_dirs), input_files)
  47. gpu_options = tf.GPUOptions(allow_growth= True)
  48. sess_config = tf.ConfigProto(gpu_options=gpu_options)
  49. with tf.Session(graph=g, config=sess_config) as sess:
  50. restore_fn(sess)
  51. tracker = Tracker(model, model_config=model_config, track_config=track_config)
  52. for video_dir in video_dirs:
  53. if not osp.isdir(video_dir):
  54. logging.warning( '{} is not a directory, skipping...'.format(video_dir))
  55. continue
  56. video_name = osp.basename(video_dir)
  57. video_log_dir = osp.join(track_config[ 'log_dir'], video_name)
  58. mkdir_p(video_log_dir)
  59. filenames = sort_nicely(glob(video_dir + '/img/*.jpg'))
  60. first_line = open(video_dir + '/groundtruth_rect.txt').readline()
  61. bb = [int(v) for v in first_line.strip().split( ',')]
  62. init_bb = Rectangle(bb[ 0] - 1, bb[ 1] - 1, bb[ 2], bb[ 3]) # 0-index in python
  63. # 返回的跟踪结果
  64. trajectory = tracker.track(sess, init_bb, filenames, video_log_dir)
  65. with open(osp.join(video_log_dir, 'track_rect.txt'), 'w') as f:
  66. for region in trajectory:
  67. rect_str = '{},{},{},{}\n'.format(region.x + 1, region.y + 1,
  68. region.width, region.height)
  69. f.write(rect_str)

好了,你现在已经可以用预训练模型测试你想测试的视频了,接下来为了能更好地分析问题,将你测试的一些结果都进行可视化,在此之前还是瞧瞧咱们测试前后都有哪些数据输入和输出:

输入:解压缩之后的KiteSurf,包括了存在img文件夹中的图像数据和配置文件.cfg和groudtruth_rect.txt文件。



输出:每张图片跟踪到的目标的bbox和scale,以及每张图片的respones响应,还有crop出来的图片,最后呢就是像groundth_rect.txt一样的一个跟踪结果文件track_rect.txt。




2.5  视频测试结果可视化 

核心文件:scripts/show_tracking.py

核心功能:模型测试跟踪,这里也先只贴出文件内容,且先不深究。


   
   
  1. #! /usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Copyright © 2017 bily Huazhong University of Science and Technology
  5. #
  6. # Distributed under terms of the MIT license.
  7. import os.path as osp
  8. import sys
  9. from sacred import Experiment
  10. ex = Experiment()
  11. import numpy as np
  12. from matplotlib.pyplot import imread, Rectangle
  13. CURRENT_DIR = osp.abspath(osp.dirname(__file__))
  14. sys.path.append(osp.join(CURRENT_DIR, ".."))
  15. from utils.videofig import videofig
  16. def readbbox(file):
  17. with open(file, 'r') as f:
  18. lines = f.readlines()
  19. bboxs = [[float(val) for val in line.strip().replace( ' ', ',').replace( '\t', ',').split( ',')] for line in lines]
  20. return bboxs
  21. def create_bbox(bbox, color):
  22. return Rectangle((bbox[ 0], bbox[ 1]), bbox[ 2], bbox[ 3],
  23. fill= False, # remove background\n",
  24. edgecolor=color)
  25. def set_bbox(artist, bbox):
  26. artist.set_xy((bbox[ 0], bbox[ 1]))
  27. artist.set_width(bbox[ 2])
  28. artist.set_height(bbox[ 3])
  29. @ex.config
  30. def configs():
  31. videoname = 'KiteSurf'
  32. runname = 'SiamFC-3s-color-pretrained'
  33. data_dir = '/workspace/czx/Projects/SiamFC-TensorFlow/assets/'
  34. track_log_dir = '/workspace/czx/Projects/SiamFC-TensorFlow/Logs/SiamFC/track_model_inference/{}/{}'.format(runname, videoname)
  35. @ex.automain
  36. def main(videoname, data_dir, track_log_dir):
  37. track_log_dir = osp.join(track_log_dir)
  38. video_data_dir = osp.join(data_dir, videoname)
  39. te_bboxs = readbbox(osp.join(track_log_dir, 'track_rect.txt'))
  40. gt_bboxs = readbbox(osp.join(video_data_dir, 'groundtruth_rect.txt'))
  41. num_frames = len(gt_bboxs)
  42. def redraw_fn(ind, axes):
  43. ind += 1
  44. input_ = imread(osp.join(track_log_dir, 'image_cropped{}.jpg'.format(ind)))
  45. response = np.load(osp.join(track_log_dir, 'response{}.npy'.format(ind)))
  46. org_img = imread(osp.join(data_dir, videoname, 'img', '{:04d}.jpg'.format(ind + 1)))
  47. gt_bbox = gt_bboxs[ind]
  48. te_bbox = te_bboxs[ind]
  49. bbox = np.load(osp.join(track_log_dir, 'bbox{}.npy'.format(ind)))
  50. if not redraw_fn.initialized:
  51. ax1, ax2, ax3 = axes
  52. redraw_fn.im1 = ax1.imshow(input_)
  53. redraw_fn.im2 = ax2.imshow(response)
  54. redraw_fn.im3 = ax3.imshow(org_img)
  55. redraw_fn.bb1 = create_bbox(bbox, color= 'red')
  56. redraw_fn.bb2 = create_bbox(gt_bbox, color= 'green')
  57. redraw_fn.bb3 = create_bbox(te_bbox, color= 'red')
  58. ax1.add_patch(redraw_fn.bb1)
  59. ax3.add_patch(redraw_fn.bb2)
  60. ax3.add_patch(redraw_fn.bb3)
  61. redraw_fn.text = ax3.text( 0.03, 0.97, 'F:{}'.format(ind), fontdict={ 'size': 10, },
  62. ha= 'left', va= 'top',
  63. bbox={ 'facecolor': 'red', 'alpha': 0.7},
  64. transform=ax3.transAxes)
  65. redraw_fn.initialized = True
  66. else:
  67. redraw_fn.im1.set_array(input_)
  68. redraw_fn.im2.set_array(response)
  69. redraw_fn.im3.set_array(org_img)
  70. set_bbox(redraw_fn.bb1, bbox)
  71. set_bbox(redraw_fn.bb2, gt_bbox)
  72. set_bbox(redraw_fn.bb3, te_bbox)
  73. redraw_fn.text.set_text( 'F: {}'.format(ind))
  74. redraw_fn.initialized = False
  75. videofig(int(num_frames) - 1, redraw_fn,
  76. grid_specs={ 'nrows': 2, 'ncols': 2, 'wspace': 0, 'hspace': 0},
  77. layout_specs=[ '[0, 0]', '[0, 1]', '[1, :]'])
运行show_tracking.py脚本你应该就能得到这么一个视频,下面是两个截图,左上角是crop出来的图片,右上角是对应的响应图,下面是视频帧中原始的图片。



有了上面的一些可视化结果你就很方便进行下一步的分析了,比如上面两个图片中第一个中的响应比第二个要小很多,从crop的图片来看,很容易分析出人的侧脸且低头并有一定的运动模糊导致最后的响应偏低,对于其他视频也是可以如此分析的。如果你想测试其他的视频分析跟踪效果,可以去下载OTB100,VOT等数据集上的视频进行评估。

3:小结

1:这篇博客看到这里,你可以了解的有:

(1)预训练模型有哪些,如何下载;

(2)如何将.mat格式模型转换为.ckpt格式模型并大致知道模型里面都有哪些参数,如何验证转换是否正确;

(3)在不需要深入了解模型设计、训练、测试和评估的基础上 能够利用已有脚本对单个视频进行测试和可视化分析。

2:这篇博客只谈到了预训练模型的测试问题,那么接下来还会进一步介绍的有:

(1)数据预处理:如果要自己重新训练模型,用什么数据,又该如何进行预处理?

(2)模型设计:SiameseFC模型具体是什么样的?比如说网络结构是怎样的,Loss怎么构建等。

(3)模型训练:如何训练自己的模型?比如说数据怎么加载,怎么设置参数训练等。

(4)模型评估:单个视频测试的具体实现以及如何在OTB数据集上进行评估等。

3:好了,到这了呢基本上第一篇就写完了,代码贴的可能有点多,当然可能有很多疏漏的地方,欢迎指教和交流,我是认为这份代码是相当棒的,尤其是对于做跟踪的小伙伴而言,大家要是也这么觉得,那就点个Star吧,哈哈。



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值