python提取人物特征_python—sift特征提取

代码:

1 #-*- coding: utf-8 -*-

2 from PIL importImage3 from pylab import *

4 from PCV.localdescriptors importsift5 from PCV.localdescriptors importharris6

7 #添加中文字体支持

8 from matplotlib.font_manager importFontProperties9 font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)10

11 imname = 'siftt/24.jpg'

12 im = array(Image.open(imname).convert('L'))13 sift.process_image(imname, '24.sift')14 l1, d1 = sift.read_features_from_file('24.sift')15

16 figure()17 gray()18 subplot(131)19 sift.plot_features(im, l1, circle=False)20 title(u'SIFT特征',fontproperties=font)21 subplot(132)22 sift.plot_features(im, l1, circle=True)23 title(u'用圆圈表示SIFT特征尺度',fontproperties=font)24

25 #检测harris角点

26 harrisim =harris.compute_harris_response(im)27

28 subplot(133)29 filtered_coords = harris.get_harris_points(harrisim, 6, 0.1)30 imshow(im)31 plot([p[1] for p in filtered_coords], [p[0] for p in filtered_coords], '*')32 axis('off')33 title(u'Harris角点',fontproperties=font)34

35 show()

原图

运行结果:

小结:由图看出,sift算法检测出来的特征点比harris角点算法检测出的角点多。sift算法测出来的特征点大多数都是重合的。

2、图像集里的所有图像的sift特征提取

代码:

1 #-*- coding: utf-8 -*-

2 from PIL importImage3 from pylab import *

4 from PCV.localdescriptors importsift5 from PCV.localdescriptors importharris6 from PCV.tools.imtools import get_imlist #导入原书的PCV模块

7

8 #添加中文字体支持

9 from matplotlib.font_manager importFontProperties10 font = FontProperties(fname=r"c:\windows\fonts\SimSun.ttc", size=14)11

12 #获取project2_data文件夹下的图片文件名(包括后缀名)

13 filelist = get_imlist('siftt/')14

15 for infile in filelist: #对文件夹下的每张图片进行如下操作

16 print(infile) #输出文件名

17

18 im = array(Image.open(infile).convert('L'))19 sift.process_image(infile, 'infile.sift')20 l1, d1 = sift.read_features_from_file('infile.sift')21 i=1

22

23 figure(i)24 i=i+1

25 gray()26

27 subplot(131)28 sift.plot_features(im, l1, circle=False)29 title(u'SIFT特征',fontproperties=font)30

31 subplot(132)32 sift.plot_features(im, l1, circle=True)33 title(u'用圆圈表示SIFT特征尺度',fontproperties=font)34

35 #检测harris角点

36 harrisim =harris.compute_harris_response(im)37

38 subplot(133)39 filtered_coords = harris.get_harris_points(harrisim, 6, 0.1)40 imshow(im)41 plot([p[1] for p in filtered_coords], [p[0] for p in filtered_coords], '*')42 axis('off')43 title(u'Harris角点',fontproperties=font)44

45 show()

结果截图:

3、两张图片,计算sift特征匹配结果

代码:

1 #-*- coding: utf-8 -*-

2 from PIL importImage3 from pylab import *

4 from numpy import *

5 importos6

7 def process_image(imagename, resultname, params="--edge-thresh 10 --peak-thresh 5"):8 """处理一幅图像,然后将结果保存在文件中"""

9 if imagename[-3:] != 'pgm':10 #创建一个pgm文件

11 im = Image.open(imagename).convert('L')12 im.save('tmp.pgm')13 imagename ='tmp.pgm'

14 cmmd = str("sift"+imagename+"--output="+resultname+" "+params)15 os.system(cmmd)16 print 'processed', imagename, 'to', resultname17

18 defread_features_from_file(filename):19 """读取特征属性值,然后将其以矩阵的形式返回"""

20 f =loadtxt(filename)21 return f[:,:4], f[:,4:] #特征位置,描述子

22

23 defwrite_featrues_to_file(filename, locs, desc):24 """将特征位置和描述子保存到文件中"""

25 savetxt(filename, hstack((locs,desc)))26

27 def plot_features(im, locs, circle=False):28 """显示带有特征的图像29 输入:im(数组图像),locs(每个特征的行、列、尺度和朝向)"""

30

31 defdraw_circle(c,r):32 t = arange(0,1.01,.01)*2*pi33 x = r*cos(t) +c[0]34 y = r*sin(t) + c[1]35 plot(x, y, 'b', linewidth=2)36

37 imshow(im)38 ifcircle:39 for p inlocs:40 draw_circle(p[:2], p[2])41 else:42 plot(locs[:,0], locs[:,1], 'ob')43 axis('off')44

45 defmatch(desc1, desc2):46 """对于第一幅图像中的每个描述子,选取其在第二幅图像中的匹配47 输入:desc1(第一幅图像中的描述子),desc2(第二幅图像中的描述子)"""

48 desc1 = array([d/linalg.norm(d) for d indesc1])49 desc2 = array([d/linalg.norm(d) for d indesc2])50 dist_ratio = 0.6

51 desc1_size =desc1.shape52 matchscores = zeros((desc1_size[0],1),'int')53 desc2t = desc2.T #预先计算矩阵转置

54 for i inrange(desc1_size[0]):55 dotprods = dot(desc1[i,:],desc2t) #向量点乘

56 dotprods = 0.9999*dotprods57 #反余弦和反排序,返回第二幅图像中特征的索引

58 indx =argsort(arccos(dotprods))59 #检查最近邻的角度是否小于dist_ratio乘以第二近邻的角度

60 if arccos(dotprods)[indx[0]] < dist_ratio * arccos(dotprods)[indx[1]]:61 matchscores[i] =int(indx[0])62 returnmatchscores63

64 defmatch_twosided(desc1, desc2):65 """双向对称版本的match()"""

66 matches_12 =match(desc1, desc2)67 matches_21 =match(desc2, desc1)68 ndx_12 =matches_12.nonzero()[0]69 #去除不对称的匹配

70 for n inndx_12:71 if matches_21[int(matches_12[n])] !=n:72 matches_12[n] =073 returnmatches_1274

75 defappendimages(im1, im2):76 """返回将两幅图像并排拼接成的一幅新图像"""

77 #选取具有最少行数的图像,然后填充足够的空行

78 rows1 =im1.shape[0]79 rows2 =im2.shape[0]80 if rows1 <81 im1="concatenate((im1," zeros elif rows1>rows2:83 im2 = concatenate((im2, zeros((rows1-rows2,im2.shape[1]))),axis=0)84 return concatenate((im1,im2), axis=1)8581>

86 def plot_matches(im1,im2,locs1,locs2,matchscores,show_below=True):87 """显示一幅带有连接匹配之间连线的图片88 输入:im1, im2(数组图像), locs1,locs2(特征位置),matchscores(match()的输出),89 show_below(如果图像应该显示在匹配的下方)90 """

91 im3=appendimages(im1, im2)92 ifshow_below:93 im3=vstack((im3, im3))94 imshow(im3)95 cols1 = im1.shape[1]96 for i inrange(len(matchscores)):97 if matchscores[i]>0:98 plot([locs1[i,0],locs2[matchscores[i,0],0]+cols1], [locs1[i,1],locs2[matchscores[i,0],1]],'c')99 axis('off')100

101 im1f = 'siftt/25.jpg'

102 im2f = 'siftt/26.jpg'

103

104 im1 =array(Image.open(im1f))105 im2 =array(Image.open(im2f))106

107 process_image(im1f, 'out_sift_1.txt')108 l1,d1 = read_features_from_file('out_sift_1.txt')109 figure()110 gray()111 subplot(121)112 plot_features(im1, l1, circle=False)113

114 process_image(im2f, 'out_sift_2.txt')115 l2,d2 = read_features_from_file('out_sift_2.txt')116 subplot(122)117 plot_features(im2, l2, circle=False)118

119 matches =match_twosided(d1, d2)120 print '{} matches'.format(len(matches.nonzero()[0]))121

122 figure()123 gray()124 plot_matches(im1, im2, l1, l2, matches, show_below=True)125 show()

结果截图:

小结:用siftt算法提取两张图的特征点,然后双向匹配两张图片的描述子,用线将两幅图相匹配的描述子相连,连的线越多,说明这两幅图的匹配度越高,两幅图越相似。

4、给定一张图片,输出匹配度最高的三张图片

代码:

1 #-*- coding: utf-8 -*-

2 from PIL importImage3 from pylab import *

4 from numpy import *

5 importos6 from PCV.tools.imtools import get_imlist #导入原书的PCV模块

7 import matplotlib.pyplot as plt #plt 用于显示图片

8 import matplotlib.image as mpimg #mpimg 用于读取图片

9

10 def process_image(imagename, resultname, params="--edge-thresh 10 --peak-thresh 5"):11 """处理一幅图像,然后将结果保存在文件中"""

12 if imagename[-3:] != 'pgm':13 #创建一个pgm文件

14 im = Image.open(imagename).convert('L')15 im.save('tmp.pgm')16 imagename ='tmp.pgm'

17 cmmd = str("sift"+imagename+"--output="+resultname+" "+params)18 os.system(cmmd)19 print 'processed', imagename, 'to', resultname20

21 defread_features_from_file(filename):22 """读取特征属性值,然后将其以矩阵的形式返回"""

23 f =loadtxt(filename)24 return f[:,:4], f[:,4:] #特征位置,描述子

25

26 defwrite_featrues_to_file(filename, locs, desc):27 """将特征位置和描述子保存到文件中"""

28 savetxt(filename, hstack((locs,desc)))29

30 def plot_features(im, locs, circle=False):31 """显示带有特征的图像32 输入:im(数组图像),locs(每个特征的行、列、尺度和朝向)"""

33

34 defdraw_circle(c,r):35 t = arange(0,1.01,.01)*2*pi36 x = r*cos(t) +c[0]37 y = r*sin(t) + c[1]38 plot(x, y, 'b', linewidth=2)39

40 imshow(im)41 ifcircle:42 for p inlocs:43 draw_circle(p[:2], p[2])44 else:45 plot(locs[:,0], locs[:,1], 'ob')46 axis('off')47

48 defmatch(desc1, desc2):49 """对于第一幅图像中的每个描述子,选取其在第二幅图像中的匹配50 输入:desc1(第一幅图像中的描述子),desc2(第二幅图像中的描述子)"""

51 desc1 = array([d/linalg.norm(d) for d indesc1])52 desc2 = array([d/linalg.norm(d) for d indesc2])53 dist_ratio = 0.6

54 desc1_size =desc1.shape55 matchscores = zeros((desc1_size[0],1),'int')56 desc2t = desc2.T #预先计算矩阵转置

57 for i inrange(desc1_size[0]):58 dotprods = dot(desc1[i,:],desc2t) #向量点乘

59 dotprods = 0.9999*dotprods60 #反余弦和反排序,返回第二幅图像中特征的索引

61 indx =argsort(arccos(dotprods))62 #检查最近邻的角度是否小于dist_ratio乘以第二近邻的角度

63 if arccos(dotprods)[indx[0]] < dist_ratio * arccos(dotprods)[indx[1]]:64 matchscores[i] =int(indx[0])65 returnmatchscores66

67 defmatch_twosided(desc1, desc2):68 """双向对称版本的match()"""

69 matches_12 =match(desc1, desc2)70 matches_21 =match(desc2, desc1)71 ndx_12 =matches_12.nonzero()[0]72 #去除不对称的匹配

73 for n inndx_12:74 if matches_21[int(matches_12[n])] !=n:75 matches_12[n] =076 returnmatches_1277

78 defappendimages(im1, im2):79 """返回将两幅图像并排拼接成的一幅新图像"""

80 #选取具有最少行数的图像,然后填充足够的空行

81 rows1 =im1.shape[0]82 rows2 =im2.shape[0]83 if rows1 <84 im1="concatenate((im1," zeros elif rows1>rows2:86 im2 = concatenate((im2, zeros((rows1-rows2,im2.shape[1]))),axis=0)87 return concatenate((im1,im2), axis=1)8884>

89 def plot_matches(im1,im2,locs1,locs2,matchscores,show_below=True):90 """显示一幅带有连接匹配之间连线的图片91 输入:im1, im2(数组图像), locs1,locs2(特征位置),matchscores(match()的输出),92 show_below(如果图像应该显示在匹配的下方)93 """

94 im3=appendimages(im1, im2)95 ifshow_below:96 im3=vstack((im3, im3))97 imshow(im3)98 cols1 = im1.shape[1]99 for i inrange(len(matchscores)):100 if matchscores[i]>0:101 plot([locs1[i,0],locs2[matchscores[i,0],0]+cols1], [locs1[i,1],locs2[matchscores[i,0],1]],'c')102 axis('off')103

104 #获取project2_data文件夹下的图片文件名(包括后缀名)

105 filelist = get_imlist('project2_data/')106

107 #输入的图片

108 im1f = '23.jpg'

109 im1 =array(Image.open(im1f))110 process_image(im1f, 'out_sift_1.txt')111 l1, d1 = read_features_from_file('out_sift_1.txt')112

113 i=0114 num = [0]*30 #存放匹配值

115 for infile in filelist: #对文件夹下的每张图片进行如下操作

116 im2 =array(Image.open(infile))117 process_image(infile, 'out_sift_2.txt')118 l2, d2 = read_features_from_file('out_sift_2.txt')119 matches =match_twosided(d1, d2)120 num[i] =len(matches.nonzero()[0])121 i=i+1

122 print '{} matches'.format(num[i-1]) #输出匹配值

123

124 i=1

125 figure()126 while i<4: #循环三次,输出匹配最多的三张图片

127 index=num.index(max(num))128 printindex, filelist[index]129 lena = mpimg.imread(filelist[index]) #读取当前匹配最大值的图片

130 #此时 lena 就已经是一个 np.array 了,可以对它进行任意处理

131 #lena.shape # (512, 512, 3)

132 subplot(1,3,i)133 plt.imshow(lena) #显示图片

134 plt.axis('off') #不显示坐标轴

135 num[index] = 0 #将当前最大值清零

136 i=i+1

137 show()

结果截图:

给定的图片

输出的图片

小结:通过用给定的图匹配图像集中的每张图片的描述子,然后用线与图像集中的图片的描述子相连,匹配度最高的图片就会被输出。

七、图像全景拼接RANSAC

7.1 RANSAC算法原理

OpenCV中滤除误匹配对采用RANSAC算法寻找一个最佳单应性矩阵H,矩阵大小为3×3。RANSAC目的是找到最优的参数矩阵使得满足该矩阵的数据点个数最多,通常令h33=1来归一化矩阵。由于单应性矩阵有8个未知参数,至少需要8个线性方程求解,对应到点位置信息上,一组点对可以列出两个方程,则至少包含4组匹配点对。

RANSAC算法从匹配数据集中随机抽出4个样本并保证这4个样本之间不共线,计算出单应性矩阵,然后利用这个模型测试

所有数据,并计算满足这个模型数据点的个数与投影误差(即代价函数),若此模型为最优模型,则对应的代价函数最小。

7.2 RANSAC算法步骤

1. 随机从数据集中随机抽出4个样本数据 (此4个样本之间不能共线),计算出变换矩阵H,记为模型M;

2. 计算数据集中所有数据与模型M的投影误差,若误差小于阈值,加入内点集 I ;

3. 如果当前内点集 I 元素个数大于最优内点集 I_best , 则更新 I_best = I,同时更新迭代次数k ;

4. 如果迭代次数大于k,则退出 ; 否则迭代次数加1,并重复上述步骤;

注:迭代次数k在不大于最大迭代次数的情况下,是在不断更新而不是固定的;p为置信度,一般取0.995;w为"内点"的比例 ; m为计算模型所需要的最少样本数=4;

7.3 RANSAC 基本假设

测试的数据都是由"局外点"组成的,建立模型,局外点是不能适应该模型的数据,也就是不合适该模型的局外点就是噪声。

7.4  RANSAC 局外点产生的原因

A、噪声的极值

B、错误的测量方法

C、对数据的错误假设

7.5实验代码

1 from pylab import *

2 from PIL importImage3 importwarp4 importhomography5 importsift6

7 #set paths to data folder

8 featname = ['D:/new/jia/' + str(i + 1) + '.sift' for i in range(3)]9 imname = ['D:/new/jia/' + str(i + 1) + '.jpg' for i in range(3)]10

11 #extract features and match

12 l ={}13 d ={}14 for i in range(3):15 sift.process_image(imname[i], featname[i])16 l[i], d[i] =sift.read_features_from_file(featname[i])17

18 matches ={}19 for i in range(2):20 matches[i] = sift.match(d[i + 1], d[i])21

22 #visualize the matches (Figure 3-11 in the book)

23 for i in range(2):24 im1 =array(Image.open(imname[i]))25 im2 = array(Image.open(imname[i + 1]))26 figure()27 sift.plot_matches(im2, im1, l[i + 1], l[i], matches[i], show_below=True)28

29

30 #function to convert the matches to hom. points

31 defconvert_points(j):32 ndx =matches[j].nonzero()[0]33 fp = homography.make_homog(l[j + 1][ndx, :2].T)34 ndx2 = [int(matches[j][i]) for i inndx]35 tp = homography.make_homog(l[j][ndx2, :2].T)36

37 #switch x and y - TODO this should move elsewhere

38 fp = vstack([fp[1], fp[0], fp[2]])39 tp = vstack([tp[1], tp[0], tp[2]])40 returnfp, tp41

42

43 #estimate the homographies

44 model =homography.RansacModel()45

46 fp,tp = convert_points(1)47 H_12 = homography.H_from_ransac(fp,tp,model)[0] #im 1 to 2

48

49 fp,tp =convert_points(0)50 H_01 = homography.H_from_ransac(fp,tp,model)[0] #im 0 to 1

51

52

53 #warp the images

54 delta = 1000 #for padding and translation

55

56 im1 = array(Image.open(imname[1]), "uint8")57 im2 = array(Image.open(imname[2]), "uint8")58 im_12 =warp.panorama(H_12,im1,im2,delta,delta)59

60 im1 = array(Image.open(imname[0]), "f")61 im_02 =warp.panorama(dot(H_12,H_01),im1,im_12,delta,delta)62

63 figure()64 imshow(array(im_02, "uint8"))65 axis('off')66 show()

7.6结果截图

单一的环境图片

分析:我拍摄的是四张图片,环境很单一,同一个场景,不同的角度,由结果截图看出前面一张图片的拼接点较多,从第二张看出删除点较为明显,一看就可以看出来那些点被删除了,删除后觉得看到的连线比较清晰,连接的线条变少。

分析:这组图片是同一个地点拍的,环境比较丰富,从不同的角度拍摄,第一张图片跟第二张的不同点相当的明显,第一张的连线很多,拼接的效果很成功,连线很多,看出有重复点,覆盖匹配点,第二张的图片相似点较少,连线也不多,说明了,相似度高的匹配程度就高,拼接效果也好,相似度低的就相反。

7.7遇到的问题

因为运行之前没有导入包,就产生了错误,然后我就导入了warp包

报错

1 Arrays cannot be empty

矩阵为空,我就重新改了图像的像素,提取sift特征

然后由报错

1 did not meet fit acceptance criteria

这是因为图片的水平落差比较大,我们得再拍一组照片。改了图片的下高速,图片的像素都改成一样,不能太大也不能太小,我改成的是600*600.

八、SIFT实验总结

1、sift算法提取特征点稳定,不会因为光照、旋转、尺度等因素而改变图像的特征点。

2、图像的尺度越大,图像就会越模糊。

3、sift算法可以对多张图像进行快速的、准确的关键点匹配,产生大量的特征点,可以适用于生活中的很多运用。

4、sift算法提取的特征点会有重叠。

5、在用sift算法提取特征时,应该降低图片的像素,像素过高会导致运行时间过长或失败。

九、实验遇到的问题

出现的问题:1、运行代码时出现这样的错误:

在D:\Anaconda2\Lib\site-packages目录中找到pydot.py ,用记事本打开,把self.prog = 'dot‘改成self.prog = r'C:\Program Files (x86)\Graphviz2.38\bin\dot.exe',保存,关掉运行软件再打开就可以了。

2、运行代码出现这样的结果

我用的项目的路径,出现以上报错,把路径改成了图片的路径,图片的后缀改成.jpg就可以了。

3、因为图片像素过高,运行时间会过长,结果一直出不来,还以为是代码出来了错误,但是不报错,想着可能是照片是自己拍的,像素过高了,就去降低了图片的像素,运行速率变快,结果就出来了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值