matlab练习程序(透视投影,把lena贴到billboard上)
2014-10-18 14:36
351 查看
本练习程序是受到了这个老外博文的启发,感觉挺有意思,就尝试了一下。他用的是opencv,我这里用的是matlab。
过去写过透视投影,当时是用来做倾斜校正的,这次同样用到了透视投影,不过更有意思,是将一张图像贴到另一张图像上。
两个透视投影都需要先计算投影矩阵,倾斜校正那一篇是通过解线性方程组求的变换矩阵,而这一篇是通过奇异值分解求的变换矩阵。
为了对齐两张图像,还需要对投影后的图像做一次仿射变换,其实就是坐标平移。
这里做投影和仿射直接调用了matlab的系统函数,方便一些。
还是先介绍下如何投影吧:
比如我们解单应性方程组或奇异值分解得到了投影矩阵:
![](http://latex.codecogs.com/gif.latex?%5Cbegin%7Bbmatrix%7D%20a%26b%20%26c%20%5C%5C%20d%26e%20%26f%20%5C%5C%20g%26h%20%261%20%5Cend%7Bbmatrix%7D)
那么变换方程就可以写为:
![](http://latex.codecogs.com/gif.latex?X%3D%5Cfrac%7Ba*x+b*y+c%7D%7Bg*x+h*y+1%7D)
![](http://latex.codecogs.com/gif.latex?Y%3D%5Cfrac%7Bd*x+e*y+f%7D%7Bg*x+h*y+1%7D)
其中,x,y为原图像像素坐标,X,Y为目标图像像素坐标。
做一些正反点匹配变换的时候我会用这个公式,不过大多数情况下在做图像投影的时候,我并不用上面的公式,而是用下面这个公式:
![](http://latex.codecogs.com/gif.latex?x%3D%5Cfrac%7B-c*e+b*f+e*X-f*h*X-b*Y+c*h*Y%7D%7Bb*d-a*e+e*g*X-d*h*X-b*g*Y+a*h*Y%7D)
![](http://latex.codecogs.com/gif.latex?y%3D%5Cfrac%7B-c*d+a*f+d*X-f*g*X-a*Y+c*g*Y%7D%7B-b*d+a*e-e*g*X+d*h*X+b*g*Y-a*h*Y%7D)
其中,x,y为原图像像素坐标,X,Y为目标图像像素坐标。
第一个公式计算后图像会出现空洞,第二个公式计算量明显变大了,各有利弊吧。
这么复杂的一个公式,我可推不出来,是用Mathematica推的,这个软件真是极大的提高了我的效率。
话说matlab应该也能推,不过matlab的符号计算毕竟不是强项,我也就没去了解matlab的这项功能。
看看效果吧。
原图:
![](http://images.cnitblog.com/blog/340413/201410/181046467632085.jpg)
广告牌:
![](http://images.cnitblog.com/blog/340413/201410/181047073104541.jpg)
结果:
![](http://images.cnitblog.com/blog/340413/201410/181047252942914.jpg)
matlab代码如下:
main.m
calc_homography
过去写过透视投影,当时是用来做倾斜校正的,这次同样用到了透视投影,不过更有意思,是将一张图像贴到另一张图像上。
两个透视投影都需要先计算投影矩阵,倾斜校正那一篇是通过解线性方程组求的变换矩阵,而这一篇是通过奇异值分解求的变换矩阵。
为了对齐两张图像,还需要对投影后的图像做一次仿射变换,其实就是坐标平移。
这里做投影和仿射直接调用了matlab的系统函数,方便一些。
还是先介绍下如何投影吧:
比如我们解单应性方程组或奇异值分解得到了投影矩阵:
那么变换方程就可以写为:
其中,x,y为原图像像素坐标,X,Y为目标图像像素坐标。
做一些正反点匹配变换的时候我会用这个公式,不过大多数情况下在做图像投影的时候,我并不用上面的公式,而是用下面这个公式:
其中,x,y为原图像像素坐标,X,Y为目标图像像素坐标。
第一个公式计算后图像会出现空洞,第二个公式计算量明显变大了,各有利弊吧。
这么复杂的一个公式,我可推不出来,是用Mathematica推的,这个软件真是极大的提高了我的效率。
话说matlab应该也能推,不过matlab的符号计算毕竟不是强项,我也就没去了解matlab的这项功能。
看看效果吧。
原图:
![](http://images.cnitblog.com/blog/340413/201410/181046467632085.jpg)
广告牌:
![](http://images.cnitblog.com/blog/340413/201410/181047073104541.jpg)
结果:
![](http://images.cnitblog.com/blog/340413/201410/181047252942914.jpg)
matlab代码如下:
main.m
clear all;close all;clc; img1=imread('lena.jpg'); [h1 w1]=size(img1); mask=uint8(ones(h1,w1)); %二值模板,方便最后的合成 img2=imread('pai.jpg'); [h2 w2]=size(img2); imshow(img1); figure;imshow(img2); p1=[1,1;w1,1;1,h1;w1,h1]; p2=ginput(); %依次点击公告牌左上、右上、左下、右下 T=calc_homography(p1,p2); %计算单应性矩阵 T=maketform('projective',T); %投影矩阵 [imgn X Y]=imtransform(img1,T); %投影 mask=imtransform(mask,T); T2=eye(3); if X(1)>0, T2(3,1)= X(1); end if Y(1)>0, T2(3,2)= Y(1); end T2=maketform('affine',T2); %仿射矩阵 imgn=imtransform(imgn,T2,'XData',[1 w2],'YData',[1 h2]); %仿射 mask=imtransform(mask,T2,'XData',[1 w2],'YData',[1 h2]); img=img2.*(1-mask)+imgn.*mask; %合成 figure;imshow(img,[])
calc_homography
function T = calc_homography(points1, points2) xaxb = points2(:,1) .* points1(:,1); xayb = points2(:,1) .* points1(:,2); yaxb = points2(:,2) .* points1(:,1); yayb = points2(:,2) .* points1(:,2); A = zeros(size(points1, 1)*2, 9); A(1:2:end,3) = 1; A(2:2:end,6) = 1; A(1:2:end,1:2) = points1; A(2:2:end,4:5) = points1; A(1:2:end,7) = -xaxb; A(1:2:end,8) = -xayb; A(2:2:end,7) = -yaxb; A(2:2:end,8) = -yayb; A(1:2:end,9) = -points2(:,1); A(2:2:end,9) = -points2(:,2); [junk1,junk2,V] = svd(A); h = V(:,9) ./ V(9,9); T= reshape(h,3,3); end
相关文章推荐
- matlab练习程序(图像加噪,各种滤波)
- matlab练习程序(最大中值滤波)
- matlab练习程序(Floyd–Steinberg dithering)
- matlab练习程序(Gabor Filter)
- matlab练习程序(感知哈希对比图片)
- matlab练习程序(求灰度图像最大灰度,最小灰度,平均灰度)
- matlab练习程序(LMS)
- matlab练习程序(图像旋转,最邻近插值)
- matlab练习程序(图像水平/竖直移动)
- matlab练习程序(白平衡<动态阈值>)
- matlab练习程序(中值滤波)
- matlab练习程序(灰度拉伸)
- matlab练习程序(生成高斯图像)
- matlab练习程序(图像错切)
- matlab练习程序(makelut/applylut)
- matlab练习程序(最大均值滤波)
- matlab练习程序(读入灰度图像序列)
- matlab练习程序(灰度图直方图均衡化)
- matlab练习程序(透视变换)
- matlab练习程序(PCA<SVD>)