julia - bicubic
2015-06-18


禺画像]
バイキュービックの計算には、16画素のデータそれぞれに対する係数を求める必要がある。

求める画素位置と、実際の画素の位置から、画素間の距離を求め、その距離に応じた係数をそれぞれの画素の輝度値に掛け、その総和を求める画素の輝度値とする。
ここで、距離と係数の関係は sinc 関数を3次近似したものが使われる。
上の画像のピンクの線が sinc 関数で、下の緑と青が近似した値である。見やすくするために sinc 関数は上に0.5だけ移動してある。
ちなみに、sinc 関数とは sin(πx)/(πx) のこと。

この部分を関数にするとこんな感じ。
function fsinc(d)
        return (d < 1) ? d^3 - 2d^2 + 1 : (d < 2) ? -d^3 + 5d^2 - 8d + 4 : 0
end
実は julia には sinc 関数があるので、別の名前にした。

x方向、y方向、それぞれ独立に係数を求め、掛け合わせることで16個の係数を求める。(試しに xy両方を含めた距離で計算してみたが、ノイズっぽい画像になってしまった)

x方向だけ考えると、求める画素の位置は、4つの画素の真ん中にくる。
x値を小さい順に x1, x2, x3, x4 と置くと、求める画素の位置(x)は x2≦x<x3 となり、x2= floor(x) である。
よって、x と x2 の距離は x - floor(x) であり、x と x1 の距離は x と x2 の距離に1を足したものである。
また、x と x3 の距離は、1から(x と x2 の距離)を引いたものとなり、x と x4 の距離はそれに1を足したものである。
よって、x と x2 の距離(すなわち、x - floor(x) )を xd とすれば、それぞれ xd+1, xd, 1-xd, 2-xd となる。
y に関しても同様。

これを関数で書くと以下のようになる。
function getCOEFFS (xin, yin)
        # coefficient (a= -1)
        function fsinc(d)
                return (d < 1) ? d^3 - 2d^2 + 1 : (d < 2) ? -d^3 + 5d^2 - 8d + 4 : 0
        end
        # calc coefficients
        xd= xin - floor(xin)
        xc= map(x -> fsinc(x), [xd+1; xd; 1-xd; 2-xd])
        #
        yd= yin - floor(yin)
        yc= map(x -> fsinc(x), [yd+1 yd 1-yd 2-yd])
        #
        return xc * yc
end
関数の中に関数が書けるのは便利。
map を使って、行列の距離値を sinc 関数を使った係数に変換している。

xc は、4行1列の行列。yc は、1行4列の行列。
これらを掛け合わせると、4行4列の行列が得られる。これを戻り値にしている。

完成した関数は以下のとおり。
# ibuff の (xin,yin) から画素値を取得する
function imgpic (ibuff, xin, yin)

        # get 4x4 pixels
        function getPIX4x4 (ibuff, xin, yin)
                xstart= ifloor(xin) - 1
                ystart= ifloor(yin) - 1
                try
                        return ibuff[xstart:(xstart+3), ystart:(ystart+3)]
                catch   # out of range
                        obuff= ibuff[1:4,1:4]
                        (xmax,ymax)= size(ibuff)
                        for x= 1:4, y= 1:4
                                xin= xstart + (x - 1)
                                yin= ystart + (y - 1)
                                xin= (xin < 1) ? 1 : (xin > xmax) ? xmax : xin
                                yin= (yin < 1) ? 1 : (yin > ymax) ? ymax : yin
                                obuff[x,y]= ibuff[xin,yin]
                        end
                        return obuff
                end
        end

        # get 4x4 coefficients
        function getCOEFFS (xin, yin)
                # coefficient (a= -1)
                function fsinc(d)
                        return (d < 1) ? d^3 - 2d^2 + 1 : (d < 2) ? -d^3 + 5d^2 - 8d + 4 : 0
                end
                # calc coefficients
                xd= xin - floor(xin)
                xc= map(x -> fsinc(x), [xd+1; xd; 1-xd; 2-xd])
                #
                yd= yin - floor(yin)
                yc= map(x -> fsinc(x), [yd+1 yd 1-yd 2-yd])
                #
                return xc * yc
        end

        pixels= getPIX4x4(ibuff, xin, yin)
        coeffs= getCOEFFS(xin, yin)

        return sum(pixels .* coeffs) / sum(coeffs)

end
[Julia]
[画像処理]

コメント(全0件)
コメントをする


記事を書く
powered by ASAHIネット