opencv perspectiveTransform

来源:互联网 发布:手机p照片软件 编辑:程序博客网 时间:2024/06/01 11:05

Opencv 投射变换代码,代码很简单,但是也记录一下

 

公式为

 

 

 

Dst x,y,z为变化过后的坐标

Src x,y,z为变换签坐标

H为投射矩阵

 

 

 

 

void cv::perspectiveTransform( InputArray _src, OutputArray _dst, InputArray _mtx )

{

    Mat src = _src.getMat(), m = _mtx.getMat();//从接口类导出Mat

    int depth = src.depth(), scn = src.channels(), dcn = m.rows-1;//获得深度及通道数

    CV_Assert( scn + 1 == m.cols && (depth == CV_32F || depth == CV_64F));

 

    _dst.create( src.size(), CV_MAKETYPE(depth, dcn) );//分配内存

    Mat dst = _dst.getMat();

 

    const int mtype = CV_64F;

    AutoBuffer<double> _mbuf;

    double* mbuf = _mbuf;

 

    if( !m.isContinuous() || m.type() != mtype )//判断数据存储是否连续,以及类型是否是64位浮点

    {

        _mbuf.allocate((dcn+1)*(scn+1));

        Mat tmp(dcn+1, scn+1, mtype, (double*)_mbuf);

        m.convertTo(tmp, mtype);

        m = tmp;

    }

    else

        mbuf = (double*)m.data;

 

    TransformFunc func = depth == CV_32F ?

        (TransformFunc)perspectiveTransform_32f :

        (TransformFunc)perspectiveTransform_64f;//我理解这里其实就是一个函数指针,根据数据类型选择合适的函数

    CV_Assert( func != 0 );

 

    const Mat* arrays[] = {&src, &dst, 0};

    uchar* ptrs[2];

    NAryMatIterator it(arrays, ptrs);//作用等同于把src和dst的data地址给了ptrs,ptr[0]指向src

    size_t i, total = it.size;

 

    for( i = 0; i < it.nplanes; i++, ++it )

        func( ptrs[0], ptrs[1], (uchar*)mbuf, (int)total, scn, dcn );//调用真正的变换函数

}

 

 

 

template<typename T> static void

perspectiveTransform_( const T* src, T* dst, const double* m, int len, int scn, int dcn )

{

    const double eps = FLT_EPSILON;//无穷小

    int i;

 

    if( scn == 2 && dcn == 2 )//如果都是二维坐标,函数可以处理二维或三维或混合坐标,三维坐标就是齐次坐标

    {

        for( i = 0; i < len*2; i += 2 )

        {

            T x = src[i], y = src[i + 1];

            double w = x*m[6] + y*m[7] + m[8];//取得第三维度坐标,等会儿要归一化

 

            if( fabs(w) > eps )//如果第三维坐标为0,表示无穷远

            {

                w = 1./w;//归一化,做乘法比做除法更快

                dst[i] = (T)((x*m[0] + y*m[1] + m[2])*w);//计算变换后的坐标x

                dst[i+1] = (T)((x*m[3] + y*m[4] + m[5])*w); //计算变换后的坐标y

            }

            else

                dst[i] = dst[i+1] = (T)0;

        }

    }

    else if( scn == 3 && dcn == 3 )

    {

        for( i = 0; i < len*3; i += 3 )

        {

            T x = src[i], y = src[i + 1], z = src[i + 2];

            double w = x*m[12] + y*m[13] + z*m[14] + m[15];

 

            if( fabs(w) > eps )

            {

                w = 1./w;

                dst[i] = (T)((x*m[0] + y*m[1] + z*m[2] + m[3]) * w);

                dst[i+1] = (T)((x*m[4] + y*m[5] + z*m[6] + m[7]) * w);

                dst[i+2] = (T)((x*m[8] + y*m[9] + z*m[10] + m[11]) * w);

            }

            else

                dst[i] = dst[i+1] = dst[i+2] = (T)0;

        }

    }

    else if( scn == 3 && dcn == 2 )

    {

        for( i = 0; i < len; i++, src += 3, dst += 2 )

        {

            T x = src[0], y = src[1], z = src[2];

            double w = x*m[8] + y*m[9] + z*m[10] + m[11];

 

            if( fabs(w) > eps )

            {

                w = 1./w;

                dst[0] = (T)((x*m[0] + y*m[1] + z*m[2] + m[3])*w);

                dst[1] = (T)((x*m[4] + y*m[5] + z*m[6] + m[7])*w);

            }

            else

                dst[0] = dst[1] = (T)0;

        }

    }

    else

    {

        for( i = 0; i < len; i++, src += scn, dst += dcn )

        {

            const double* _m = m + dcn*(scn + 1);

            double w = _m[scn];

            int j, k;

            for( k = 0; k < scn; k++ )

                w += _m[k]*src[k];

            if( fabs(w) > eps )

            {

                _m = m;

                for( j = 0; j < dcn; j++, _m += scn + 1 )

                {

                    double s = _m[scn];

                    for( k = 0; k < scn; k++ )

                        s += _m[k]*src[k];

                    dst[j] = (T)(s*w);

                }

            }

            else

                for( j = 0; j < dcn; j++ )

                    dst[j] = 0;

        }

    }

}

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 专升本考试怎么办 专升本毕业论文怎么办 手机扫码模糊怎么办 iphone相册闪退怎么办 快件签收扫描失败怎么办 创业迷茫的时候怎么办 月经期间腰酸痛怎么办 被重庆微跑骗了怎么办 遴选到中央房子怎么办 转了户口社保怎么办 政府咨询电话打不通怎么办 公务员准考证丢了怎么办 行测老打40多分怎么办 网上没有报名的怎么办? 上大学转户口怎么办 梅菜扣肉勾芡怎么办 有个精神病妈妈怎么办 妈得了精神病该怎么办 思维不正常的人怎么办 妈妈是个精神病怎么办 我老婆有精神病怎么办 在郑州怎么办完税证明 中专没考上大专怎么办 考研两次没考上怎么办 2018造价员取消后怎么办 造价员取消了投标怎么办 造价员考试取消后怎么办 只拿到结业证怎么办 本科只有结业证怎么办 健身后肌肉水肿怎么办 大腿面肌肉疼怎么办 跑步后大腿酸疼怎么办? 运动后大腿胀痛怎么办 尔雅课程没看完怎么办 国家课程校本化怎么办 上海买房限购怎么办 投资公司要求回购股份怎么办 超过应届生落户年龄怎么办 造价员章到期了怎么办 造价员继续教育过期了怎么办 sd卡存储不够怎么办?