Unwarp segment of 360 degree fisheye lens

asked 2012-10-01 03:36:19 -0600

andy.donaghey gravatar image

I have a 360 degree image taken from a fisheye lens and I would like to unwarp a segment of it. i.e. select a point in the image and then unwarp a segment surrounding that point - like a digital pan-tilt-zoom within the image.

I can successfully use the C++ version of opencv to create a panoramic image from it by building a mapping array and using remap like so:

int warpedW = src.size().width;
int warpedH = src.size().height;

int unwarpedW = 800;
int unwarpedH = 180;

// Angle to start unwarping from
float angularOffset = 0.0f;

// Centre point
float warpedCx = warpedW / 2.0f;
float warpedCy = warpedH / 2.0f;

/// Create map_x and map_y with the same size as src:
map_x.create( unwarpedH, unwarpedW, CV_32FC1 );
map_y.create( unwarpedH, unwarpedW, CV_32FC1 );

float circFactor = 0.0f - TWO_PI / (float) unwarpedW;

for ( int dsty = 0; dsty < unwarpedH; ++dsty )
{
    float y = ( (float) dsty / (float) unwarpedH );
    float yfrac = MIN( 1.0f, MAX( 0.0f, y ) ); 

    float radius = yfrac * warpedCy;

    for (int dstx = 0; dstx < unwarpedW; ++dstx )
    {
        float angle = ( (float) dstx * circFactor ) + ( DEG_TO_RAD * angularOffset );

        // map the source pixel to the destination pixel
        map_x.at< float >( dsty, dstx ) = warpedCx + radius * cosf( angle );
        map_y.at< float >( dsty, dstx ) = warpedCy + radius * sinf( angle );
    }
}

dst.create( unwarpedH, unwarpedW, src.type() );

remap( src, dst, map_x, map_y, CV_INTER_LINEAR );

I think I should be able to create mapping matrices and do a similar set of steps but I am a bit lost on the maths on how to do this.

Is there perhaps an easier way of doing this in opencv? I found detail::FisheyeWarper and detail::SphericalWarper and thought perhaps their warpBackward() method might work but my experimentation has so far been unsuccessful in getting these to do anything at all without asserting.

edit retag flag offensive close merge delete