Bob gilong
Bob gilong

Reputation: 215

Tilting an Image in CUDA

I'm trying to tilt an image 90 degrees, currently I'm following the method presented here: http://www.scribd.com/doc/66589491/Image-Rotation-Using-CUDA

My current code for the kernel is this:

 __global__ void kernCuda(float *Source,float * Destination, int width)
{
    int x = blockIdx.x * blockDim.x + threadIdx.x;
    int y = blockIdx.y * blockDim.y + threadIdx.y; 

    int i = abs(x*cosf(theta)-y*sinf(theta));
    int j = abs(x*sinf(theta)+y*cosf(theta));

    if(x<width && y<width){
        Destination[j*width+i]=Source[y*width+x];
    }

}

The image tilts somewhat, however it seems like it is not correct, on top of that some pixels that are colored is now black(0). Any help would be appreciated

Upvotes: 1

Views: 1549

Answers (3)

talonmies
talonmies

Reputation: 72338

The obvious problem is the integer truncation/interpolation issue.

One way around that would be to bind the source image to a texture and then read from the texture using the computed real valued coordinates. CUDA textures give you "free", hardware based interpolation/filtering. The main disadvantage of textures is the interpolation is limited to 8 bit internal accuracy, so it might not be accurate enough in some situations. But as a first attempt, try something like:

 __global__ void kernCuda(float * Destination, const float sintheta, const float costheta, 
                            const int width) 
{ 
    int x = blockIdx.x * blockDim.x + threadIdx.x; 
    int y = blockIdx.y * blockDim.y + threadIdx.y;  

    float tx = float(x)*costheta-float(y)*sintheta; 
    float ty = float(x)*sintheta+float(y)*costheta; 

    if(x<width && y<width){ 
        Destination[x*width+y]=tex2D(Source_texture, tx+0.5f,ty+0.5f); 
    } 
} 

(note not tested, never been near a compiler, use at your own risk).

Here Source_texture is the texture you bind the source data to. You can set the edge behaviour of the rotation in the texture setup, depending on how you want to handle it. How to setup and bind a texture in Section 3.2.10.1 of the CUDA 4.1 programming guide.

Note also that the cosine and sine in the rotation matrix are constant for a given value of theta, so it would be much more efficient to pass them to the kernel as an argument, rather than have every thread compute the same values. For the 90 degree rotation you have asked about, simply call the kernel with sintheta=0.f and costheta=1.f and you are done.

Upvotes: 1

devsnd
devsnd

Reputation: 7722

If you simply want to tilt the image by 90 degrees, then you won't need any trigonometric functions, since you can simply swap the x and y axis while interating through the pixels:

Destination[x+y*width]=tex2D(Source_texture, tx+0.5f,ty+0.5f); 

should do it.

Upvotes: 0

Azrael3000
Azrael3000

Reputation: 1897

I assume that theta is a floating point number. So you are mixing floating point and integer variables. I would suggest you use the appropriate casts to make it work and look for rounding issues.

Secondly, in order to see whether your program works in general you can replace cosf(theta) by 0 and sinf(theta) by 1.

One third issue that I can see is that you only take one x,y value instead of looping over them by using a while loop. So in case your image dimension is larger than the kernel that you use, you will not get all your pixels.

Edit: I just had a brief look at the report. It really is not very good. If you want to just learn about CUDA I suggest you get the book called "CUDA by Example".

Upvotes: 2

Related Questions