siamfc论文:Fully-Convolutional Siamese Networks for Object Tracking

gitHub代码:https://github.com/huanglianghua/siamfc-pytorch

论文模型架构:

在此文章中将以代码+注释的形式详解推理过程,即test.py中的代码。
后续有空将会详解训练过程即train.py的代码。

推理大致流程代码阅读顺序:

|—test.py
|——TrackerSiamFC类
|———初始SiamFC超参
|———Net
|————BackBone
|————head*
|————Loss(BalancedLoss,测试的时候不会使用)
|————Optimizer(SGD)
|————Lr
|——ExperimentOTB类
|———OTB类(继承Object)
|——run函数
|——eport函数(结果)

代码流程

test.py:
首先看到trackerSiamFC类(test.py --Line15)
crtl+左键点进去,进入到siamfc.py中

TrackerSiamFC类中init函数:

代码详解(注释)
过程简述:

  1. 超参初始化
  2. 创建siamfc架构;
  3. 模型加载;
  4. 定义损失函数(BalancedLoss,测试的时候不会使用);
  5. SGD优化器;
  6. 获得指数衰减学习率因子函数:ExponentialLR

回到test.py中,看到ExperimentOTB类(test.py --Line19)
crtl+左键点进去。进入到experiments\otb.py中

ExperimentOTB类中init函数:

这是Siamfc作者定义的一个类,方便使用OTB10K数据集。
init()中:

  1. 首先用OTB类初始化好数据集
  2. 初始化结果路径

补充:OTB类代码详解(注释)

回到test.py中,看到run函数(test.py --Line20),crtl+左键点进去。

experiments/otb.py下run函数

代码详解(注释)
过程简述:

通过for循环遍历dataset
并执行如下操作:

  1. 创建输出结果.txt(如果不存在的话)
  2. 进行推理 (最重要)
  3. 结果保存

当前函数中看到tracker.track(experiments/otb.py—Line55)
这是最关键的一步,点进去,进入到siamfc.py下的track函数

siamfc.py下track函数

代码详解(注释)
过程简述:

  1. 获得第一个框(目标框的参数)
  2. 如果是第一帧,进行推理初始化(init函数)
  3. 如果是非第一帧,进行正常推理(update函数)
  4. 结果框的显示

如果是第一帧,跳转进入到Init函数(siamfc.py --Line299):

siamfc.py下init函数:

代码详解(注释)
过程简述:

  1. 获得第一帧图片的annontation值
  2. 初始化裁剪图片的中心点坐标 (self.center)
  3. 初始化最终目标框图片大小 (self.target)
  4. 初始化响应图进行上采样后的大小(即 17*16==272)
  5. 初始化汉宁窗
  6. 初始化裁剪图的缩放因子
  7. 初始化裁剪z图片和x图片的大小
  8. 初始化feature_z并固定

如果非第一帧,跳转进入到update函数(siamfc.py --Line301):

siamfc.py下update函数:

代码详解(注释)
过程简述:

  1. 通过Crop_and_resize函数来获得不同尺度下的搜索图片大小
  2. 通过backbone获得feature_x;进而获得响应图response
  3. 上采样response为了后续计算中心偏差和图片大小偏差
  4. 获得最优响应图对应id(index)
  5. 计算中心偏差和图片大小偏差
  6. 修改下一帧的中心偏差和图片大小偏差
  7. 返回Box值,用于后续可显示化

————————————————————————————————————

代码解析:

TrackerSiamFC类init函数

额外补充:
self.parse_args函数
head=SiamFC()函数
BalancedLoss()类,测试的时候不会使用
ExponentialLR()类

class TrackerSiamFC(Tracker):def __init__(self, net_path=None, **kwargs):super(TrackerSiamFC, self).__init__('SiamFC', True)self.cfg = self.parse_args(**kwargs)##超参数的定义# setup GPU device if availableself.cuda = torch.cuda.is_available()self.device = torch.device('cuda:0' if self.cuda else 'cpu')# setup modelself.net = Net(backbone=AlexNetV1(),        ##特征提取层,在此不做赘述head=SiamFC(self.cfg.out_scale))##头处理,详看补充代码解析(注释)ops.init_weights(self.net)# load checkpoint if providedif net_path is not None:self.net.load_state_dict(torch.load(net_path, map_location=lambda storage, loc: storage))self.net = self.net.to(self.device)# setup criterionself.criterion = BalancedLoss()##定义损失函数,详看补充代码解析(注释)# setup optimizerself.optimizer = optim.SGD(self.net.parameters(),lr=self.cfg.initial_lr,weight_decay=self.cfg.weight_decay,momentum=self.cfg.momentum)# setup lr schedulergamma = np.power(self.cfg.ultimate_lr / self.cfg.initial_lr,1.0 / self.cfg.epoch_num)self.lr_scheduler = ExponentialLR(self.optimizer, gamma)##指数衰减学习率, 详看补充代码解析(注释)## lr=lr*gamma**epoch
run函数

otb.py下run函数 (otb.py---Line38)

    def run(self, tracker, visualize=False):print('Running tracker %s on %s...' % (tracker.name, type(self.dataset).__name__))# loop over the complete datasetfor s, (img_files, anno) in enumerate(self.dataset): ## img_files是list ,保存的是dataset中某一子文件夹中的所有图片路径##anno 是list ,保存的是dataset中某一子文件夹中的groundtruth路径seq_name = self.dataset.seq_names[s] ##取第s批数据print('--Sequence %d/%d: %s' % (s + 1, len(self.dataset), seq_name))# skip if results existrecord_file = os.path.join(self.result_dir, tracker.name, '%s.txt' % seq_name)if os.path.exists(record_file):print('  Found results, skipping', seq_name)continue# tracking loopboxes, times = tracker.track(       ##最重要部分img_files, anno[0, :], visualize=visualize)assert len(boxes) == len(anno)"""img_files: 保存的是一个文件夹下所有图片的路径anno[0, :]: 第一张图片的annotation值;目标框的annnotation值(因为siamfc始终实以第一帧图片作为目标框)visualize: 结果的可视化"""# record resultsself._record(record_file, boxes, times)
track函数

siamfc.py下track函数 (.siamfc.py---Line287)

    def track(self, img_files, box, visualize=False):##box: 第一帧,在siamfc中是要跟踪的物体,且后续不会发生变化frame_num = len(img_files)       ##总帧数boxes = np.zeros((frame_num, 4)) ##准备预测所有框的参数boxes[0] = box                   ##获得第一个框(目标框的参数)times = np.zeros(frame_num)      ## 时间,用于后续计算fpsfor f, img_file in enumerate(img_files):img = ops.read_image(img_file) ##img_file 这里传入的是一个img路径begin = time.time()if f == 0:          ##第一帧self.init(img, box)##初始化了很多参数,并固定feature_z 并作为后续的卷积核else:##不过不是第一帧boxes[f, :] = self.update(img)  ##重要函数,实际推理过程times[f] = time.time() - begin##耗时if visualize:ops.show_image(img, boxes[f, :])return boxes, times
init函数

siamfc.py下init函数:(siamfc.py---Line116)

额外补充:crop_and_resize函数

    def init(self, img, box):# set to evaluation modeself.net.eval()##评估模式# convert box to 0-indexed and center based [y, x, h, w]box = np.array([  ##点转换box[1] - 1 + (box[3] - 1) / 2,box[0] - 1 + (box[2] - 1) / 2,box[3], box[2]], dtype=np.float32)self.center, self.target_sz = box[:2], box[2:] ##lefr,up,h,w--->center_y,center_x,h,w# create hanning windowself.upscale_sz = self.cfg.response_up * self.cfg.response_sz##reponse_sz==17 (对应论文)   ##response_up : 将最后的响应图上采样的倍率 这里是16##响应图上采样后的大小: upscale_sz==272self.hann_window = np.outer(np.hanning(self.upscale_sz),np.hanning(self.upscale_sz))self.hann_window /= self.hann_window.sum()  ##汉宁窗的创建  ##汉宁窗结果是越靠近中心,值越大##在这里主要是为了抑制边缘特征,突出中心# search scale factorsself.scale_factors = self.cfg.scale_step ** np.linspace(-(self.cfg.scale_num // 2),self.cfg.scale_num // 2, self.cfg.scale_num)##截取  搜索框框图片时不同的缩放因子##当 scale_num==3 and  scale_step==1.3075   ##则sacle_factos的值为:[0.9638  1  1.0375]##获得裁剪图片大小# exemplar and search sizescontext = self.cfg.context * np.sum(self.target_sz)##self.cfg.context==0.5self.z_sz = np.sqrt(np.prod(self.target_sz + context))##目标框(Z)图片裁剪的宽和高##np.prob 表示内积: 即 w*hself.x_sz = self.z_sz * \self.cfg.instance_sz / self.cfg.exemplar_sz  ###乘以 255/127  获得搜索框框(x)图片裁剪的宽和高##x,sz 一般为 220左右# exemplar imageself.avg_color = np.mean(img, axis=(0, 1))  ##原始图片img##三通道求均值,用于后续填充使用z = ops.crop_and_resize(img, self.center, self.z_sz,out_size=self.cfg.exemplar_sz,border_value=self.avg_color)##中心,按照 z_sz大小裁剪,并resize到 emamplar_sz# exemplar featuresz = torch.from_numpy(z).to(self.device).permute(2, 0, 1).unsqueeze(0).float()self.kernel = self.net.backbone(z) ##卷积kernel====feature_z (目标框特征), 放到init函数中代表后续的卷积核不会改变(因为在推理过程)
update函数

siamfc.py下update函数 (./siamfc.py---Line172)

    def update(self, img): ##非第一帧,要进行实际预测# set to evaluation modeself.net.eval()# search imagesx = [ops.crop_and_resize(img, self.center, size=self.x_sz * f,  ##第二帧时,self.center 为第一帧的中心out_size=self.cfg.instance_sz,border_value=self.avg_color) for f in self.scale_factors]##通过 len (scale_factors)个尺度,获得不同的 img_xx = np.stack(x, axis=0) #堆叠##X.shape=B,W,H,C  ## B==len(scale_factors)x = torch.from_numpy(x).to(self.device).permute(0, 3, 1, 2).float()##B,W,H,C-->B,C,W,H# 获得相应图responsesx = self.net.backbone(x) ## feature_xresponses = self.net.head(self.kernel, x)   ##得到相应图 responseresponses = responses.squeeze(1).cpu().numpy()####N,1,W,H--->N,W,H# upsample responses and penalize scale changesresponses = np.stack([cv2.resize(u, (self.upscale_sz, self.upscale_sz),interpolation=cv2.INTER_CUBIC)for u in responses])##上采样缩放图##resspnses.shape:N,1,272,272"""对发生形变的图片对应的响应图进行惩罚如果self.cfg.scale_num ==3对第一张和第三张图片进行尺度惩罚,因为除了第二张,其他图片都发生了形变(乘了 self.sacle_factor)中间图片不进行缩放尺度惩罚"""responses[:self.cfg.scale_num // 2]     *= self.cfg.scale_penaltyresponses[self.cfg.scale_num // 2 + 1:] *= self.cfg.scale_penalty##PS: cfg.scale_penalty:0.9745# peak scalescale_id = np.argmax(np.amax(responses, axis=(1, 2)))  ##获得最好的响应图对应的下标###np.amax(responses, axis=(1, 2)): 每个响应图的 峰值##返回这些峰值中最大的下标# peak locationresponse = responses[scale_id]  ##获得最好的响应图情况response -= response.min()response /= response.sum() + 1e-16#归一化response = (1 - self.cfg.window_influence) * response + \self.cfg.window_influence * self.hann_window        ##余弦窗惩罚"""self.cfg.window_influence:0.176尺度惩罚因子,超参数           """loc = np.unravel_index(response.argmax(), response.shape) ## 获得实际的中心点坐标,在siamfc中默认最大值为图片中心的"""np.unravel_index函数: 返回 响应图峰值下标(index)在shape下对应的坐标点e.g.loc=np.unravel_index(20,(5,5)) ##loc===(4,0)"""# locate target centerdisp_in_response = np.array(loc) - (self.upscale_sz - 1) / 2 ##实际中心点坐标减去  上采样后的response的中心;;;这里获得偏移误差## 272图片大小中, 中心点的偏移误差disp_in_instance = disp_in_response * \self.cfg.total_stride / self.cfg.response_up###total_stride==8disp_in_image = disp_in_instance * self.x_sz * \self.scale_factors[scale_id] / self.cfg.instance_sz##e.g. self.x_sz约为220  self.cfg.instance_sz==255## 转移到 127图片大小中, 中心点的偏移误差self.center += disp_in_image    ## 修改下一预测框的中心 ##这里的center尺度是127*127 图片大小的# update target sizescale =  (1 - self.cfg.scale_lr) * 1.0 + \self.cfg.scale_lr * self.scale_factors[scale_id]   ## 按权重修改  图片缩放比例##形似 (1-a) * scale1 + a * scale2## 1- a: 原图缩放比占的比率,## 1.0 :相对于原图的缩放比率,1.0表示维持当前情况## scale_factors[sacle_id] : 最优 响应图 对应的缩放比率##self.target_sz *= scale  ##下一预测框的大小要改变self.z_sz *= scale  ##Z的剪切大小  * 优化缩放比例self.x_sz *= scale  ##X的剪切大小  * 优化缩放比例# return 1-indexed and left-top based bounding boxbox = np.array([self.center[1] + 1 - (self.target_sz[1] - 1) / 2,self.center[0] + 1 - (self.target_sz[0] - 1) / 2,self.target_sz[1], self.target_sz[0]])##得到:left right w,hreturn box  ##预测的结果框

————————————————————————————————————

额外补充:

parse_args函数

parse_args函数 TrackerSiamFC类下parse_args函数 (siamfc.py---Line82) 功能:定义一些超参数(固定,推理时用到,训练时用到)

cfg = {# basic parameters'out_scale': 0.001, ##获得响应图后对整体结果进行sacle缩放'exemplar_sz': 127, ## 默认目标图像X的大小'instance_sz': 255, ## 默认搜索图像Z的大小'context': 0.5,     ## 后续做图像切割使用# inference parameters'scale_num': 3,     ##推理过程中,候选尺度窗的个数'scale_step': 1.0375, ##最大候选尺度窗相对于上一帧的缩放因子'scale_lr': 0.59,     ##'scale_penalty': 0.9745, ## 惩罚项因子'window_influence': 0.176, ##'response_sz': 17,  ##最终得到响应图的大小'response_up': 16,  ## 响应图上采样的倍率    16*17=272'total_stride': 8,# train parameters'epoch_num': 50,'batch_size': 8,'num_workers': 32,'initial_lr': 1e-2,   ##初始lr'ultimate_lr': 1e-5,  ##最终Lr'weight_decay': 5e-4,'momentum': 0.9,      ##SGD'r_pos': 16,          ## 两个用来构造训练时的 label'r_neg': 0}           ## 两个用来构造训练时的 labelfor key, val in kwargs.items():if key in cfg:cfg.update({key: val})return namedtuple('Config', cfg.keys())(**cfg)
SiamFC类

.heads.py

class SiamFC(nn.Module):def __init__(self, out_scale=0.001):super(SiamFC, self).__init__()self.out_scale = out_scaledef forward(self, z, x):return self._fast_xcorr(z, x) * self.out_scaledef _fast_xcorr(self, z, x): ##互相关操作# fast cross correlationnz = z.size(0)          ##z.shape==Batch*1,128,h_z,w_z (B*1,128,6,6)nx, c, h, w = x.size()  ##x.shape==Batch*3,128,h_x,w_x (B*3,128,22,22)##一般来说nx=B*   3(等于len(self.arg.scale_num))x = x.view(-1, nz * c, h, w) ##3,128*B,22,22out = F.conv2d(x, z, groups=nz)##:x.shape==3,128*B,22,22  ,z.shape==B*1,128,6,6 ,groups=B##得到结果Out.shape==3,B,17,17out = out.view(nx, -1, out.size(-2), out.size(-1))##最后out shape:[B*nx, 1, 17,17]return out

其中F.conv2d(x, z, groups=nz)是组卷积
x.shape=3,128×B,22,22 ,z.shape=B×1,128,6,6 ,groups=B
首先考虑输出的size = (W − F + 2P )/S+1(W=22,F=6,P=0,S=1)
即size=17
组卷积步骤:

  1. 将x按照通道数(axis=2)划分B个,会将z按照batch(axis=3)划分B个。每个子x.shape为3,128,22,22,每个子z.shape为1,128,6,6。
  2. 每个子z与与子x(卷积核)进行卷积,得到子输出out.shape为3,1,17,17。
  3. 共进行groups=B次卷积,并按照通道数(axis=3)堆叠。即最终输出out.shape为3,B,17,17。
OTB类

/datasets/otb.py---Line72

简述:
init中,会将所有图片的路径和文件夹里面的groundtruth.txt的路径保存到List里面,方便后续调用
代码解析(注释):

 def __init__(self, root_dir, version=2015, download=True):super(OTB, self).__init__()assert version in self.__version_dict##...##...##...self.seq_dirs = [os.path.dirname(f) for f in self.anno_files] ##保存所有文件夹中groundtruth.txt路径self.seq_names = [os.path.basename(d) for d in self.seq_dirs] ##保存所有文件夹中图片路径# rename repeated sequence names# (e.g., Jogging and Skating2)self.seq_names = self._rename_seqs(self.seq_names)
crop_and_resize函数

.ops.py—Line92
参数:

def     crop_and_resize(img,
center,                             ##裁剪中心
size,                               ##裁剪大小
out_size,                           ##最后输出大小
border_type=cv2.BORDER_CONSTANT,    ##边缘填充方式:固定值填充
border_value=(0, 0, 0),            ##默认固定值填充;;本文中是取每个通道均值
interp=cv2.INTER_LINEAR):          ##resize是的方法:线性插值法

功能:在center位置剪切size大小图片并且缩放到output_size大小

代码解析(注释):

def     crop_and_resize(img, center, size, out_size,border_type=cv2.BORDER_CONSTANT,border_value=(0, 0, 0),interp=cv2.INTER_LINEAR):# convert box to corners (0-indexed)size = round(size)##center[0]==center_x##center[1]==center_ycorners = np.concatenate((np.round(center - (size - 1) / 2),np.round(center - (size - 1) / 2) + size))corners = np.round(corners).astype(int)##corners[0]==[left,up] ##左上顶点##corners[1]==[right,down] ##右下顶点# pad image if necessarypads = np.concatenate((-corners[:2], corners[2:] - img.shape[:2]))npad = max(0, int(pads.max())) ##如果要裁剪的大小超出图像大小,则会进行pad ,##一般情况下不会发生这种情况, 则npad==0if npad > 0:img = cv2.copyMakeBorder(img, npad, npad, npad, npad,border_type, value=border_value)# crop image patchcorners = (corners + npad).astype(int)   ##一般情况下 npad==0patch = img[corners[0]:corners[2], corners[1]:corners[3]] #截断操作,left:right,   up:down  图片裁剪# resize to out_sizepatch = cv2.resize(patch, (out_size, out_size),interpolation=interp) ##resizereturn patch
BalancedLoss类,测试的时候不会使用

.losses.py—Line27 (该py文件下还有其他的损失函数,感兴趣可以自行查阅)
功能:通过看最后一行,可以发现就是(binary_cross_entropy)交叉熵损失函数,只不过多了一个weight权重,用于平衡计算最终loss。
代码解析(注释):

class BalancedLoss(nn.Module):def __init__(self, neg_weight=1.0):super(BalancedLoss, self).__init__()self.neg_weight = neg_weightdef forward(self, input, target):"""##测试的时候不会用到,训练时:##target是0和1 矩阵,shape==(1,15,15) ##(至于为什么不是论文中的1,17,17,主要原因是预处理时,x.shape=B,C,239,239;;详情看训练时代码解析的博客)"""pos_mask = (target == 1) #获得target中 1(正样本)对应的下标neg_mask = (target == 0) #获得target中 0(负样本)对应的下标pos_num = pos_mask.sum().float()#获得1的总数neg_num = neg_mask.sum().float()#获得0的总数weight = target.new_zeros(target.size())weight[pos_mask] = 1 / pos_num#接着生成weight矩阵, 其中正样本对应下标的值为1/正样本总数weight[neg_mask] = 1 / neg_num * self.neg_weight#同理,负样本对应下标的值为1/负样本总数*权重比(超参数)weight /= weight.sum()#weight归一化return F.binary_cross_entropy_with_logits(input, target, weight, reduction='sum')
ExponentialLR类

网上一查便知公式,在此不做详细解析。 [学习率衰减策略 ](https://zhuanlan.zhihu.com/p/475824165)

学习率计算公式: lr = lr * gamma^epoch

欢迎指正

因为本文主要是本人用来做的笔记,顺便进行知识巩固。如果本文对你有所帮助,那么本博客的目的就已经超额完成了。
本人英语水平、阅读论文能力、读写代码能力较为有限。有错误,恳请大佬指正,感谢。

欢迎交流
邮箱:refreshmentccoffee@gmail.com

SiamFC代码讲解,推理测试讲解相关推荐

  1. 在html语言中建立网页链接,HTML代码实例:详细讲解超级链接

    HTML代码实例:详细讲解超级链接 互联网   发布时间:2009-04-02 20:55:27   作者:佚名   我要评论 超级链接是网站中使用比较频繁的HTML元素,因为网站的各种页面都是由超级 ...

  2. java 代码块的作用_4种Java代码块的作用讲解

    4种Java代码块的作用讲解 时间:2017-06-28     来源:华清远见JAVA学院 今天华清Java学院小编要和大家分享的是Java代码块的作用,代码块是一种常见的代码形式,他用大括号&qu ...

  3. 测试http请求的Chrome插件:Postman插件的查找安装模拟测试 - 讲解篇

    一个测试http请求的Chrome插件:Postman 本文简述一下这个Chrome插件:Postman插件的查找.下载.安装. 这里需要合法的VPN服务商,具体原因你懂的. Chrome资源查找下载 ...

  4. 强化学习代码实操和讲解(三)

    强化学习代码实操和讲解(三) 引言 杰克租车问题 重点代码解析 环境设置 poisson_probability:泊松概率的计算 expected_return:根据给定策略进行策略评估 figure ...

  5. 双麦降噪回音消除芯片-NR2047技术讲解和测试视频

    NR-2047芯片技术讲解和测试视频,请点击收看 兼具双工免提通话消回音(AEC)及环境噪音压制(ENC)的 语音处理芯片 NR2047 一, 概述 NR2047 是一款强效的多功能语音及音频 DSP ...

  6. 模糊推理 控制 易于实现_代码“易于推理”是什么意思?

    模糊推理 控制 易于实现 by Preethi Kasireddy 通过Preethi Kasireddy 代码"易于推理"是什么意思? (What does it mean wh ...

  7. 【网页制作】CSS文本和字体属性讲解【附讲解视频】

    1.CSS文本和字体属性的作用:给文本和字体设置样式(具体看第二部分) 注意:在html中我们可以省略单位,但CSS中不可以省略单位. 简单的说大多数情况在html的body标签中我们可以省略单位,但 ...

  8. SiamFC代码配置复现 matlab版本

    原创 SiamFC代码配置复现 2019-04-29 22:18:06 ZZXin_ 阅读数 1603更多 分类专栏: 深度学习 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议 ...

  9. SiamFC代码大乱炖 (pytorch)

    写前bb 最早是看了matlab的代码,搭了环境,demo也跑了,就再也没碰过了.之后想自己把测试和训练部分全部跑通,找了个用pytorch写的代码,看的过程中发现自己还是很多细节部分不是很清楚.虽然 ...

  10. Oracle11g全新讲解之SQL讲解

    SQL操作和查询 一.SQL简介   SQL是结构化查询语言(Structured Query Language),专门用于数据存取.数据更新及数据库管理等操作.   在Oracle开发中,客户端把S ...

最新文章

  1. VR技术怎么落地,行业应用怎么挖掘,来江苏虚拟现实发展大会侃侃
  2. 【ZooKeeper Notes 9】ZooKeepr日志清理
  3. internetreadfile读取数据长度为0_Datax3.0的安装和基本使用
  4. 计算机工程毕业论文任务书,(计算机工程毕业设计论文任务书开题报告模板.doc...
  5. 使用java解析XML文件的步骤
  6. ps -ef |grep -v 在shell sh 脚本中貌似无效?
  7. mysql查询选课最少成绩最高_MySQL 练习
  8. Structure of a Task
  9. linux 下nm命令输出,Linux nm命令介绍
  10. 卡西欧手表城市编码,调时区用
  11. 软考中常见的英文缩写
  12. 电脑调节,电脑调节亮度怎么调
  13. 前端基础学习-element-ui表格表头做成斜线表头
  14. 阡陌路 - 自动档车的开法(转)
  15. openocd Win10安装jlink->winUSB失败
  16. gfp 通用成帧程序 帧结构 校验 crc 多项式 加扰
  17. 关于cv2.cvtColor(im, cv2.COLOR_RGB2BGR)的一点细节
  18. 抽象类和抽象方法 abstract类和abstract方法
  19. 七牛云上传资源和拉取
  20. 截屏工具、录屏工具不能用?是因为这个!!

热门文章

  1. 计算机考研数学一大纲2016,2016年计算机考研大纲原文
  2. java 规范 阿里巴巴_阿里巴巴 Java 代码规范
  3. 如何用文件对比工具进行文件内容比较
  4. inode对接微软服务器,H3C iNode智能客户端安装指导(Windows)-7.3-5PW102
  5. 计算机复试不机试的学校,计算机考研复试:计算机考研复试不考机试的高校
  6. Pytorch Note19 优化算法5 Adadelta算法
  7. GAMP|Visual Studio 2019环境下配置GAMP
  8. java算法面试题_Java算法面试题汇总
  9. docker搭建pgadmin并挂载
  10. html中div圆角效果,div+css实现圆角即网页上常用的圆角效果