图像匹配 | NCC 归一化互相关损失 | 代码 + 讲解
- 文章转载自:微信公众号「机器学习炼丹术」
- 作者:炼丹兄(已授权)
- 作者联系方式:微信cyx645016617(欢迎交流共同进步)
本次的内容主要讲解NCCNormalized cross-correlation 归一化互相关。
两张图片是否是同一个内容,现在深度学习的方案自然是用神经网络,比方说:孪生网络的架构做人面识别等等;
在传统的非参数方法中,常见的也有相关系数等。我在上一片文章voxelmorph的模型的学习中发现,在医学图像配准任务(不限于医学),衡量两个图片相似的度量有一种叫做NCC的
而这个NCC就是Normalized Cross-Correlation归一化互相关系数。
1 互相关系数
如果你知道互相关系数,那么你就能很好的理解归一化互相关系数。
相关系数的计算公式如下:
\]
公式中的X,Y分别表示两个图片,\(Cov(X,Y)\)表示两个图片的协方差,\(Var(X)\)表示X自身的方差;
2 归一化互相关NCC
如果把一张图片,按照一定的像素,比方说9x9的一个框滑动,那么就可以把图片分成很多的9x9的小图片,那么NCC就是X,Y两张大图片中的对应的小图片的互相关系数的平均值。
这里看一下协方差的计算方式:
\(Cov(X,Y) = E[(X-E(X))(Y-E(Y))]\)
方差的计算为:
\(Var(X) = E[(X-E(X))^2]\)
其实NCC不难理解,但是如何用代码计算呢?当然我们可以一行一行遍历求解,但是这样时间复杂度过高,所以我们做好还是选择矩阵运算。
3 NCC损失函数的代码
class NCC:
"""
Local (over window) normalized cross correlation loss.
"""
def __init__(self, win=None):
self.win = win
def loss(self, y_true, y_pred):
I = y_true
J = y_pred
# get dimension of volume
# assumes I, J are sized [batch_size, *vol_shape, nb_feats]
ndims = len(list(I.size())) - 2
assert ndims in [1, 2, 3], "volumes should be 1 to 3 dimensions. found: %d" % ndims
# set window size
win = [9] * ndims if self.win is None else self.win
# compute filters
sum_filt = torch.ones([1, 1, *win]).to("cuda")
pad_no = math.floor(win[0]/2)
if ndims == 1:
stride = (1)
padding = (pad_no)
elif ndims == 2:
stride = (1,1)
padding = (pad_no, pad_no)
else:
stride = (1,1,1)
padding = (pad_no, pad_no, pad_no)
# get convolution function
conv_fn = getattr(F, 'conv%dd' % ndims)
# compute CC squares
I2 = I * I
J2 = J * J
IJ = I * J
I_sum = conv_fn(I, sum_filt, stride=stride, padding=padding)
J_sum = conv_fn(J, sum_filt, stride=stride, padding=padding)
I2_sum = conv_fn(I2, sum_filt, stride=stride, padding=padding)
J2_sum = conv_fn(J2, sum_filt, stride=stride, padding=padding)
IJ_sum = conv_fn(IJ, sum_filt, stride=stride, padding=padding)
win_size = np.prod(win)
u_I = I_sum / win_size
u_J = J_sum / win_size
cross = IJ_sum - u_J * I_sum - u_I * J_sum + u_I * u_J * win_size
I_var = I2_sum - 2 * u_I * I_sum + u_I * u_I * win_size
J_var = J2_sum - 2 * u_J * J_sum + u_J * u_J * win_size
cc = cross * cross / (I_var * J_var + 1e-5)
return -torch.mean(cc)
这段代码其实不是很好看懂,我思考了很久才明白。其中的关键就在于如何理解:
# compute CC squares
I2 = I * I
J2 = J * J
IJ = I * J
I_sum = conv_fn(I, sum_filt, stride=stride, padding=padding)
J_sum = conv_fn(J, sum_filt, stride=stride, padding=padding)
I2_sum = conv_fn(I2, sum_filt, stride=stride, padding=padding)
J2_sum = conv_fn(J2, sum_filt, stride=stride, padding=padding)
IJ_sum = conv_fn(IJ, sum_filt, stride=stride, padding=padding)
win_size = np.prod(win)
u_I = I_sum / win_size
u_J = J_sum / win_size
cross = IJ_sum - u_J * I_sum - u_I * J_sum + u_I * u_J * win_size
I_var = I2_sum - 2 * u_I * I_sum + u_I * u_I * win_size
J_var = J2_sum - 2 * u_J * J_sum + u_J * u_J * win_size
我们可以才到,这个cross应该是协方差部分,I_var和J_var是方差部分。
我们对协方差公式进行推导:\(Cov(X,Y) = E[(X-E(X))(Y-E(Y))]\)
\(=E[XY-XE(Y)-YE(X)+E(X)E(Y)]\)
这样刚好和cross对应上。
- IJ_sum = E[XY]
- u_J * I_sum = E[XE(Y)]
- u_I * u_J * win_size = E[E(X)E(Y)]
对方差公式进行推导:\(Var(X) = E[(X-E(X))^2]=E[X^2-2XE(X)+E(X)^2]\)
- J2_sum = E(X^2)
- 2 * u_J * J_sum = E[2XE(X)]
- u_J * u_J * win_size = E[E(X)^2]
图像匹配 | NCC 归一化互相关损失 | 代码 + 讲解的更多相关文章
- 第二章--Win32程序运行原理 (部分概念及代码讲解)
学习<Windows程序设计>记录 概念贴士: 1. 每个进程都有赋予它自己的私有地址空间.当进程内的线程运行时,该线程仅仅能够访问属于它的进程的内存,而属于其他进程的内存被屏蔽了起来,不 ...
- 『HTML5实现人工智能』小游戏《井字棋》发布,据说IQ上200才能赢【算法&代码讲解+资源打包下载】
一,什么是TicTacToe(井字棋) 本游戏为在下用lufylegend开发的第二款小游戏.此游戏是大家想必大家小时候都玩过,因为玩它很简单,只需要一张草稿纸和一只笔就能开始游戏,所以广受儿童欢迎. ...
- Java生鲜电商平台-生鲜电商高并发下的接口幂等性实现与代码讲解
Java生鲜电商平台-生鲜电商高并发下的接口幂等性实现与代码讲解 说明:Java生鲜电商平台-生鲜电商高并发下的接口幂等性实现与代码讲解,实际系统中有很多操作,是不管做多少次,都应该产生一样的效果或返 ...
- faster RCNN(keras版本)代码讲解(3)-训练流程详情
转载:https://blog.csdn.net/u011311291/article/details/81121519 https://blog.csdn.net/qq_34564612/artic ...
- 毕业设计java实验室预约管理系统SSH机房预约系统javaweb机房实验室排课系统mysql机房管理系统 实验室管理系统 课程设计 代码讲解 调试运行
毕业设计java实验室预约管理系统SSH机房预约系统javaweb机房实验室排课系统mysql机房管理系统 实验室管理系统 课程设计 代码讲解 调试运行 注意:该项目只展示部分功能,如需了解,评论区咨 ...
- 双目立体匹配——归一化互相关(NCC)
归一化相关性,normalization cross-correlation,因此简称NCC,下文中笔者将用NCC来代替这冗长的名称. NCC,顾名思义,就是用于归一化待匹配目标之间的相关程度,注意这 ...
- CUDA学习,第一个kernel函数及代码讲解
前一篇CUDA学习,我们已经完成了编程环境的配置,现在我们继续深入去了解CUDA编程.本博文分为三个部分,第一部分给出一个代码示例,第二部分对代码进行讲解,第三部分根据这个例子介绍如何部署和发起一个k ...
- 李宏毅 Gradient Descent Demo 代码讲解
何为梯度下降,直白点就是,链式求导法则,不断更新变量值. 这里讲解的代码为李宏毅老师机器学习课程中 class 4 回归展示 中的代码demo Loss函数 python代码如下 import n ...
- Widget代码讲解
参考:https://zhuanlan.zhihu.com/p/28225011 QT版本为5.12.4 1.main.cpp #include "widget.h" #inclu ...
随机推荐
- Spring Cloud Alibaba+Nacos搭建微服务架构
1. Spring Cloud Alibaba 简介 Spring Cloud Alibaba是阿里巴巴为分布式应用提供的一站式解决方案,能够更方便快捷地搭建分布式平台,nacos拥有着替换eu ...
- reStructuredText(.rst) && read the docs
Read the Docs && reStructuredText (.rst) && markdown 1. github master 分支,创建 docs ...
- holy shit StackOverflow
holy shit StackOverflow refs https://stackoverflow.com/users/5934465/xgqfrms?tab=questions xgqfrms 2 ...
- Linux & SIGUSER1
Linux & SIGUSER1 https://stackoverflow.com/questions/10824886/how-to-signal-an-application-witho ...
- Flutter使用WebSockets
文档 注意是WebSockets而不是socket.io install dependencies: web_socket_channel: demo import 'dart:convert'; i ...
- PAUL ADAMS ARCHITECT LTD:拜登上台后,美国房地产走势如何?
受全球经济危机影响,美国经济的复苏之路并不平坦,然而住宅房地产市场却是少数的例外,表现得非常亮眼.而随着美国拜登总统上台的临近,美国房产市场还会持续当前的发展吗?对于这个问题,近日,美国知名房地产公司 ...
- 为什么说NGK公链的商用落地是可行的?
互联网.大数据以及云计算的发展给人们的生活.工作带来了诸多便利,也让人们一次又一次感叹科技的进步.而NGK公链的诞生,更是让众人称之为传奇.其商用落地可行性,也让人惊叹.那么,为什么说NGK公链的商用 ...
- pycharm + git+gitlab的可视化界面操作
前言: 写这篇博客,主要为了记录一套经过本人实践,并运行通过的操作gitlab流程. 通过以下步骤,可实现最基本的远程服务器(gitlab)和本地工具(pycharm)的,针对两端文件增删改查的及 ...
- Python 爬虫使用动态切换ip防止封杀
对于爬虫被封禁 ! 爬虫一般来说只要你的ip够多,是不容易被封的. 一些中小网站要封杀你,他的技术成本也是很高的,因为大多数网站没有vps,他们用的是虚拟空间或者是sae,bae这样的paas云. 其 ...
- 09_MySQL数据库的索引机制
CREATE TABLE t_message( id INT UNSIGNED PRIMARY KEY, content VARCHAR(200) NOT NULL, type ENUM(" ...