官方例子给的是用掩模来过滤点的代码,其实效果是一样的,这个调用不需要加_create。

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组

掩模的话,就是只有对应位置非0,才会把连线画出来的,上面不知道你们是否还记得**的用法。

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_02

这个输入只能是两个参数,这两个参数应该规定就是字典了,下面这样其实也是可以的。

我稍微比较了一下时间:

python中如何两个矩阵元组 python求两个矩阵的和_特征点_03

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_04

enmmm,FLANN并不是时间更短啊。

还有一点需要注意的是:

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_05

python中如何两个矩阵元组 python求两个矩阵的和_特征点_06

前两个不是用二进制描述的,没有问题,这里用二进制描述的就不行了。

python中如何两个矩阵元组 python求两个矩阵的和_插值_07

显示的是不支持这种格式的。

python中如何两个矩阵元组 python求两个矩阵的和_插值_08

BRISK的也不行。说明FLANN_INDEX_KDTREE算法不能用二进制的描述。

python中如何两个矩阵元组 python求两个矩阵的和_特征点_09

用了opencv官方给的ORB的例子也出错。我的opencv版本这里再说一下:

python中如何两个矩阵元组 python求两个矩阵的和_插值_10

不过opencv已经出了4,肯定时会有一定的变化的。不过其实问题在于数据格式,在网上查了资料http://answers.opencv.org/question/59996/flann-error-in-opencv-3/

说是flann的输入需要时浮点类型的32F。

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_11

我这里查到了汉明2距离的计算,它就是把两个比特位相加,然后按照一个比特位对待,然后按照汉明距离计算。

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_12

不过不能按照汉明距离去计算。

python中如何两个矩阵元组 python求两个矩阵的和_特征点_13

这里我们只是利用了normalize函数来把整数化为32F,不过这样其实有问题,因为原来的二进制应该按照汉明距离来匹配,但是现在却是按照欧式距离。我们看一下结果:

python中如何两个矩阵元组 python求两个矩阵的和_python如何对两个矩阵进行拼接_14

有几个还不错,但是蓝线时明显不对的。现在还不太知道FLANN怎么按照汉明距离来分类。这个其实用np.float32也可以实现:

python中如何两个矩阵元组 python求两个矩阵的和_插值_15

我们上面做的事情是在一张图片上找到特征点,我们找另一张图片,也找到特征点,然后匹配这些特征点。简单地说,我们在图中找到了一个物体某些部分的位置。这个信息足以在第二张图片中找到这个物体(也就是说我们在第二张图片中找到第一张图片中的指定物体)。这个我们前面尝试过,用模板匹配和直方图匹配都试过,但是,它们的尺度和旋转不变性很差,以前我们介绍过七种矩,它们的值可以用来作为识别物体的工具,现在我们用的是特征点匹配。有的时候,比如图像配准,我们需要知道两张图像的透视变换关系(之所以说是透视变换是因为它可以包含仿射变换)。我们是用calib3d模块里面的cv2.findHomography函数。如果我们把两幅图对应的点集作为参数传进去。它会找到这个透视变换关系,也就是透视变换矩阵M。关于透视变换,可以看一看:

python中如何两个矩阵元组 python求两个矩阵的和_插值_16

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_17

找到了透视变换关系之后可以用cv2.perspectiveTransform来实现这个变换,我们知道在匹配的时候会出现错误,这会影响最后的结果。为了解决这个问题,使用RANSAC或者LEAST_MEDIAN算法来解决。所以好的匹配给出的是好的结果,被叫做样本点,其它的不太好的结果叫做极端点。cv2.findHomography会返回一个掩模,这个掩模可以区分样本点和极端点。我们先来研究一下这两个函数:

python中如何两个矩阵元组 python求两个矩阵的和_特征点_18

首先注意输入的类型应该是32F。第三个参数比较重要,是方法,0用的是用所有点的最小二乘法,这个大家都学过,其实这个找关系的步骤就像是一个拟合的过程,其实就是确定透视矩阵M的8个参数,但是其实只需要4对点就可以确定8个参数,但是我们不止有4个点,我们可以确定很多组参数,怎么找到一组合适的参数呢?最小二乘给出了一种评价方法,就是让误差的平方和最小。RANSAC参考:


python中如何两个矩阵元组 python求两个矩阵的和_插值_19

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_20

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_21

python中如何两个矩阵元组 python求两个矩阵的和_特征点_22

python中如何两个矩阵元组 python求两个矩阵的和_python如何对两个矩阵进行拼接_23

这种算法也很好理解,就是随机取四对点,计算出透视变换矩阵,再拿其它点经过这个透视变换,看看变换的结果和匹配点的距离有多远,如果这个距离太大,就舍弃这一组四个点,重复选点,直到满足一定条件,当然每次取的可以不是4对点,每次用最小二乘算出来一个透视变换关系。 Least-Median是最小二乘的改进,因为点里面会有很多噪声胡总和说无效点,计算误差平方和会被无效点或者说离群点带偏,因为为了让它们的偏差变小,整个拟合结果就被带偏了。而加权和或许是一个不错的方法,不过权重怎么给呢?这个权重可以根据最后的误差平方和来调整,不过这个比较麻烦。用误差平方的中值最小作为目标就会比较好,因为中值不容易被噪声带偏。参考

python中如何两个矩阵元组 python求两个矩阵的和_python如何对两个矩阵进行拼接_24

python中如何两个矩阵元组 python求两个矩阵的和_特征点_25

参考

python中如何两个矩阵元组 python求两个矩阵的和_python如何对两个矩阵进行拼接_26

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_27

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_28

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_29

python中如何两个矩阵元组 python求两个矩阵的和_特征点_30

这个说明的额比较详细:

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_31

python中如何两个矩阵元组 python求两个矩阵的和_python如何对两个矩阵进行拼接_32

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_33

python中如何两个矩阵元组 python求两个矩阵的和_python如何对两个矩阵进行拼接_34

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_35

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_36

python中如何两个矩阵元组 python求两个矩阵的和_特征点_37

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_38

第四个参数是阈值,也就是最大的允许的透视变换偏差,如果超过这个偏差,就不作为样本点(用在RANSAC和RHO方法里)。偏差用的是二范数,对于点来说就是欧式距离。mask是输出的矩阵,它标记了样本点和极端点(离群点)。maxiters是RANSAC的最大迭代次数,confidence是置信度,越大的话两个集合匹配的结果越好,但是剩下的点会很少。

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_39

默认的方法是0,也就是最小二乘法,最后的结果可能找不出一个变换矩阵,这是返回的是空矩阵。原来我们用过:

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_40

这个函数的输入是四对点,结果是确定的,方程是封闭的。而上面用的可以输入多于4个点,用不同的方法可以得到不同的结果,因为方程比未知数多,就要用到一些拟合的方法。

python中如何两个矩阵元组 python求两个矩阵的和_python如何对两个矩阵进行拼接_41

这个是实现变换的函数,输入可以是二维点,这个时候变换矩阵是3×3的,也可以是三维点,变换矩阵是4×4的。

python中如何两个矩阵元组 python求两个矩阵的和_特征点_42

这个是更直接一点,为什么里面会有插值呢?因为变换之后的结果不一定是整数,但是显示的时候一定是整数,那么就得用插值来得到整数点的值了。代码:

python中如何两个矩阵元组 python求两个矩阵的和_特征点_43

这里设定了一个最小匹配点对数,如果获得的有效匹配点对数太少,不足以我们找到这个变换关系或者说变换关系不好。如果得到足够多的匹配点对,我们可以得到匹配点对在图像中的坐标,然后我们用它们来求出透视矩阵。

python中如何两个矩阵元组 python求两个矩阵的和_python如何对两个矩阵进行拼接_44

src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)

这一句首先float32是findHomography函数输入的要求,m.querydx是点的索引,再经过kp1就得到了坐标,最后的reshpe(-1,1,2)是为了符合格式:

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_45

这样也就是-1代表是不确定的值,不过应该是个整数。

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_46

看来findHomography的输出应该是样本点标记为1而离群点标记为0了。

python中如何两个矩阵元组 python求两个矩阵的和_插值_47

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_48

python中如何两个矩阵元组 python求两个矩阵的和_python如何对两个矩阵进行拼接_49

图2中红色边框是图一经过映射之后的边界。

换一种方法,用LMEDS:

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_50

变换矩阵还是不太一样的呢。

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_51

用变换矩阵变换图像之后。说明这个变换矩阵还是很好的。

opencv图像拼接和融合

这个和利用金字塔融合是不一样的,那个是强行融合,这个是找到相对应的特征点,然后根据特征点匹配的结果来拼接和融合。参考了和http://blog.sina.com.cn/s/blog_cfc0eb8f0101k8vz.html

python中如何两个矩阵元组 python求两个矩阵的和_插值_52

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_53

我们这里就用SIFT来提取特征点,接着上面的工作继续做下去。其实上面我们已经做了不少工作了,下一步就是要把两幅图拼接在一起了。

python中如何两个矩阵元组 python求两个矩阵的和_特征点_54

t1.png

python中如何两个矩阵元组 python求两个矩阵的和_插值_55

t2.png我拿这两幅图作为测试。如果要拼接三张,其实就是两次两两拼接,所以掌握了两两拼接就够了。

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_56

这个变换的时候最好是从右边的图片变到左边而不是左边到右边,因为左边到右边的话,经过透视变换之后,左边图片的左边部分丢失了,反过来就不会有问题了。

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_57

然后就可以直接拼接了,但是拼接后的大小要事先计算一下。

python中如何两个矩阵元组 python求两个矩阵的和_特征点_58

先计算右边图像2变换之后在左边图像中的最左边界位置,看到是510.6725。然后再计算右边图像经过透视变换之后需要多宽。

python中如何两个矩阵元组 python求两个矩阵的和_python如何对两个矩阵进行拼接_59

最右减去最左,然后就可以确定拼接之后的宽度为b1+d了。

python中如何两个矩阵元组 python求两个矩阵的和_特征点_60

这个错误是因为少了一个int。

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_61

结果:

python中如何两个矩阵元组 python求两个矩阵的和_特征点_62

中间重叠的部分由于加了两次,所以就会过分的亮,这个好解决。

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_63

拼接结果:

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_64

中间有些过渡的地方还是有些突兀的。这个时侯最好的办法不是滤波,也不是金字塔融合,因为它们都会让原图模糊,最好的办法是加权融合,这样会让边界不那么明显。

python中如何两个矩阵元组 python求两个矩阵的和_插值_65

这个加权得自己写程序,我写的意思是黑色的不参与加权,只有那些不是黑色的地方参与加权,权重各为0.5,效果:

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_66

过渡是自然了,但是那条裂缝很明显,我感觉很奇怪为什么会有裂缝,并且右边有一些黑色区域,这个我们可以这样处理。因为裂缝那个区域是两张图片一起加的,img1那里不是0,加起来怎么会得到结果是0呢。

python中如何两个矩阵元组 python求两个矩阵的和_python如何对两个矩阵进行拼接_67

我把透视变换那一步的插值方式换了一下,而且宽度也变了,不是用dst的最右边点了,而是用次右边。

结果:

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_68

裂缝相比上面没那么明显,但是还是看得到,但是这种插值方式出来的结果是最好的了。那个地方看起来明显是因为左右的亮度差太明显。

python中如何两个矩阵元组 python求两个矩阵的和_特征点_69

如果调整一下权重。看起来还是有点奇怪。

python中如何两个矩阵元组 python求两个矩阵的和_特征点_70

我最后想到一种比较好的办法。

python中如何两个矩阵元组 python求两个矩阵的和_特征点_71

我们只在最后的重合的10列里进行加权,效果:

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_72

觉得效果不好的话,你可以再增加列数。

Stitcher

这个类就是用来拼接图像的:

python中如何两个矩阵元组 python求两个矩阵的和_插值_73

参考了https://stackoverflow.com/questions/34362922/how-to-use-opencv-stitcher-class-with-python

python中如何两个矩阵元组 python求两个矩阵的和_插值_74

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_75

裁剪一下就可以了,虽然这个原理不是很清楚呢,因为不要想去看源码。

三张也可以:

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_76

如果是不沾边的图像输进去呢?

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_77

至少有两张可以拼接的,ret返回就是0,没有就是1。

python中如何两个矩阵元组 python求两个矩阵的和_透视变换_78

python中如何两个矩阵元组 python求两个矩阵的和_插值_79

2.png

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_80

t3.png

python中如何两个矩阵元组 python求两个矩阵的和_python中如何两个矩阵元组_81