我尝试为warpPerspective()函数指定与基本(0,0)不同的原点,以便独立于支持图像的大小来应用变换。我在原始代码中添加了CvPoint参数,但是找不到在哪里使用这些坐标。我试图在X0,Y0和W0的计算中使用它们,但是它不起作用,这只会在结果图像中移动转换后的图像。任何的想法?

这里的代码:

void warpPerspective( const Mat& src, Mat& dst, const Mat& M0, Size dsize,
            int flags, int borderType, const Scalar& borderValue, CvPoint origin )
{
    dst.create( dsize, src.type() );

    const int BLOCK_SZ = 32;
    short XY[BLOCK_SZ*BLOCK_SZ*2], A[BLOCK_SZ*BLOCK_SZ];
    double M[9];
    Mat _M(3, 3, CV_64F, M);
    int interpolation = flags & INTER_MAX;
    if( interpolation == INTER_AREA )
        interpolation = INTER_LINEAR;

    CV_Assert( (M0.type() == CV_32F || M0.type() == CV_64F) && M0.rows == 3 && M0.cols == 3 );
    M0.convertTo(_M, _M.type());

    if( !(flags & WARP_INVERSE_MAP) )
     invert(_M, _M);

    int x, y, x1, y1, width = dst.cols, height = dst.rows;

    int bh0 = std::min(BLOCK_SZ/2, height);
    int bw0 = std::min(BLOCK_SZ*BLOCK_SZ/bh0, width);
    bh0 = std::min(BLOCK_SZ*BLOCK_SZ/bw0, height);

    for( y = 0; y < height; y += bh0 )
    {
        for( x = 0; x < width; x += bw0 )
        {
        int bw = std::min( bw0, width - x);
        int bh = std::min( bh0, height - y);

        Mat _XY(bh, bw, CV_16SC2, XY), _A;
        Mat dpart(dst, Rect(x, y, bw, bh));

        for( y1 = 0; y1 < bh; y1++ )
        {
                short* xy = XY + y1*bw*2;
                double X0 = M[0]*x + M[1]*(y + y1) + M[2];
                double Y0 = M[3]*x + M[4]*(y + y1) + M[5];
                double W0 = M[6]*x + M[7]*(y + y1) + M[8];

                if( interpolation == INTER_NEAREST )
                    for( x1 = 0; x1 < bw; x1++ )
                    {
                        double W = W0 + M[6]*x1;
                        W = W ? 1./W : 0;
                        int X = saturate_cast<int>((X0 + M[0]*x1)*W);
                        int Y = saturate_cast<int>((Y0 + M[3]*x1)*W);
                        xy[x1*2] = (short)X;
                        xy[x1*2+1] = (short)Y;
                    }
                else
                {
                    short* alpha = A + y1*bw;
                    for( x1 = 0; x1 < bw; x1++ )
                    {
                        double W = W0 + M[6]*x1;
                        W = W ? INTER_TAB_SIZE/W : 0;
                        int X = saturate_cast<int>((X0 + M[0]*x1)*W);
                        int Y = saturate_cast<int>((Y0 + M[3]*x1)*W);
                        xy[x1*2] = (short)(X >> INTER_BITS);
                        xy[x1*2+1] = (short)(Y >> INTER_BITS);
                        alpha[x1] = (short)((Y & (INTER_TAB_SIZE-1))*INTER_TAB_SIZE +
                                                  (X & (INTER_TAB_SIZE-1)));
                    }
                }
        }

        if( interpolation == INTER_NEAREST )
                remap( src, dpart, _XY, Mat(), interpolation, borderType, borderValue );
        else
        {
                Mat _A(bh, bw, CV_16U, A);
                remap( src, dpart, _XY, _A, interpolation, borderType, borderValue );
        }
        }
    }
}

最佳答案

好的,我自己找到了!您有2件事要做:

  • 计算源引用中的目标维度,并使用这些维度进行重新映射;
  • 增加计算点的坐标。

  • 这是经过转换的代码:
    void warpPerspective( const Mat& src, Mat& dst, const Mat& M0, Size dsize,
            int flags, int borderType, const Scalar& borderValue, CvPoint origin )
    {
    dst.create( dsize, src.type() );
    
    const int BLOCK_SZ = 32;
    short XY[BLOCK_SZ*BLOCK_SZ*2], A[BLOCK_SZ*BLOCK_SZ];
    double M[9];
    Mat _M(3, 3, CV_64F, M);
    int interpolation = flags & INTER_MAX;
    if( interpolation == INTER_AREA )
        interpolation = INTER_LINEAR;
    
    CV_Assert( (M0.type() == CV_32F || M0.type() == CV_64F) && M0.rows == 3 && M0.cols == 3 );
    M0.convertTo(_M, _M.type());
    
    if( !(flags & WARP_INVERSE_MAP) )
     invert(_M, _M);
    
    int x, xDest, y, yDest, x1, y1, width = dst.cols, height = dst.rows;
    
    int bh0 = std::min(BLOCK_SZ/2, height);
    int bw0 = std::min(BLOCK_SZ*BLOCK_SZ/bh0, width);
    bh0 = std::min(BLOCK_SZ*BLOCK_SZ/bw0, height);
    
    for( y = -origin.y, yDest = 0; y < height; y += bh0, yDest += bh0 )
    {
        for( x = -origin.x, xDest = 0; x < width; x += bw0, xDest += bw0 )
        {
        int bw = std::min( bw0, width - x);
        int bh = std::min( bh0, height - y);
        // to avoid dimensions errors
        if (bw <= 0 || bh <= 0)
        break;
    
        Mat _XY(bh, bw, CV_16SC2, XY), _A;
        Mat dpart(dst, Rect(xDest, yDest, bw, bh));
    
        for( y1 = 0; y1 < bh; y1++ )
        {
                short* xy = XY + y1*bw*2;
                double X0 = M[0]*x + M[1]*(y + y1) + M[2];
                double Y0 = M[3]*x + M[4]*(y + y1) + M[5];
                double W0 = M[6]*x + M[7]*(y + y1) + M[8];
    
                if( interpolation == INTER_NEAREST )
                    for( x1 = 0; x1 < bw; x1++ )
                    {
                        double W = W0 + M[6]*x1;
                        W = W ? 1./W : 0;
                        int X = saturate_cast<int>((X0 + M[0]*x1)*W);
                        int Y = saturate_cast<int>((Y0 + M[3]*x1)*W);
                        xy[x1*2] = (short)X;
                        xy[x1*2+1] = (short)Y;
                    }
                else
                {
                    short* alpha = A + y1*bw;
                    for( x1 = 0; x1 < bw; x1++ )
                    {
                        double W = W0 + M[6]*x1;
                        W = W ? INTER_TAB_SIZE/W : 0;
                        int X = saturate_cast<int>((X0 + M[0]*x1)*W);
                        int Y = saturate_cast<int>((Y0 + M[3]*x1)*W);
                        xy[x1*2] = (short)(X >> INTER_BITS) + origin.x;
                        xy[x1*2+1] = (short)(Y >> INTER_BITS) + origin.y;
                        alpha[x1] = (short)((Y & (INTER_TAB_SIZE-1))*INTER_TAB_SIZE +
                                                  (X & (INTER_TAB_SIZE-1)));
                    }
                }
        }
    
        if( interpolation == INTER_NEAREST )
                remap( src, dpart, _XY, Mat(), interpolation, borderType, borderValue );
        else
        {
                Mat _A(bh, bw, CV_16U, A);
                remap( src, dpart, _XY, _A, interpolation, borderType, borderValue );
        }
        }
    }
    }
    

    具有此功能:
    CvPoint transformPoint(const CvPoint pointToTransform, const CvMat* matrix) {
    double coordinates[3] = {pointToTransform.x, pointToTransform.y, 1};
    CvMat originVector = cvMat(3, 1, CV_64F, coordinates);
    CvMat transformedVector = cvMat(3, 1, CV_64F, coordinates);
    cvMatMul(matrix, &originVector, &transformedVector);
    CvPoint outputPoint = cvPoint((int)(cvmGet(&transformedVector, 0, 0) / cvmGet(&transformedVector, 2, 0)), (int)(cvmGet(&transformedVector, 1, 0) / cvmGet(&transformedVector, 2, 0)));
    return outputPoint;
    }
    

    关于opencv - 在OpenCV 2.x中为warpPerspective()函数指定一个原点,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4279008/

    10-12 21:09