Использование фильтра Гаусса в C ++ AMP возвращаются неправильные цвета

Обновить

April 2019

Просмотры

49 раз

1

Я пытаюсь использовать гауссовский фильтр на заданном множестве Мандельброта, и у меня есть решение, которое будет работать последовательно. Тем не менее, я хочу иметь решение, которое работает с использованием обработки GPU.

Я использую C ++ AMP использовать обработку GPU. Проблема с хранением отдельных цветовых каналов пикселей, что в AMP вы не можете использовать неподписанные 8 - битные целые числа ( uint8_t), поэтому я должен был хранить каналы в беззнаковых 32 - битных целых чисел ( uint32_t). Весь синтаксис , что я реализованный в код AMP является таким же , как последовательными один, однако цвет, генерируемым в AMP имеет выход неправильных цветов, однако форму Мандельброта все еще можно увидеть.

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

Последовательный выход введите описание изображения здесь Последовательный код:

void applyFilter(){

    int kernelCentreX, kernelCentreY;// center index of kernel
    int kernelRadius = 5 / 2;
    uint8_t r, g, b;
    float kernelTotal = 0.0;
    float redTotal = 0.0, blueTotal = 0.0, greenTotal = 0.0;
    float sum;

    the_clock::time_point start = the_clock::now();

    for (int y = 0; y < HEIGHT; y++) { //loop through image height
        for (int x = 0; x < WIDTH; x++) {//loop through image width

            float redTotal = 0.0, blueTotal = 0.0, greenTotal = 0.0;
            float kernelTotal = 0.0;

            for (int v = 0; v < 5; v++) { //loop through for kernel height
                for (int u = 0; u < 5; u++) { //loop through for kernel width

                    // Current position
                    int cX = x + u - kernelRadius;
                    int cY = y + v - kernelRadius;

                    //Make sure we stay in boundries
                    if (cX < 0 || cX > WIDTH - 1 || cY < 0 || cY > HEIGHT - 1)
                    {
                        continue;
                    }

                    //Get colour channels of current pixel
                    r = (image[cY][cX] >> 16);
                    g = (image[cY][cX] >> 8);
                    b = (image[cY][cX]);

                    //Get colour channels of current pixel
                    /*r = image[cY][cX] >> 16;
                    g = image[cY][cX] >> 8;
                    b = image[cY][cX];*/

                    //Calculate Totals
                    redTotal += r *kernel[v][u];
                    greenTotal += g *kernel[v][u];
                    blueTotal += b *kernel[v][u];
                    kernelTotal += kernel[v][u];

                }
            }

            //Calculate new pixel values
            r = (redTotal / kernelTotal);
            g = (greenTotal / kernelTotal);
            b = (blueTotal / kernelTotal);

            image[y][x] = (r << 16 | g << 8 | b);

        }
    }

    the_clock::time_point end = the_clock::now();
    auto time_taken = duration_cast<milliseconds>(end - start).count();
    cout << "Time taken to apply kernel(sequential) " << time_taken << "ms" << endl;

}

Параллельный выход введите описание изображения здесь Параллельный код:

void applyFilterAMP() {

    the_clock::time_point start = the_clock::now();

    uint32_t *pImage = &(image[0][0]);
    uint32_t *pFilteredImage = &(filteredImage[0][0]);
    float *pKernel = &(kernel[0][0]);
    uint32_t pi[HEIGHT/3][WIDTH/3][3];
    uint32_t* pPi = &(pi[0][0][0]);

    array_view<float, 2>k(5, 5, pKernel);
    array_view<uint32_t, 2> m(HEIGHT, WIDTH, pImage);
    array_view<uint32_t, 2> fi(HEIGHT, WIDTH, pFilteredImage);
    //array_view<uint32_t, 3> piColor(HEIGHT/3, WIDTH/3, 3, pPi);
    fi.discard_data();

    static const int TileSize = 16;

    parallel_for_each(fi.extent, [=](concurrency::index<2> idx) restrict(amp) {
    //parallel_for_each(fi.extent.tile<TileSize, TileSize>(), [=](tiled_index<TileSize, TileSize> tidx) restrict(amp) {
            int kernelCentreX, kernelCentreY;// center index of kernel
            int kernelRadius = 5/2;
            int y = idx[0];
            int x = idx[1];
            //int y = tidx.global[0];
            //int x = tidx.global[1];

            float kernelTotal = 0.0;
            float redTotal = 0.0, blueTotal = 0.0, greenTotal = 0.0;
            float sum=0.0;

            uint32_t r, g, b, newPixel;

            for (int v = 0; v < 5; v++) { //loop through for kernel height
                for (int u = 0; u < 5; u++) { //loop through for kernel width

                    // Current position
                    int cX = x + u - kernelRadius;
                    int cY = y + v - kernelRadius;
                    //int cX = tidx.global[1] + u - kernelRadius;
                    //int cY = tidx.global[0] + v - kernelRadius;

                    //Make sure we stay in boundries
                    if ((cX < 0 || cX > WIDTH - 1 || cY < 0 || cY > HEIGHT - 1))
                    {
                        continue;
                    }

                    //Get colour channels of pixel
                    r = m[cY][cX] >> 16; 
                    g = m[cY][cX] >> 8;
                    b = m[cY][cX];

                    //Calculate Totals
                    redTotal += r *k[v][u];
                    greenTotal += g *k[v][u];
                    blueTotal += b *k[v][u];
                    kernelTotal += k[v][u];
                }
            }

            //Calculate new pixel values
            r = (redTotal / kernelTotal);
            g = (greenTotal / kernelTotal);
            b = (blueTotal / kernelTotal);

            fi[y][x] = (r << 16 | g << 8 | b);

    });
    fi.synchronize();
    //m.synchronize();
    the_clock::time_point end = the_clock::now();
    auto time_taken = duration_cast<milliseconds>(end - start).count();
    cout << "Time taken to apply kernel(parallel) " << time_taken << "ms" << endl;


    errno_t err = memcpy_s(image, sizeof(uint32_t)*(HEIGHT * WIDTH), filteredImage, sizeof(uint32_t)*(HEIGHT * WIDTH));
    if (err)
    {
        printf("Error executing memcpy_s.\n");
    }

    /*for (int j = 0; j < HEIGHT; j++) {
        for (int i = 0; i < WIDTH; i++) {
            image[j][i] = filteredImage[j][i];
        }
    }*/

}

0 ответы