您的位置:首页 > 运维架构

opencv perspectiveTransform

2015-10-22 22:35 316 查看
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;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: