CUDA Image Rotation - PullRequest
       8

CUDA Image Rotation

2 голосов
/ 23 марта 2012

У меня проблемы с реализацией поворота изображения в CUDA.У меня есть очень простая функция поворота, которая работает следующим образом:

__device__ float readPixVal( float* ImgSrc,int ImgWidth,int x,int y)
{
    return (float)ImgSrc[y*ImgWidth+x];
}
__device__ void putPixVal( float* ImgSrc,int ImgWidth,int x,int y, float floatVal)
{
    ImgSrc[y*ImgWidth+x] = floatVal;
}

__global__ void Rotate(float* Source, float* Destination, int sizeX, int sizeY, float deg)
{
    int i = blockIdx.x * blockDim.x + threadIdx.x;// Kernel definition
    int j = blockIdx.y * blockDim.y + threadIdx.y;

    if(i < sizeX && j < sizeY)
    {
        putPixVal(Destination, sizeX, ((float)i)*cos(deg) - ((float)j)*sin(deg), ((float)i)*sin(deg) + ((float)j)*cos(deg)), readPixVal(Source, sizeX, i, j));
    }
}

Проблема в том, что я не знаю, как сделать какую-либо интерполяцию.С учетом вышеизложенного многие пиксели пропускаются из-за округления целого числа.Кто-нибудь знает, как это исправить, или есть какие-либо бесплатные / открытые реализации поворота изображения?Я не смог найти ни одного для CUDA.

Ответы [ 3 ]

5 голосов
/ 23 марта 2012

Обычно при такого рода манипуляциях с изображением вы циклически перемещаетесь по всем позициям конечного пикселя, вычисляя соответствующий пиксель (или интерполируя группы пикселей) в исходном изображении.

Это обеспечивает равномерное и равномерное заполнение полученного изображения, которое обычно является тем, что вас волнует.

2 голосов
/ 04 апреля 2012
void rotateImage_Kernel(cufftComplex* trg, const cufftComplex* src, const unsigned int imageWidth,const unsigned int imageHeight, const float angle, const float scale)
{
    // compute thread dimension
    const unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
    const unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;

    //// compute target address
    const unsigned int idx = x + y * imageWidth;

    const int xA = (x - imageWidth/2 );
    const int yA = (y - imageHeight/2 );

    const int xR = (int)floor(1.0f/scale * (xA * cos(angle) - yA * sin(angle)));
    const int yR = (int)floor(1.0f/scale * (xA * sin(angle) + yA * cos(angle)));

    float src_x = xR + imageWidth/2;
    float src_y = yR + imageHeight/2;



     if ( src_x >= 0.0f && src_x < imageWidth && src_y >= 0.0f && src_y < imageHeight) {
        // BI - LINEAR INTERPOLATION
        float src_x0 = (float)(int)(src_x);
        float src_x1 = (src_x0+1);
        float src_y0 = (float)(int)(src_y);
        float src_y1 = (src_y0+1);

        float sx = (src_x-src_x0);
        float sy = (src_y-src_y0);


        int idx_src00 = min(max(0.0f,src_x0   + src_y0 * imageWidth),imageWidth*imageHeight-1.0f);
        int idx_src10 = min(max(0.0f,src_x1   + src_y0 * imageWidth),imageWidth*imageHeight-1.0f);
        int idx_src01 = min(max(0.0f,src_x0   + src_y1 * imageWidth),imageWidth*imageHeight-1.0f);
        int idx_src11 = min(max(0.0f,src_x1   + src_y1 * imageWidth),imageWidth*imageHeight-1.0f);

        trg[idx].y = 0.0f;

        trg[idx].x  = (1.0f-sx)*(1.0f-sy)*src[idx_src00].x;
        trg[idx].x += (     sx)*(1.0f-sy)*src[idx_src10].x;
        trg[idx].x += (1.0f-sx)*(     sy)*src[idx_src01].x;
        trg[idx].x += (     sx)*(     sy)*src[idx_src11].x;
    } else {
        trg[idx].x = 0.0f;
        trg[idx].y = 0.0f;
     }

    DEVICE_METHODE_LAST_COMMAND;

}


void translateImage_Kernel(cufftComplex* trg, const cufftComplex* src, const unsigned int imageWidth, const unsigned int imageHeight, const float tX, const float tY)
{
    // compute thread dimension
    const unsigned int x = blockIdx.x * blockDim.x + threadIdx.x;
    const unsigned int y = blockIdx.y * blockDim.y + threadIdx.y;

    //// compute target address
    const unsigned int idx = x + y * imageWidth;

    const int xB = ((int)x + (int)tX );
    const int yB = ((int)y + (int)tY );

    if ( xB >= 0 && xB < imageWidth && yB >= 0 && yB < imageHeight) {
        trg[idx] = src[xB + yB * imageWidth];
    } else {
        trg[idx].x = 0.0f;
        trg[idx].y = 0.0f;
    }

    DEVICE_METHODE_LAST_COMMAND;

}
0 голосов
/ 23 марта 2012

Это, кажется, делает трюк

__global__ void Rotate(float* Source, float* Destination, int sizeX, int sizeY, float deg)
{
    int i = blockIdx.x * blockDim.x + threadIdx.x;// Kernel definition
    int j = blockIdx.y * blockDim.y + threadIdx.y;
    int xc = sizeX - sizeX/2;
    int yc = sizeY - sizeY/2;
    int newx = ((float)i-xc)*cos(deg) - ((float)j-yc)*sin(deg) + xc;
    int newy = ((float)i-xc)*sin(deg) + ((float)j-yc)*cos(deg) + yc;
    if (newx >= 0 && newx < sizeX && newy >= 0 && newy < sizeY)
    {
        putPixVal(Destination, sizeX, i , j, readPixVal(Source, sizeX, newx, newy));
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...