2013-02-05 10 views
5

Sto cercando di risolvere un problema in cui dovrei cambiare un'immagine a colori in un'immagine in scala di grigi. Per questo scopo sto usando un approccio parallelo CUDA.

Il codice kerne che sto invocando sulla GPU è il seguente.immagine colorata in scala di grigi usando elaborazione parallela CUDA

__global__ 
void rgba_to_greyscale(const uchar4* const rgbaImage, 
        unsigned char* const greyImage, 
        int numRows, int numCols) 
{ 
    int absolute_image_position_x = blockIdx.x; 
    int absolute_image_position_y = blockIdx.y; 

    if (absolute_image_position_x >= numCols || 
    absolute_image_position_y >= numRows) 
{ 
    return; 
} 
uchar4 rgba = rgbaImage[absolute_image_position_x + absolute_image_position_y]; 
float channelSum = .299f * rgba.x + .587f * rgba.y + .114f * rgba.z; 
greyImage[absolute_image_position_x + absolute_image_position_y] = channelSum; 

} 

void your_rgba_to_greyscale(const uchar4 * const h_rgbaImage, 
          uchar4 * const d_rgbaImage, 
          unsigned char* const d_greyImage, 
          size_t numRows, 
          size_t numCols) 
{ 
    //You must fill in the correct sizes for the blockSize and gridSize 
    //currently only one block with one thread is being launched 
    const dim3 blockSize(numCols/32, numCols/32 , 1); //TODO 
    const dim3 gridSize(numRows/12, numRows/12 , 1); //TODO 
    rgba_to_greyscale<<<gridSize, blockSize>>>(d_rgbaImage, 
              d_greyImage, 
              numRows, 
              numCols); 

    cudaDeviceSynchronize(); checkCudaErrors(cudaGetLastError()); 
} 


vedo una linea di punti nella prima riga di pixel.

errore sto ottenendo è errore

libdc1394: Impossibile inizializzare libdc1394
di differenza al pos 51 supera tolleranza del 5
Riferimento: 255
GPU: 0
my input/output images Qualcuno mi può aiutare con questo ??? Grazie in anticipo.

+1

Si prega di dare alla vostra domanda un titolo più significativo.Così com'è, non significa assolutamente niente per nessuno tranne te. Come farebbe una ricerca con una simile domanda di elaborazione delle immagini * mai *? – talonmies

+0

@talonmies: spero che il titolo abbia senso ora. –

+2

Questo è un compito del corso "Introduzione alla programmazione parallela" su Udacity. Dovresti risolverlo da solo e non usare stackowerflow per ottenerlo risolto dagli altri. – RoBiK

risposta

5

Ora, da quando ho postato questa domanda ho lavorato costantemente su questo problema
ci sono un paio di miglioramenti che dovrebbero essere fatti al fine di ottenere questo problema corretto ora mi rendo conto della mia soluzione iniziale era sbagliata .
modifiche da compiere: -

1. absolute_position_x =(blockIdx.x * blockDim.x) + threadIdx.x; 
2. absolute_position_y = (blockIdx.y * blockDim.y) + threadIdx.y; 

secondo luogo,

1. const dim3 blockSize(24, 24, 1); 
2. const dim3 gridSize((numCols/16), (numRows/16) , 1); 

Nella soluzione stiamo usando una griglia di numColonne/16 * numColonne/16
e del blocco di 24 * 24

codice eseguito in 0,040576 ms

@datenwolf: grazie per aver risposto sopra !!!

+2

qualche idea sul perché blockSize deve essere '24,24' e gridSize' numCols/16, numRows/16'? C'è una ragione per cui? Può funzionare un altro numero? – alvas

1

libdc1394 error: Failed to initialize libdc1394

Non credo che questo sia un problema CUDA. libdc1394 è una libreria utilizzata per accedere ai dispositivi video IEEE1394 aka FireWire o iLink (videocamere DV, fotocamera Apple iSight). Quella libreria non viene inizializzata correttamente, quindi non ottieni risultati utili. Fondamentalmente è NINO: Nonsens In Nonsens Out.

+0

@datewolf si prega di vedere ho aggiunto un link per l'output di immagine di input/output che sto ottenendo. –

+0

quello che vedo è un errore in pos 51 supera il tolernace di 5 quindi sto indovinando se è relativo al modello di colore e non qualsiasi altro errore di tipo linker. –

+0

@ ashish173: Non si tratta di un problema di collegamento, è un problema di runtime. La libreria dc1394 non riesce a inizializzarsi correttamente all'avvio del programma e probabilmente produrrà solo spazzatura quando viene utilizzata per recuperare le immagini. È necessario prima correggere il problema di inizializzazione (questa è una cosa di runtime, cioè qualcosa che devi codificare). – datenwolf

0

Si esegue seguente numero di blocchi e griglie:

const dim3 blockSize(numCols/32, numCols/32 , 1); //TODO 
    const dim3 gridSize(numRows/12, numRows/12 , 1); //TODO 

ancora non si utilizza qualsiasi thread nel codice del kernel!

int absolute_image_position_x = blockIdx.x; 
int absolute_image_position_y = blockIdx.y; 

pensare questo modo, la larghezza di un'immagine può essere dividere in absolute_image_position_x parti della colonna e l'altezza di un'immagine può essere dividere in absolute_image_position_y parti della fila. Ora il riquadro di ciascuna sezione trasversale che crea è necessario modificare/ridisegnare tutti i pixel in termini di greyImage, in parallelo. Abbastanza spoiler per un incarico :)

+0

thnks per rispondere ho capito, non stavo usando alcun thread che era così stupido da parte mia. –

1

il calcolo di x assoluto x & posizioni di immagine è perfetto. ma quando hai bisogno di accedere a quel particolare pixel dell'immagine colorata, non dovresti usare il seguente codice ??

uchar4 rgba = rgbaImage[absolute_image_position_x + (absolute_image_position_y * numCols)]; 

ho pensato così, quando si confrontano a un codice che ci scrive per eseguire lo stesso problema in codice seriale. Per favore fatemi sapere :)

1

Si dovrebbe ancora avere un problema con il tempo di esecuzione - la conversione non darà un risultato corretto.

Le linee:

  1. uchar4 RGBA = rgbaImage [absolute_image_position_x + absolute_image_position_y];
  2. greyImmagine [absolute_image_position_x + absolute_image_position_y] = channelSum;

dovrebbe essere cambiata a:

  1. uchar4 rgba = rgbaImage [absolute_image_position_x + absolute_image_position_y * numColonne];
  2. greyImmagine [absolute_image_position_x + absolute_image_position_y * numCols] = channelSum;
1
__global__ 
void rgba_to_greyscale(const uchar4* const rgbaImage, 
         unsigned char* const greyImage, 
         int numRows, int numCols) 
{ 
    int rgba_x = blockIdx.x * blockDim.x + threadIdx.x; 
    int rgba_y = blockIdx.y * blockDim.y + threadIdx.y; 
    int pixel_pos = rgba_x+rgba_y*numCols; 

    uchar4 rgba = rgbaImage[pixel_pos]; 
    unsigned char gray = (unsigned char)(0.299f * rgba.x + 0.587f * rgba.y + 0.114f * rgba.z); 
    greyImage[pixel_pos] = gray; 
} 

void your_rgba_to_greyscale(const uchar4 * const h_rgbaImage, uchar4 * const d_rgbaImage, 
          unsigned char* const d_greyImage, size_t numRows, size_t numCols) 
{ 
    //You must fill in the correct sizes for the blockSize and gridSize 
    //currently only one block with one thread is being launched 
    const dim3 blockSize(24, 24, 1); //TODO 
    const dim3 gridSize(numCols/24+1, numRows/24+1, 1); //TODO 
    rgba_to_greyscale<<<gridSize, blockSize>>>(d_rgbaImage, d_greyImage, numRows, numCols); 

    cudaDeviceSynchronize(); checkCudaErrors(cudaGetLastError()); 
} 
+0

sebbene si possa ottenere la risposta giusta, lo si fa in un modo molto strano. Si passano colonne in cui le righe devono essere passate nel gridsize e la formula per pixel_pos non è legata allo std. modo di appiattire un array 2d in un array 1d ... dovrebbe essere numRows * y + x, o numCols * x + y, ma tutto funziona fuori b/c il tuo gird è impostato su cols, righe invece di righe, cols – labheshr

0

stesso codice con con la capacità di gestire immagini in formato di input non standard

int idx=blockDim.x*blockIdx.x+threadIdx.x; 
int idy=blockDim.y*blockIdx.y+threadIdx.y; 

uchar4 rgbcell=rgbaImage[idx*numCols+idy]; 

    greyImage[idx*numCols+idy]=0.299*rgbcell.x+0.587*rgbcell.y+0.114*rgbcell.z; 


    } 

    void your_rgba_to_greyscale(const uchar4 * const h_rgbaImage, uchar4 * const d_rgbaImage, 
         unsigned char* const d_greyImage, size_t numRows, size_t numCols) 
{ 
//You must fill in the correct sizes for the blockSize and gridSize 
//currently only one block with one thread is being launched 

int totalpixels=numRows*numCols; 
int factors[]={2,4,8,16,24,32}; 
vector<int> numbers(factors,factors+sizeof(factors)/sizeof(int)); 
int factor=1; 

    while(!numbers.empty()) 
    { 
if(totalpixels%numbers.back()==0) 
{ 
    factor=numbers.back(); 
    break; 
} 
    else 
    { 
    numbers.pop_back(); 
    } 
} 



const dim3 blockSize(factor, factor, 1); //TODO 
const dim3 gridSize(numRows/factor+1, numCols/factor+1,1); //TODO 
rgba_to_greyscale<<<gridSize, blockSize>>>(d_rgbaImage, d_greyImage, numRows, numCols); 
0

L'errore libdc1394 non è correlato a FireWire, ecc, in questo caso - è la libreria che Udacity sta usando per confrontare l'immagine creata dal programma con l'immagine di riferimento. E quello che sta dicendo è che la differenza tra la tua immagine e l'immagine di riferimento è stata superata da una soglia specifica, per quella posizione cioè. pixel.

5

Recentemente ho aderito a questo corso e ho provato la soluzione ma non funziona così, ho provato il mio. Sei quasi corretto. La soluzione corretta è questa:

__global__` 
void rgba_to_greyscale(const uchar4* const rgbaImage, 
       unsigned char* const greyImage, 
       int numRows, int numCols) 
{` 

int pos_x = (blockIdx.x * blockDim.x) + threadIdx.x; 
int pos_y = (blockIdx.y * blockDim.y) + threadIdx.y; 
if(pos_x >= numCols || pos_y >= numRows) 
    return; 

uchar4 rgba = rgbaImage[pos_x + pos_y * numCols]; 
greyImage[pos_x + pos_y * numCols] = (.299f * rgba.x + .587f * rgba.y + .114f * rgba.z); 

} 

Il resto è uguale al codice.

+0

puoi spiegare la formula: pos_x + pos_y * numCols? – labheshr

+0

non importa: questo ha risposto alla mia domanda https://stackoverflow.com/questions/2151084/map-a-2d-array-onto-a-1d-array-c – labheshr

2

Poiché non si è a conoscenza delle dimensioni dell'immagine. È meglio scegliere qualsiasi dimensione ragionevole del blocco bidimensionale dei thread e quindi verificare due condizioni. Il primo è che gli indici pos_x e pos_y nel kernel non superano numRows e numCols. In secondo luogo, la dimensione della griglia dovrebbe essere appena sopra il numero totale di thread in tutti i blocchi.

const dim3 blockSize(16, 16, 1); 
const dim3 gridSize((numCols%16) ? numCols/16+1 : numCols/16, 
(numRows%16) ? numRows/16+1 : numRows/16, 1); 
0

1- int x =(blockIdx.x * blockDim.x) + threadIdx.x;

2- int y = (blockIdx.y * blockDim.y) + threadIdx.y;

E nella griglia e blocco dimensioni

1- const dim3 blockSize(32, 32, 1);

2- const dim3 gridSize((numCols/32+1), (numRows/32+1) , 1);

codice eseguito in 0. 036992 ms.

0
const dim3 blockSize(16, 16, 1); //TODO 
const dim3 gridSize((numRows+15)/16, (numCols+15)/16, 1); //TODO 

int x = blockIdx.x * blockDim.x + threadIdx.x; 
int y = blockIdx.y * blockDim.y + threadIdx.y; 

uchar4 rgba = rgbaImage[y*numRows + x]; 
float channelSum = .299f * rgba.x + .587f * rgba.y + .114f * rgba.z; 
greyImage[y*numRows + x] = channelSum;