Opencvに基づく二重線形補間の実現(二)


前編のブログでは,二重線形補間アルゴリズムに基づく画像スケーリングを実現し,主な関数zoomではポインタが大量に用いられている.ポインタで画像画素を読み取る利点は、実行速度が速く、コードが読みにくいことです.本編ではopencvライブラリに付属するcvGet 2 D()とcvSet 2 D()関数を用いて画像画素を読み書きし,実行速度は遅いがコード読解性が強く,簡単明瞭である.
次は主な関数zoomの実装で、他の部分は私の前のブログを参考にします.
void zoom(IplImage* src, IplImage* dst)
{
    int srcWidth = src->width;
    int srcHeight = src->height;
    int dstWidth = dst->width;
    int dstHeight = dst->height;

    //             ,   1   ,      ,     。        
    const float tx = (srcWidth-1.0f)/(dstWidth-1.0f);
    const float ty = (srcHeight-1.0f)/(dstHeight-1.0f);

    CvPoint2D32f uv;//          
    CvPoint3D32f f1;
    CvPoint3D32f f2;

    for (int j=0; j<dstHeight-1; j++)
     {
         for (int i=0; i<dstWidth-1; i++)
         {
			uv.x = i*tx;
			uv.y = j*ty;

			int iu = (int)uv.x;
            int iv = (int)uv.y;

            CvScalar p1, p2, p3, p4, s;
            p1=cvGet2D(src, iv, iu);
            p2=cvGet2D(src, iv, iu+1);
            p3=cvGet2D(src, iv+1, iu);
            p4=cvGet2D(src, iv+1, iu+1);

            f1.x = p1.val[0]*(1-Abs(uv.x-iu))+p2.val[0]*(uv.x-iu);
            f1.y = p1.val[1]*(1-Abs(uv.x-iu))+p2.val[1]*(uv.x-iu);
            f1.z = p1.val[2]*(1-Abs(uv.x-iu))+p2.val[2]*(uv.x-iu);

            f2.x = p3.val[0]*(1-Abs(uv.x-iu))+p4.val[0]*(uv.x-iu);
            f2.y = p3.val[1]*(1-Abs(uv.x-iu))+p4.val[1]*(uv.x-iu);
            f2.z = p3.val[2]*(1-Abs(uv.x-iu))+p4.val[2]*(uv.x-iu);

            s.val[0] = f1.x*(1-Abs(uv.y-iv))+f2.x*(Abs(uv.y-iv));
            s.val[1] = f1.y*(1-Abs(uv.y-iv))+f2.y*(Abs(uv.y-iv));
            s.val[2] = f1.z*(1-Abs(uv.y-iv))+f2.z*(Abs(uv.y-iv));
            cvSet2D(dst, j, i, s);
     
         }
         //         
         cvSet2D(dst, j, dstWidth-1, cvGet2D(dst, j, dstWidth-2));
    }
    //         
    for(int i=0; i<dstWidth; i++)
    {
        cvSet2D(dst, dstHeight-1, i, cvGet2D(dst, dstHeight-2, i));
    }
}