图像几何变化

梳理一下常见的图像几何变换及校正方式。参考资料来自《Computer Vision:Algorithms and Applications 》Richard Szeliski


图像几何变换

由于拍摄角度的不固定,图像出现几何变换,平移、旋转、尺度、仿射、投影等。如车牌检测的预处理,要将车牌校正,变成一个矩形。
常见的2D图像变化
这里写图片描述

  • translation
    2D的平移,x=x+t
    x¯=[It01]x¯
  • rotation+translation
    2D刚性运动,x=Rx+t

    R=[ cosθsinθsinθcosθ]

    正交旋转矩阵,欧式距离保持不变

  • scaled rotation
    “相似”变化,x=sRx+t, s代表尺度因子

    x=[sRt]x¯=[abtxbaty]x¯
    相似变换保持直线间的夹角不变

  • stretch/squash
    改变图像的aspect ratio

    x=sxx+tx
    y=syy+ty

  • affine
    仿射变换写作x=Ax¯,A是一个3×4的矩阵

    x=[a00a01a02a03a10a11a12a13a20a21a22a23]x¯

平行线和平行平面在经过仿射变换之后仍然保持平行。
- projective
投影变换,3D透视变换

x~=H~x~,
x=h00x+h01y+h02h20x+h21y+h22
y=h10x+h11y+h12h20x+h21y+h22

直线在经过投影变换之后还是直线
- 双线性内插
x=a0+a1x+a2y+a6xy
y=a3+a4x+a5y+a7xy
双线性内插一般用来resize图像


图像校正

存在明显特征的图像,可以提取特征点,然后配准求变换矩阵。注意选用的特征是否本身具备尺度、旋转不变性等。
如果只需要进行图像旋转校正,可以使用霍夫变换检测直线然后计算角度。我的理解,通过ρ=xcos(θ)+ysin(θ),把每个通过点(x,y)的直线就变成了正弦曲线(ρ,θ)。在参数空间中,找到(ρ,θ)的极值点,就对应一条直线。

function H = standardHoughTransform(BW,theta,rho)

coder.inline('always');
coder.internal.prefer_const(BW,theta,rho);

rhoLength   = coder.internal.indexInt(length(rho));
thetaLength = coder.internal.indexInt(length(theta));

firstRho = rho(1);
[numRow,numCol] = size(BW);

% Allocate space for H and initialize to 0
H = zeros(rhoLength,thetaLength);

% Allocate space for cos/sin lookup tables
cost = coder.nullcopy(zeros(thetaLength,1));
sint = coder.nullcopy(zeros(thetaLength,1));

% Pre-compute the sin and cos tables
for i = 1:thetaLength
    % Theta is in radians
    cost(i) = cos(theta(i) * pi/180);
    sint(i) = sin(theta(i) * pi/180);
end

% Compute the factor for converting back to the rho matrix index
slope = double(rhoLength-1) / double(rho(rhoLength) - firstRho);

% Compute the Hough transform
for n = 1:numCol
    for m = 1:numRow
        if BW(m,n) % if pixel is on
            for thetaIdx = 1:thetaLength
                % rho = x*cos(theta) + y*sin(theta)
                myRho = (n-1) * cost(thetaIdx) + (m-1) * sint(thetaIdx);
                % convert to bin index
                rhoIdx = roundAndCastInt(slope*(myRho - firstRho)) + 1;
                % accumulate
                H(rhoIdx,thetaIdx) = H(rhoIdx,thetaIdx)+1;
            end
        end
    end
end

%--------------------------------------------------------------------------
function y = roundAndCastInt(x)

coder.inline('always');
coder.internal.prefer_const(x);

% Only works if x >= 0
y = coder.internal.indexInt(x+0.5);

得到直线的斜率之后,将图片旋转、“掰正”。这时候图像存在黑色背景,然后根据斜率的符号确定图像的旋转方向,进而得到图形的有效区域。
直线检测也可以通过拟合得到,基于最小二乘和RANSAC得到直线方程。

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭