Кросскорреляция изображений АЭС, не дающая достоверных результатов - PullRequest
0 голосов
/ 08 июля 2019

Я пытаюсь реализовать метод смещения изображения, используя библиотеку кросс-корреляции NPP.

Я попытался создать простое решение, сгенерировав пару простых изображений в памяти, с выводом массивов Npp8u или Npp32f.Однако библиотека взаимной корреляции выдает бессмысленные или недействительные результаты (т. Е. NAN).

int main(int argc, char* argv[])
{
    Npp8u* gpuImg1, * gpuImg2;
    Npp32f *gpuDest;

    cudaDeviceInit(argc, (const char**)argv);

    long dataSize1 = 128;
    auto err = cudaMalloc((void**)&gpuImg1, dataSize1 * dataSize1 * sizeof(unsigned char));
    auto img1Data = static_cast<unsigned char*>(malloc(dataSize1 * dataSize1 * sizeof(unsigned char)));
    memset(img1Data, 0, dataSize1 * dataSize1);

    for(auto y = 40; y < 60; y++)
    {
        for(auto x = 20; x < 40; x++)
        {
            img1Data[y * dataSize1 + x] = 0xff;
        }
    }

    long dataSize2 = 64;
    err = cudaMalloc((void**)&gpuImg2, dataSize2);
    auto img2data = static_cast<unsigned char*>(malloc(dataSize2 * dataSize2 * sizeof(unsigned char)));
    memset(img2data, 0, dataSize2 * dataSize2);

    for (auto y = 10; y < 30; y++)
    {
        for (auto x = 20; x < 40; x++)
        {
            img2data[y * dataSize2 + x] = 0xff;
        }
    }

    auto resSize = (dataSize1 - dataSize2) + 1;
    err = cudaMalloc((void**)&gpuDest, resSize * resSize * sizeof(Npp32f));
    auto resData = static_cast<Npp32f*>(malloc(resSize * resSize * sizeof(Npp32f)));

    NppiSize nppiSize1;
    nppiSize1.height = dataSize1;
    nppiSize1.width = dataSize1;

    NppiSize nppiSize2;
    nppiSize2.height = dataSize2;
    nppiSize2.width = dataSize2;

    err = cudaMemcpy(gpuImg1, img1Data, dataSize1, cudaMemcpyHostToDevice);
    err = cudaMemcpy(gpuImg2, img2data, dataSize2, cudaMemcpyHostToDevice);

    auto status = nppiCrossCorrValid_Norm_8u32f_C1R(gpuImg1, dataSize1, nppiSize1, gpuImg2, dataSize2, nppiSize2, gpuDest, resSize * sizeof(Npp32f));

    err = cudaMemcpy(resData, gpuDest, resSize * resSize * sizeof(Npp8u), cudaMemcpyDeviceToHost);

}

И методы CUDA, и метод NPP возвращают сообщения об успехе, поэтому я почти уверен, что я что-то не так делаюс настройкой взаимной корреляции.Кто-нибудь может помочь подтолкнуть меня в правильном направлении для решения?

1 Ответ

4 голосов
/ 08 июля 2019

Кажется, есть две категории проблем с вашим кодом.

Во-первых, у вас есть различные проблемы с размерами данных.Не уверен, где находится разъединение, так как некоторые из них вы имеете право, поэтому я просто укажу на то, что вижу.

Эта конструкция верна:

auto err = cudaMalloc((void**)&gpuImg1, dataSize1 * dataSize1 * sizeof(unsigned char));

Вы должнысделали то же самое здесь:

err = cudaMalloc((void**)&gpuImg2, dataSize2);

Это не правильно.cudaMemcpy, как memcpy, и как cudaMalloc принимает параметр размера в байтах:

err = cudaMemcpy(gpuImg1, img1Data, dataSize1, cudaMemcpyHostToDevice);
err = cudaMemcpy(gpuImg2, img2data, dataSize2, cudaMemcpyHostToDevice);
                                    ^^^^^^^^^

Вы получили его почти правильно на следующей копии с устройства на хост, за исключением того, что ваш sizeofдолжно быть для правильного типа:

err = cudaMemcpy(resData, gpuDest, resSize * resSize * sizeof(Npp8u), cudaMemcpyDeviceToHost);
                                                              ^^^^^

Во-вторых, вы используете нормализованную версию взаимной корреляции.Если вы изучите документацию , я полагаю, вы обнаружите, что знаменатель может быть рассчитан как корень квадратный из нуля, когда большие части вашего изображения имеют нулевое значение.В любом случае, когда я конвертирую «фон» из 0 в 1, я получаю ощутимые результаты.Другой вариант - переключиться на ненормализованную версию функции (nppiCrossCorrValid_8u32f_C1R), которая также дает результаты, отличные от NAN, даже с большими областями нулевого «фона».

Вот исправленная версия,Я думаю, что это даст вам результаты не NAN:

# cat t14.cu
#include <npp.h>
#include <iostream>
int main(int argc, char* argv[])
{
    Npp8u* gpuImg1, * gpuImg2;
    Npp32f *gpuDest;

   // cudaDeviceInit(argc, (const char**)argv);

    long dataSize1 = 128;
    auto err = cudaMalloc((void**)&gpuImg1, dataSize1 * dataSize1 * sizeof(unsigned char));
    unsigned char *img1Data = static_cast<unsigned char*>(malloc(dataSize1 * dataSize1 * sizeof(unsigned char)));
    memset(img1Data, 1, dataSize1 * dataSize1);

    for(auto y = 40; y < 60; y++)
    {
        for(auto x = 20; x < 40; x++)
        {
            img1Data[y * dataSize1 + x] = 0xff;
        }
    }

    long dataSize2 = 64;
    err = cudaMalloc((void**)&gpuImg2, dataSize2*dataSize2 *sizeof(unsigned char));
    unsigned char *img2data = static_cast<unsigned char*>(malloc(dataSize2 * dataSize2 * sizeof(unsigned char)));
    memset(img2data, 1, dataSize2 * dataSize2);

    for (auto y = 10; y < 30; y++)
    {
        for (auto x = 20; x < 40; x++)
        {
            img2data[y * dataSize2 + x] = 0xff;
        }
    }

    auto resSize = (dataSize1 - dataSize2) + 1;
    err = cudaMalloc((void**)&gpuDest, resSize * resSize * sizeof(Npp32f));
    auto resData = static_cast<Npp32f*>(malloc(resSize * resSize * sizeof(Npp32f)));

    NppiSize nppiSize1;
    nppiSize1.height = dataSize1;
    nppiSize1.width = dataSize1;

    NppiSize nppiSize2;
    nppiSize2.height = dataSize2;
    nppiSize2.width = dataSize2;

    err = cudaMemcpy(gpuImg1, img1Data, dataSize1*dataSize1*sizeof(unsigned char), cudaMemcpyHostToDevice);
    err = cudaMemcpy(gpuImg2, img2data, dataSize2*dataSize2*sizeof(unsigned char), cudaMemcpyHostToDevice);

    auto status = nppiCrossCorrValid_Norm_8u32f_C1R(gpuImg1, dataSize1, nppiSize1, gpuImg2, dataSize2, nppiSize2, gpuDest, resSize * sizeof(Npp32f));

    err = cudaMemcpy(resData, gpuDest, resSize * resSize * sizeof(Npp32f), cudaMemcpyDeviceToHost);
    for (int i = 0; i < resSize*2; i++)
      std::cout << resData[i] << ",";
    std::cout << std::endl;
}
# nvcc -std=c++11 -o t14 t14.cu -lnppc -lnppist
# cuda-memcheck ./t14
========= CUDA-MEMCHECK
0.00796924,0.00796924,0.00796924,0.00796924,0.00796924,0.00796924,0.00796924,0.00796924,0.00796924,0.00796924,0.00796924,0.00796924,0.00796924,0.00796925,0.00796925,0.00796925,0.00796925,0.00796925,0.00796925,0.00796925,0.00796925,0.00797587,0.00798853,0.00800826,0.00803633,0.00807432,0.00812423,0.00818861,0.00827071,0.00837505,0.00850754,0.00867648,0.00889385,0.00917761,0.00955609,0.0100771,0.0108291,0.0119988,0.0140744,0.0190166,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.00796925,0.00796925,0.00796925,0.00796925,0.00796925,0.00796925,0.00796925,0.00796925,0.00796925,0.00796925,0.00796925,0.00796925,0.00796925,0.00796925,0.00796925,0.00796925,0.00796925,0.00796926,0.00796926,0.00796926,0.00796926,0.00797588,0.00798854,0.00800827,0.00803634,0.00807434,0.00812425,0.00818863,0.00827071,0.00837505,0.00850754,0.00867648,0.00889385,0.00917761,0.00955609,0.0100771,0.0108291,0.0119988,0.0140744,0.0190166,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,0.323817,
========= ERROR SUMMARY: 0 errors
#
...