这几天在看特征提取、匹配及最后误匹配点对剔除的资料,无意中发现了这个图像处理函数库——VL_FEAT。
主页网址是:http://www.vlfeat.org/。有兴趣的朋友可以访问并进行学习、研究。
上网查了一些资料,中文资料讲述详细地不多,这里做一个简单的介绍。
VL_FEAT库中包含了很多用C编写的图像处理函数,配置、安装好后可以直接调用(类似于OpenCV)。
除了在C++中可以配置外,同时也提供了Matlab接口。
在以上提供的网址中可以下载各种版本的VL_FEAT,本人用的是VLFeat 0.9.16 (Windows, Mac, Linux),即目前最新的版本。
1、运用VL_FEAT中的vl_sift、vl_ubcmatch在Matlab环境运行的例子,功能是进行两幅图像的拼接:
本人设置下面提到的根路劲root为 "F:\3D_Reconstruction\Ref_code\sift_mosaic\vlfeat-0.9.16"
vlfeat-0.9.16 为下载后解压的文件存储名。
1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 %%%%%%%%%两幅图的匹配 3 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 4 function mosaic = sift_mosaic(im1, im2) 5 run('root\toolbox\vl_setup'); 6 if nargin == 0 7 im1 = imread('river1.jpg') ; %图像目录及名称根据实际情况进行更改 8 im2 = imread('river2.jpg') ; 9 end 10 % make single,every value chahged to its percent of 255 11 im1 = im2single(im1) ; 12 im2 = im2single(im2) ; 13 % make grayscale 14 if size(im1,3) > 1, im1g = rgb2gray(im1) ; else im1g = im1 ; end 15 if size(im2,3) > 1, im2g = rgb2gray(im2) ; else im2g = im2 ; end 16 % -------------------------------------------------------------------- 17 % SIFT matches 18 % -------------------------------------------------------------------- 19 [f1,d1] = vl_sift(im1g) ; %图像特征点的提取,f1,d1分别代表特征点坐标及对象描述子 20 [f2,d2] = vl_sift(im2g) ; 21 [matches, scores] = vl_ubcmatch(d1,d2) ; %对上述提取的特征点进行匹配 22 numMatches = size(matches,2) ; 23 X1 = f1(1:2,matches(1,:)) ; X1(3,:) = 1 ; 24 X2 = f2(1:2,matches(2,:)) ; X2(3,:) = 1 ; 25 % -------------------------------------------------------------------- 26 % RANSAC with homography model 27 % -------------------------------------------------------------------- 28 clear H score ok ; 29 for t = 1:100 % 迭代100次,每次进行比较,最后选择最佳的H 30 % estimate homograpyh 31 subset = vl_colsubset(1:numMatches, 4) ; 32 A = [] ; 33 for i = subset 34 A = cat(1, A, kron(X1(:,i)', vl_hat(X2(:,i)))) ; 35 end 36 [U,S,V] = svd(A) ; 37 H{t} = reshape(V(:,9),3,3) ; 38 % score homography 39 X2_ = H{t} * X1 ; 40 du = X2_(1,:)./X2_(3,:) - X2(1,:)./X2(3,:) ; 41 dv = X2_(2,:)./X2_(3,:) - X2(2,:)./X2(3,:) ; 42 ok{t} = (du.*du + dv.*dv) < 6*6 ; 43 score(t) = sum(ok{t}) ; 44 end 45 [score, best] = max(score) ; 46 H = H{best} ; 47 ok = ok{best} ; 48 % -------------------------------------------------------------------- 49 % Optional refinement 50 % -------------------------------------------------------------------- 51 function err = residual(H) 52 u = H(1) * X1(1,ok) + H(4) * X1(2,ok) + H(7) ; 53 v = H(2) * X1(1,ok) + H(5) * X1(2,ok) + H(8) ; 54 d = H(3) * X1(1,ok) + H(6) * X1(2,ok) + 1 ; 55 du = X2(1,ok) - u ./ d ; 56 dv = X2(2,ok) - v ./ d ; 57 err = sum(du.*du + dv.*dv) ; 58 end 59 if exist('fminsearch') == 2 60 H = H / H(3,3) ; 61 opts = optimset('Display', 'none', 'TolFun', 1e-8, 'TolX', 1e-8) ; 62 H(1:8) = fminsearch(@residual, H(1:8)', opts) ; 63 else 64 warning('Refinement disabled as fminsearch was not found.') ; 65 end 66 % -------------------------------------------------------------------- 67 % Show matches 68 % -------------------------------------------------------------------- 69 dh1 = max(size(im2,1)-size(im1,1),0) ; 70 dh2 = max(size(im1,1)-size(im2,1),0) ; 71 figure(1) ; clf ; 72 subplot(2,1,1) ; 73 imagesc([padarray(im1,dh1,'post') padarray(im2,dh2,'post')]) ; 74 o = size(im1,2) ; 75 line([f1(1,matches(1,:));f2(1,matches(2,:))+o], ... 76 [f1(2,matches(1,:));f2(2,matches(2,:))]) ; 77 title(sprintf('%d tentative matches', numMatches)) ; 78 axis image off ; 79 subplot(2,1,2) ; 80 imagesc([padarray(im1,dh1,'post') padarray(im2,dh2,'post')]) ; 81 o = size(im1,2) ; 82 line([f1(1,matches(1,ok));f2(1,matches(2,ok))+o], ... 83 [f1(2,matches(1,ok));f2(2,matches(2,ok))]) ; 84 title(sprintf('%d (%.2f%%) inliner matches out of %d', ... 85 sum(ok), ... 86 100*sum(ok)/numMatches, ... 87 numMatches)) ; 88 axis image off ; 89 drawnow ; 90 % -------------------------------------------------------------------- 91 % Mosaic 92 % -------------------------------------------------------------------- 93 box2 = [1 size(im2,2) size(im2,2) 1 ; 94 1 1 size(im2,1) size(im2,1) ; 95 1 1 1 1 ] ; 96 box2_ = inv(H) * box2 ; 97 box2_(1,:) = box2_(1,:) ./ box2_(3,:) ; 98 box2_(2,:) = box2_(2,:) ./ box2_(3,:) ; 99 ur = min([1 box2_(1,:)]):max([size(im1,2) box2_(1,:)]) ; 100 vr = min([1 box2_(2,:)]):max([size(im1,1) box2_(2,:)]) ; 101 [u,v] = meshgrid(ur,vr) ; 102 im1_ = vl_imwbackward(im2double(im1),u,v) ; 103 z_ = H(3,1) * u + H(3,2) * v + H(3,3) ; 104 u_ = (H(1,1) * u + H(1,2) * v + H(1,3)) ./ z_ ; 105 v_ = (H(2,1) * u + H(2,2) * v + H(2,3)) ./ z_ ; 106 im2_ = vl_imwbackward(im2double(im2),u_,v_) ; 107 mass = ~isnan(im1_) + ~isnan(im2_) ; 108 im1_(isnan(im1_)) = 0 ; 109 im2_(isnan(im2_)) = 0 ; 110 mosaic = (im1_ + im2_) ./ mass ; 111 figure(2) ; clf ; 112 imagesc(mosaic) ; axis image off ; 113 title('Mosaic') ; 114 if nargout == 0, clear mosaic ; end 115 end
2、VS2010中某个项目配置VL_FEAT,并建立.cpp文件运行输出"HELLO VL_FEAT!"
可以先在系统环境中添加path变量: root
新建一个空项目vl_feat_test,点击并获得属性对话框,配置步骤如下:
(1)在C/C++ -> 常规,右侧的附加包含目录下添加上面提到的 root
(2)在链接器 -> 常规,右侧的附加库目录下添加 root/bin/win32
(3)在链接器 -> 输入,右侧的附加依赖项下添加 vl.lib
.cpp文件如下:
1 #include <iostream> 2 3 using namespace std; 4 5 extern "C" 6 { 7 #include <vl/generic.h> 8 #include <vl/stringop.h> 9 #include <vl/pgm.h> 10 #include <vl/sift.h> 11 #include <vl/getopt_long.h> 12 }; 13 14 int main() 15 { 16 VL_PRINTF("HELLO VL_FEAT!\n"); //vl_feat中的输出语句 17 getchar(); 18 19 return 0; 20 }
`直接编译、运行即可。