2D свертка Blur с отделимым ядром - PullRequest
1 голос
/ 30 января 2020

Я пытаюсь свернуть размытие с помощью пользовательского массива float.

Мой массив определен как float array[width*height]. Я отредактировал эти функции, чтобы он мог работать с пользовательским массивом, а не только с OpenCV cv::Mat

Мой код выглядит так:

int reflect(int M, int x)
{
    if(x < 0)
    {
        return -x - 1;
    }
    if(x >= M)
    {
        return 2*M - x - 1;
    }

    return x;
}

void separable2DConvolution(float * data, Size dataSize, float *kernel, int kernelSize)
{
    // make copy of original image
    float * dataCopy = new float[dataSize.width()*dataSize.height()];
    memcpy(dataCopy, data, dataSize.width()*dataSize.height());
    float * temp = new float[dataSize.width()*dataSize.height()];
    memcpy(temp, data, dataSize.width()*dataSize.height());

    float sum;
    int x1, y1;
    int kernelRadius = floor(kernelSize/2);

    // along y - direction
    for(int y = 0; y < dataSize.height(); y++){
        for(int x = 0; x < dataSize.width(); x++){
            sum = 0.0;
            for(int i = -kernelRadius; i <= kernelRadius; i++){
                y1 = reflect(dataSize.height(), y - i);
                sum = sum + kernel[i + kernelRadius]*dataCopy[y1*x+y1];
            }
            temp[y*x+y] = sum;
        }
    }

    // along x - direction
    for(int y = 0; y < dataSize.height(); y++){
        for(int x = 0; x < dataSize.width(); x++){
            sum = 0.0;
            for(int i = -kernelRadius; i <= kernelRadius; i++){
                x1 = reflect(dataSize.width(), x - i);
                sum = sum + kernel[i + kernelRadius]*temp[x1*y+x1];
            }
            data[x*y+y] = sum;
        }
    }

    delete [] temp;
    delete [] dataCopy;
}

Передан массив separable2DConvolution, как data, Size - это пользовательский класс с определенной шириной и высотой (оба значения допустимы и больше 0), kernel - нормализованный гауссовский массив (почти такой же, как у cv::getGaussianKernel) и kernelSize - размер массива Гаусса (я использую размер 11).

Я использую эту функцию для замены cv::sepFilter2D из OpenCV , но каким-то образом выводим это отличается. После использования моей функции я конвертирую изображение, чтобы увидеть разницу.

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

В чем проблема с моим кодом?

Спасибо за помощь!

1 Ответ

2 голосов
/ 30 января 2020

Ваша подписка на сохранение суммы пикселей неверна. temp[y*x+y] запишет все результаты для первого столбца в первый пиксель (temp[0]). Многие другие пиксели останутся неизменными. Вы, вероятно, захотите temp[y * dataSize.width() + x], с аналогичным изменением для data[x*y+y] в следующем l oop и при расчете индексов для чтения значений пикселей.

Не связано, вам не нужно memcpy растровое изображение для создания копий, так как вы должны записывать каждый пиксель изображения. Вам вообще не нужно dataCopy, поскольку исходный массив data еще не был изменен.

Использование floor для целого числа излишне. Поскольку kernelSize является положительным, вы можете просто сказать int kernelRadius = kernelSize / 2;, так как это будет округляться.

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