计算机视觉(四)
计算机视觉中的图像到图像映射下半部分涵盖了多个关键技术和方法:
RANSAC(随机一致性采样)是一种用于描述正确模型以拟合带噪声数据的迭代方法,在单应性估计中广泛使用。
图像配准通过提取特征点(如SIFT),匹配并筛选特征对(使用RANSAC剔除非正确点),然后通过DLT算法估计全局单应性矩阵完成配准。
图割方法基于最大流最小割理论,在图像分割和修复中被用来解决复杂问题。
图像融合通过multi-band blending算法消除拼接缝中的不自然过渡效果,在高动态范围 imaging中应用广泛。
APAP算法通过网格划分和局部单应性计算解决拼接后的“鬼影现象”,提高了结果质量。
6.multi-band blending结合拉普拉斯金字塔分解与重构,在消除边缘效应方面表现出色。
计算机视觉(四)图像到图像的映射下半部分
- 1.RANSAC
- 2. 图像配准
- 3.图割方法
- 4.图像融合
- 5. APAP算法
- 6.multi-band bleing算法
在这章节的起始部分,请先了解什么是全景图景。所谓全景图景是指在同一位置(即相机所处位置一致)拍摄的两张或多张图片之间存在单应性关系。

1.RANSAC
RANSAC 是“RANdom SAmple Consensus”(随机一致性采样)的缩略形式。该算法旨在通过迭代过程系统性地确定适合于包含噪声数据的最佳模型。假设给定一个模型实例(例如两个点集之间的单应性矩阵),RANSAC 的基本思路是基于数据中存在真实样本和噪声样本的前提下,在保证模型准确性的同时有效识别并排除异常值。

2. 图像配准
图像配准过程是对图像进行特定转换的操作,其目标是使处理后的图景能够在统一的空间中实现精确重叠。这一操作对于后续对比分析以及细致入微的特征研究具有重要意义。在实际应用中,该操作通常包含多个步骤:首先,通过对图像进行关键特征提取;其次,建立两组关键点之间的相互映射关系;随后,通过RANSAC算法去除错误匹配;最后,利用高精度算法逐步优化几何关系参数以达到最佳效果。其中,DLT(直接线性变换)算法被广泛应用于复杂场景下三维重建任务中的平面校正工作;而Apop算法则采用分块策略,在每个局部区域独立处理,并基于此计算相应的几何映射关系以完成配准过程
3.图割方法
最大流最小割算法原理,
1.最小割问题
一个有向图,并有一个源顶点(source vertex)和目标顶点(target vertex).边的权值为正,又称之为容量(capacity)。如下图

将有向图的所有顶点划分为两个互不相交且互不重叠的部分的方式被称为st-cut(简称割cut)。其中源节点s位于其中一个子集内,并与另一个子集中的汇节点t相连。这种分割下连接两部分的所有边上具有一定的权重或容量之和被称为该割的容量(capacity of the cut)。需要注意的是,在计算该值时并不包括由另一侧指向这一侧的所有边上的权重或 capacity。而寻找最小割的问题就是要找到一种分割方式使得其对应的切割 capacity 达到最小值。
与最小割问题相类似地,在最大流问题中我们也会考虑一个有方向连接并带有 source vertex 和 target vertex 的图结构。在这个框架下每条连接都有一个非负数流量 capacity 来表示其承载能力上限。解决最大流问题的一般步骤如下:第一步我们设定所有连接上的初始流量 flow 值均为零;第二步则沿着确定好的增广路径不断调整当前流 state 以增加整体上的流量 value 。这里的增广路径指的是从 source 到 target 的一条无回路通路但必须满足以下条件:要么是沿未被占用的空间从前一点延伸至后一点的道路即前向道路未达到其 full capacity;要么是在已经释放的部分从后一点回退至前一点的道路即反向道路仍然存在可用空间这两种情况都可以被允许并被利用以进一步优化整个网络中的流量分布机制。
4.图像融合
在图像拼接完成后,在观察到交界处存在明显的衔接痕迹后发现该区域过渡效果欠佳。这主要是由于光照与色彩的因素导致,在拼接后的图像交界处过渡效果欠佳因此需要采取特定的方法来解决这一问题以获得更加自然的结果。目前广泛认可的融合方法之一是multi-band blending此方法通过逐层融合两张图象的空间细节得以实现显著提升融合效果同时需要注意的是拉普拉斯金字塔是高斯金字塔的逆过程。
1.构建两个待融合图像的空间频率分解结构即拉普拉斯双树
2.计算高斯双树作为掩模结构这是因为其特性具有尺度不变性
3.进行双树融合运算具体而言是在各自对应的层次上将左图右图的空间频率信息进行叠加得到最终的结果
4.通过逆变换重建最终空间域中的目标区域从而完成高质量的目标合成
5. APAP算法
在图像拼接融合的过程中,受客观因素影响,在图像拼接融合过程中会出现"鬼影现象"以及图像间过度不连续等问题。图中所示的是图像拼接过程中的一个典型"鬼影现象"实例。针对"鬼影现象"的消除问题,在实际应用中常采用APAP算法进行处理。

算法流程:
- 基于SIFT方法确定了两幅图像之间的匹配特征点对
- 使用RANSAC算法去除离群点后获得了N对稳健内点
- 通过结合DLT模型与奇异值分解(SVD)技术确定全局单应性参数
- 将原始图像划分为若干网格区域,并选取每个网格区域的中心坐标作为采样点
- 在DLT模型构建过程中将各采样点对应的权重系数融入到A矩阵中,并构建新的W*A系数矩阵
- 通过再次应用奇异值分解(SVD)方法求解局部子区域内对应的单应性矩阵
- 依次遍历每一个分割后的网格区域并进行相应的几何变换处理
- 最后进行拼接线段的加权融合处理以生成最终结果


6.multi-band bleing算法
完成后,在完成拼接缝之后受图像噪声的影响以及光照强度和曝光度等条件限制,并且还存在模型匹配所带来的误差的情况下,在两张图片的重叠区域直接进行图像合成会明显地导致边缘残留现象。

这些边痕迹需要采用图像融合技术以消除。下面介绍一种名为multi-band blending的方法。具体方法是对拼接后的两个图像进行拉普拉斯金字塔分解,并将后半部分与前半部分进行融合。首先计算当前待拼接的图像与已合成图像的重叠区域,并对其中A、B区域分别进行高斯金字塔和拉普拉斯金字塔分解。

G0为原始图像,G1表示对G0做reduce操作。Reduce操作定义如下:

首先对G1执行扩展操作后与G0执行相减运算能够得到拉普拉斯金字塔的第一层L0. 同样地拉普拉斯金字塔中的L2 L3等层级都可以采用相同的方法来进行计算. 在图像融合的过程中我们首先各自构建图像A和B各自的高斯金字塔以及拉普拉斯金字塔随后对其进行加权融合. 最后针对加权后的拉普拉斯金字塔构造出相应的层次结构完成整个算法流程.

代码:
from PIL import Image
from numpy import *
from pylab import *
import os
def process_image(imagename,resultname,params="--edge-thresh 10 --peak-thresh 5"):
""" Process an image and save the results in a file. """
if imagename[-3:] != 'pgm':
# create a pgm file
im = Image.open(imagename).convert('L')
im.save('tmp.pgm')
imagename = 'tmp.pgm'
cmmd = str(r"D:/计算机视觉/sift.exe "+imagename+" --output="+resultname+
" "+params)
os.system(cmmd)
print('processed', imagename, 'to', resultname)
def read_features_from_file(filename):
""" Read feature properties and return in matrix form. """
f = loadtxt(filename)
return f[:,:4],f[:,4:] # feature locations, descriptors
def write_features_to_file(filename,locs,desc):
""" Save feature location and descriptor to file. """
savetxt(filename,hstack((locs,desc)))
def plot_features(im,locs,circle=False):
""" Show image with features. input: im (image as array),
locs (row, col, scale, orientation of each feature). """
def draw_circle(c,r):
t = arange(0,1.01,.01)*2*pi
x = r*cos(t) + c[0]
y = r*sin(t) + c[1]
plot(x,y,'b',linewidth=2)
imshow(im)
if circle:
for p in locs:
draw_circle(p[:2],p[2])
else:
plot(locs[:,0],locs[:,1],'ob')
axis('off')
def match(desc1,desc2):
""" For each descriptor in the first image,
select its match in the second image.
input: desc1 (descriptors for the first image),
desc2 (same for second image). """
desc1 = array([d/linalg.norm(d) for d in desc1])
desc2 = array([d/linalg.norm(d) for d in desc2])
dist_ratio = 0.6
desc1_size = desc1.shape
matchscores = zeros((desc1_size[0]),'int')
desc2t = desc2.T # precompute matrix transpose
for i in range(desc1_size[0]):
dotprods = dot(desc1[i,:],desc2t) # vector of dot products
dotprods = 0.9999*dotprods
# inverse cosine and sort, return index for features in second image
indx = argsort(arccos(dotprods))
# check if nearest neighbor has angle less than dist_ratio times 2nd
if arccos(dotprods)[indx[0]] < dist_ratio * arccos(dotprods)[indx[1]]:
matchscores[i] = int(indx[0])
return matchscores
def appendimages(im1,im2):
""" Return a new image that appends the two images side-by-side. """
# select the image with the fewest rows and fill in enough empty rows
rows1 = im1.shape[0]
rows2 = im2.shape[0]
if rows1 < rows2:
im1 = concatenate((im1,zeros((rows2-rows1,im1.shape[1]))), axis=0)
elif rows1 > rows2:
im2 = concatenate((im2,zeros((rows1-rows2,im2.shape[1]))), axis=0)
# if none of these cases they are equal, no filling needed.
return concatenate((im1,im2), axis=1)
def plot_matches(im1,im2,locs1,locs2,matchscores,show_below=True):
""" Show a figure with lines joining the accepted matches
input: im1,im2 (images as arrays), locs1,locs2 (location of features),
matchscores (as output from 'match'), show_below (if images should be shown below). """
im3 = appendimages(im1,im2)
if show_below:
im3 = vstack((im3,im3))
# show image
imshow(im3)
# draw lines for matches
cols1 = im1.shape[1]
for i,m in enumerate(matchscores):
if m>0:
plot([locs1[i][0],locs2[m][0]+cols1],[locs1[i][1],locs2[m][1]],'c')
axis('off')
def match_twosided(desc1,desc2):
""" Two-sided symmetric version of match(). """
matches_12 = match(desc1,desc2)
matches_21 = match(desc2,desc1)
ndx_12 = matches_12.nonzero()[0]
# remove matches that are not symmetric
for n in ndx_12:
if matches_21[int(matches_12[n])] != n:
matches_12[n] = 0
return matches_12
结果:





因图片分辨率不足导致拼接效果欠佳。然而经过处理后图像质量仍可接受。
