Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

イメージの歪み補正アルゴリズムの開発

この例では、Symbolic Math Toolbox™ を使用して、イメージの歪みを補正する数学モデルを開発し、ライブ スクリプトでローカル関数の特徴を示します。

問題の背景

現実世界の任意の点 P(X,Y,Z) は、ある 3 次元世界の原点に対して定義できます。

カメラのレンズとの相関において、この 3 次元の点は P の回転と平行移動によって得られる p0 として定義できます。

p0=(x0,y0,z0) = RP+t

次に、3 次元の点 p0 をカメラのイメージ平面に 2 次元の点 (x1,y1) として投影します。

x1=x0z0 , y1=y0z0

カメラがイメージをキャプチャする場合、実際の点を正確にキャプチャするのではなく、むしろ実際の点が少し歪んだものをキャプチャします。これは (x2,y2) で表すことができます。歪んだ点は、以下の関数で記述できます。

x2=x1(1+k1r2+k2r4)+2p1x1y1+p2(r2+2x12)

y2=y1(1+k1r2+k2r4)+2p2x1y1+p1(r2+2y12)

ここで

k1k2 = レンズの半径方向歪み係数

p1p2 = レンズの円周方向歪み係数

r=x12+y12

歪み

レンズ歪みの例 (以下を参照): 元の歪んだイメージ (左) と歪み補正後のイメージ (右)

最初のイメージのエッジに向かうラインの湾曲に注目してください。イメージの再構成やトラッキングなどのアプリケーションでは、現実世界の点の位置を理解することが重要になります。歪んだイメージがある場合、歪んだピクセルの位置 (x2,y2) はわかっています。(x2,y2) と特定のレンズの歪み係数を与えて、歪み補正後のピクセル位置 (x1,y1) を決定することが目標です。

特に複雑な部分はないにしても、レンズ歪みの非線形特性によって難易度の高い問題となっています。

歪みモデルの定義

歪みモデルの定義から開始

% Parameters
syms k_1 k_2 p_1 p_2 real
syms r x y
distortionX = subs(x * (1 + k_1 * r^2 + k_2 * r^4) + 2 * p_1 * x * y + p_2 * (r^2 + 2 * x^2), r, sqrt(x^2 + y^2))
distortionX = p23x2+y2+xk2x2+y22+k1x2+y2+1+2p1xy
distortionY = subs(y * (1 + k_1 * r^2 + k_2 * r^4) + 2 * p_2 * x * y + p_1 * (r^2 + 2 * y^2), r, sqrt(x^2 + y^2))
distortionY = p1x2+3y2+yk2x2+y22+k1x2+y2+1+2p2xy

半径方向歪み k1=0

レンズの半径方向歪み係数をk1=0 と仮定して、ピクセル位置のグリッドをプロットします。歪みは、イメージの中心付近で最小、エッジ付近で最大となります。

% Set Parameters
parameters = [k_1 k_2 p_1 p_2];
parameterValues = [0 0 0 0];
plotLensDistortion(distortionX,distortionY,parameters,parameterValues)
spacing = 0.2000
distortionX = x
distortionY = y

Figure contains an axes object. The axes object contains 242 objects of type line, quiver.

半径方向歪み k1=0.15

k1 の変更に対する感度を調べます。

% Set Parameters
parameters = [k_1 k_2 p_1 p_2];
parameterValues = [0.15 0 0 0];
plotLensDistortion(distortionX,distortionY,parameters,parameterValues)
spacing = 0.2000
distortionX = 

x3x220+3y220+1

distortionY = 

y3x220+3y220+1

Figure contains an axes object. The axes object contains 242 objects of type line, quiver.

逆歪みモデルの計算

カメラのレンズ歪み係数と一連の歪んだピクセル位置 (x2,y2) を与えて、歪み補正後のピクセル位置 (x1,y1) を計算できるようにします。0.2 に等しい k1 を除き、すべての歪み係数が 0 の特殊なケースを調べます。

まず、歪み係数を定義します。

syms X Y positive
eq1 = X == distortionX
eq1 = X=p23x2+y2+xk2x2+y22+k1x2+y2+1+2p1xy
eq2 = Y == distortionY
eq2 = Y=p1x2+3y2+yk2x2+y22+k1x2+y2+1+2p2xy

与えられた歪み係数に対する歪み方程式を定義して、歪み補正後のピクセル位置 (x1,y1) の解を求めます。

parameters = [k_1 k_2 p_1 p_2];
parameterValues = [0.2 0 0 0];
eq1 = expand(subs(eq1, parameters, parameterValues))
eq1 = 

X=x35+xy25+x

eq2 = expand(subs(eq2, parameters, parameterValues))
eq2 = 

Y=x2y5+y35+y

Result = solve([eq1, eq2], [x,y], 'MaxDegree', 3,'Real',true)
Result = struct with fields:
    x: (X*(((5*Y^3)/(2*(X^2 + Y^2)) + ((25*Y^6)/(4*(X^2 + Y^2)^2) + (125*Y^6)/(27*(X^2 + Y^2)^3))^(1/2))^(1/3) - (5*Y^2)/(3*(X^2 + Y^2)*((5*Y^3)/(2*X^2 + 2*Y^2) + ((25*Y^6)/(4*(X^2 + Y^2)^2) + (125*Y^6)/(27*(X^2 + Y^2)^3))^(1/2))^(1/3))))/Y
    y: ((5*Y^3)/(2*(X^2 + Y^2)) + ((25*Y^6)/(4*(X^2 + Y^2)^2) + (125*Y^6)/(27*(X^2 + Y^2)^3))^(1/2))^(1/3) - (5*Y^2)/(3*(X^2 + Y^2)*((5*Y^3)/(2*X^2 + 2*Y^2) + ((25*Y^6)/(4*(X^2 + Y^2)^2) + (125*Y^6)/(27*(X^2 + Y^2)^3))^(1/2))^(1/3))

要素 1 は実数解のみであるため、その式を自身の変数へ抽出します。

[Result.x Result.y]
ans = 

(Xσ1Yσ1)where  σ1=σ2-5Y23X2+Y2σ2  σ2=5Y32X2+Y2+25Y64X2+Y22+125Y627X2+Y231/3

これで、イメージの歪み補正に使用できるピクセル位置 X と Y の解析式が得られました。

レンズ歪みを描画するための関数

function plotLensDistortion(distortionX,distortionY,parameters,parameterValues)
% distortionX is the expression describing the distorted x coordinate
% distortionY is the expression describing the distorted y coordinate
% k1 and k2 are the radial distortion coefficients 
% p1 and p2 are the tangential distortion coefficients 

syms x y

% This is the grid spacing over the image
spacing = 0.2

% Inspect and parametrically substitute in the values for k_1 k_2 p_1 p_2
distortionX = subs(distortionX,parameters,parameterValues)
distortionY = subs(distortionY,parameters,parameterValues)

% Loop over the grid
for x_i = -1:spacing:1
    for y_j = -1:spacing:1
        
        % Compute the distorted location 
        xout = subs(distortionX, {x,y}, {x_i,y_j});
        yout = subs(distortionY, {x,y}, {x_i,y_j});
        
        % Plot the original point
        plot(x_i,y_j, 'o', 'Color', [1.0, 0.0, 0.0])
        hold on
       
        % Draw the distortion direction with Quiver
        p1 = [x_i,y_j];                     % First Point
        p2 = [xout,yout];                   % Second Point
        dp = p2-p1;                         % Difference
        quiver(p1(1),p1(2),dp(1),dp(2),'AutoScale','off','MaxHeadSize',1,'Color',[0 0 1])
        
    end
end
hold off
grid on

end