cvundistort.cpp.svn-base

来自「非结构化路识别」· SVN-BASE 代码 · 共 1,555 行 · 第 1/4 页

SVN-BASE
1,555
字号
/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                        Intel License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of Intel Corporation may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/

#include "_cv.h"

typedef struct CvUnDistortData
{
    int ind;
    ushort a0;
    ushort a1;
    ushort a2;
    ushort a3;
}
CvUnDistortData;

/*F//////////////////////////////////////////////////////////////////////////////////////
//    Names: icvUnDistortInit_8uC1R, icvUnDistortInit_8uC3R, 
//    Purpose: The functions calculate arrays of distorted points indices and
//             interpolation coefficients for cvUnDistort function
//    Context:
//    Parameters:  size        - size of each image or of its ROI
//                 step        - full width of each image in bytes
//                 intrMatrix  - matrix of the camera intrinsic parameters
//                 distCoeffs  - vector of the distortion coefficients (k1, k2, p1 and p2)
//                 interToggle - interpolation toggle
//                 data        - distortion data array
//
//    Returns: CV_NO_ERR or error code
//
//    Notes:  1. If interToggle=0, interpolation disabled;
//               else bilinear interpolation is used.
//            2. Array data must be allocated before. If interToggle = 0, its length
//               must be size.width*size.height elements; else 3*size.width*size.height.
//F*/
/*______________________________________________________________________________________*/

IPCVAPI_IMPL( CvStatus, icvUnDistortInit, ( int srcStep, int* data,
                                            int mapStep, CvSize size,
                                            const float *intrMatrix,
                                            const float *distCoeffs,
                                            int interToggle, int pixSize ))
{
    const float a1 = 1.f / intrMatrix[0], b1 = 1.f / intrMatrix[4],
        u0 = intrMatrix[2], v0 = intrMatrix[5],
        k1 = distCoeffs[0], k2 = distCoeffs[1], p1 = distCoeffs[2], p2 = distCoeffs[3];
    int u, v;
    float p22 = 2.f * p2;

    if( size.width <= 0 || size.height <= 0 )
        return CV_BADSIZE_ERR;

    if( !intrMatrix || !distCoeffs || !data )
        return CV_NULLPTR_ERR;

    if( !interToggle )
    {
        for( v = 0; v < size.height; v++, (char*&)data += mapStep )
        {
            float dv = v - v0;
            float y = b1 * dv;
            float y1 = p1 / y;
            float y2 = y * y;
            float y3 = 2.f * p1 * y;

            for( u = 0; u < size.width; u++ )
            {
                float du = u - u0;
                float x = a1 * du;
                float x1 = p2 / x;
                float x2 = x * x;
                float x3 = p22 * x;
                float r2 = x2 + y2;
                float bx = r2 * (k1 + r2 * k2) + x3 + y3;
                float by = bx + r2 * y1;
                int ud = u, vd = v;

                bx += r2 * x1;
                ud += cvRound( bx * du );
                vd += cvRound( by * dv );
                data[u] = ud < 0 || ud >= size.width || vd < 0 || vd >= size.height ?
                    0 : vd * srcStep + ud*pixSize;
            }
        }
    }
    else                        /* interpolation */
    {
        const int sizex = size.width - 2, sizey = size.height - 2;
        CvUnDistortData *uData = (CvUnDistortData *) data;

        const float s15 = 32768.f;
        const int bmax = 32767;

        for( v = 0; v < size.height; v++, (char*&)uData += mapStep )
        {
            float dv = v - v0;
            float y = b1 * dv;
            float y1 = p1 / y;
            float y2 = y * y;
            float y3 = 2.f * p1 * y;

            for( u = 0; u < size.width; u++ )
            {
                float du = u - u0;
                float x = a1 * du;
                float x1 = p2 / x;
                float x2 = x * x;
                float x3 = p22 * x;
                float r2 = x2 + y2;
                float bx = r2 * (k1 + r2 * k2) + x3 + y3;
                float by = bx + r2 * y1;
                float uf = (float) u, vf = (float) v;
                int ud, vd;

                bx += r2 * x1;
                uf += bx * du;
                vf += by * dv;
                ud = cvFloor( uf );
                vd = cvFloor( vf );
                if( ud < 0 || ud > sizex || vd < 0 || vd > sizey )
                {
                    (uData + u)->ind = 0;
                    (uData + u)->a0 = (uData + u)->a1 = (uData + u)->a2 = (uData + u)->a3 =
                    (ushort) 0;
                }
                else
                {
                    float uf1, vf1;
                    int b0, b1, b2, b3;

                    (uData + u)->ind = vd * srcStep + ud*pixSize;
                    uf -= (float) ud;
                    vf -= (float) vd;
                    uf1 = 1.f - uf;
                    vf1 = 1.f - vf;
                    b0 = (int) (s15 * uf1 * vf1);
                    b1 = (int) (s15 * uf * vf1);
                    b2 = (int) (s15 * uf1 * vf);
                    b3 = (int) (s15 * uf * vf);
                    if( b0 < 0 )
                        b0 = 0;
                    if( b1 < 0 )
                        b1 = 0;
                    if( b2 < 0 )
                        b2 = 0;
                    if( b3 < 0 )
                        b3 = 0;
                    if( b0 > bmax )
                        b0 = bmax;
                    if( b1 > bmax )
                        b1 = bmax;
                    if( b2 > bmax )
                        b2 = bmax;
                    if( b3 > bmax )
                        b3 = bmax;
                    (uData + u)->a0 = (ushort) b0;
                    (uData + u)->a1 = (ushort) b1;
                    (uData + u)->a2 = (ushort) b2;
                    (uData + u)->a3 = (ushort) b3;
                }
            }                   /* u */
        }                       /* v */
    }                           /* else */

    return CV_NO_ERR;
}

/*======================================================================================*/

/*F//////////////////////////////////////////////////////////////////////////////////////
//    Names: icvUnDistort_8u_C1R, icvUnDistort_8u_C3R
//    Purpose: The functions correct radial and tangential distortion in the frame
//             using previousely calculated arrays of distorted points indices and
//             undistortion coefficients
//    Context:
//    Parameters:  src    - source (distorted) image
//                 dst    - output (undistorted) image
//                 step        - full width of each image in bytes
//                 size        - size of each image or of its ROI
//                 interToggle - interpolation toggle
//                 data        - distortion data array
//
//    Returns: CV_NO_ERR or error code
//
//    Notes:  1. Either icvUnDistortInit_8u_C1R or icvUnDistortInit_8u_C3R function
//               must be used previously
//            2. See Notes to the icvUnDistortInit_8u_C1R, icvUnDistortInit_8u_C3R
//               functions
//F*/
/*______________________________________________________________________________________*/

IPCVAPI_IMPL( CvStatus, icvUnDistort_8u_C1R, ( const uchar* src, int srcStep,
                                               const int* data, int mapStep,
                                               uchar* dst, int dstStep,
                                               CvSize size, int interToggle ))
{
    int u, v;
    uchar buf;

    if( size.width <= 0 || size.height <= 0 )
        return CV_BADSIZE_ERR;

    if( !src || !dst || !data )
        return CV_NULLPTR_ERR;

    buf = *src;
    *(uchar*&)src = (uchar)0;

    if( !interToggle )          /* Interpolation disabled */
    {
        for( v = 0; v < size.height; v++, dst += dstStep, (char*&)data += mapStep )
        {
            for( u = 0; u <= size.width - 4; u += 4 )
            {
                uchar t0 = src[data[u]];
                uchar t1 = src[data[u+1]];

                dst[u] = t0;
                dst[u + 1] = t1;

                t0 = src[data[u+2]];
                t1 = src[data[u+3]];

                dst[u + 2] = t0;
                dst[u + 3] = t1;
            }

            for( ; u < size.width; u++ )
            {
                dst[u] = src[data[u]];
            }
        }
    }
    else /* Interpolation enabled */
    {
        CvUnDistortData *uData = (CvUnDistortData *) data;

        for( v = 0; v < size.height; v++, dst += dstStep, (char*&)uData += mapStep )
        {
            for( u = 0; u < size.width; u++ )
            {
                CvUnDistortData d = uData[u];
                const uchar* s = src + d.ind;

                dst[u] = (uchar)((s[0]*d.a0 + s[1]*d.a1 +
                        s[srcStep]*d.a2 + s[srcStep+1]*d.a3) >> 15);
            }
        }
    }

    *(uchar*&)src = buf;
    return CV_NO_ERR;
}


#define ICV_COPY_C3( src_ptr, dst_ptr ) \
    (dst_ptr)[0] = (src_ptr)[0];        \
    t0 = (src_ptr)[1];                  \
    t1 = (src_ptr)[2];                  \
    (dst_ptr)[1] = t0;                  \
    (dst_ptr)[2] = t1
   

/*_____________________________ 3-CHANNEL IMAGES _______________________________*/

IPCVAPI_IMPL( CvStatus, icvUnDistort_8u_C3R, ( const uchar* src, int srcStep,
                                               const int* data, int mapStep,
                                               uchar* dst, int dstStep,
                                               CvSize size, int interToggle ))
{
    int u, v;
    uchar buf[3];

    if( size.width <= 0 || size.height <= 0 )
        return CV_BADSIZE_ERR;

    if( !src || !dst || !data )
        return CV_NULLPTR_ERR;

    memcpy( buf, src, 3 );
    memset( (void*)src, 0, 3 );

    if( !interToggle )          /* Interpolation disabled */
    {
        for( v = 0; v < size.height; v++, dst += dstStep, (char*&)data += mapStep )
        {
            for( u = 0; u <= size.width - 4; u += 4, dst += 12 )
            {
                uchar t0, t1;

                int v3 = data[u];
                ICV_COPY_C3( src + v3, dst );

                v3 = data[u + 1];
                ICV_COPY_C3( src + v3, dst + 3 );

                v3 = data[u + 2];
                ICV_COPY_C3( src + v3, dst + 6 );

                v3 = data[u + 3];
                ICV_COPY_C3( src + v3, dst + 9 );
            }

            for( ; u < size.width; u++, dst += 3 )
            {
                int v3 = data[u];
                uchar t0, t1;

                ICV_COPY_C3( src + v3, dst );
            }

            dst -= size.width * 3;
        }
    }
    else  /* Interpolation enabled */
    {
        CvUnDistortData *uData = (CvUnDistortData *) data;

        for( v = 0; v < size.height; v++, dst += dstStep, (char*&)uData += mapStep )
        {
            for( u = 0; u < size.width; u++, dst += 3 )
            {
                CvUnDistortData d = uData[u];
                const uchar* s = src + d.ind;

                dst[0] = (uchar) ((s[0] * d.a0 + s[3] * d.a1 +
                                   s[srcStep] * d.a2 + s[srcStep + 3] * d.a3) >> 15);

                dst[1] = (uchar) ((s[1] * d.a0 + s[4] * d.a1 +
                                   s[srcStep + 1] * d.a2 + s[srcStep + 4] * d.a3) >> 15);

                dst[2] = (uchar) ((s[2] * d.a0 + s[5] * d.a1 +
                                   s[srcStep + 2] * d.a2 + s[srcStep + 5] * d.a3) >> 15);
            }

            dst -= size.width * 3;
        }
    }

    memcpy( (void*)src, buf, 3 );
    return CV_NO_ERR;
}

/*======================================================================================*/

/*F//////////////////////////////////////////////////////////////////////////////////////
//    Names: icvUnDistort1_8uC1R, icvUnDistort1_8uC3R
//    Purpose: The functions correct radial image distortion using known matrix of the
//             camera intrinsic parameters and distortion coefficients
//    Context:
//    Parameters:  src    - source (distorted) image
//                 dst    - output (undistorted) image

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?