Наклон изображения в CUDA - PullRequest
1 голос
/ 27 марта 2012

Я пытаюсь наклонить изображение на 90 градусов, в настоящее время я следую методу, представленному здесь: http://www.scribd.com/doc/66589491/Image-Rotation-Using-CUDA

Мой текущий код для ядра такой:

 __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];
    }

}

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

Ответы [ 3 ]

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

Я предполагаю, что тета - это число с плавающей запятой. Итак, вы смешиваете переменные с плавающей запятой и целочисленные. Я бы посоветовал вам использовать соответствующие приведения, чтобы заставить его работать, и искать проблемы с округлением.

Во-вторых, чтобы увидеть, работает ли ваша программа в целом, вы можете заменить cosf(theta) на 0 и sinf(theta) на 1.

Третья проблема, которую я вижу, состоит в том, что вы берете только одно значение x, y, а не зацикливаетесь на них, используя цикл while. Поэтому, если размер вашего изображения больше используемого вами ядра, вы не получите все свои пиксели.

Редактировать: я только что кратко взглянул на отчет. Это действительно не очень хорошо. Если вы хотите просто узнать о CUDA, я предлагаю вам приобрести книгу под названием «CUDA by Example».

1 голос
/ 27 марта 2012

Очевидная проблема - это проблема целочисленного усечения / интерполяции.

Одним из способов решения этой проблемы является привязка исходного изображения к текстуре, а затем чтение из текстуры с использованием вычисленных действительных значений координат.Текстуры CUDA дают вам «свободную» аппаратную интерполяцию / фильтрацию.Основным недостатком текстур является то, что интерполяция ограничена 8-битной внутренней точностью, поэтому в некоторых ситуациях она может быть недостаточно точной.Но в качестве первой попытки попробуйте что-то вроде:

 __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); 
    } 
} 

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

Здесь Source_texture - это текстураВы связываете исходные данные с.Вы можете установить поведение поворота края в настройке текстуры, в зависимости от того, как вы хотите справиться с этим.Как настроить и связать текстуру в Разделе 3.2.10.1 Руководства по программированию CUDA 4.1.

Обратите также внимание, что косинус и синус в матрице вращения постоянны для данного значения тета, поэтому было бы многоболее эффективно передавать их ядру в качестве аргумента, а не каждый поток вычислять одинаковые значения.Для поворота на 90 градусов, о котором вы спрашивали, просто вызовите ядро ​​с помощью sintheta=0.f и costheta=1.f, и все готово.

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

Если вы просто хотите наклонить изображение на 90 градусов, вам не понадобятся тригонометрические функции, поскольку вы можете просто поменять местами оси x и y, проходя через пиксели:

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

должен это сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...