Фильтр для обработки изображения на C++

Пишу программу, которая сглаживает изображения от шума вида соль-перец. В программе усредняющий фильтр, медианный и Гауссовский. Начал с усредняющего. Идея такова: Берем изображение, проходимся по нему окном размера kernel*kernel, усредняем все значения, которые находятся под окном, и записываем полученное среднее в новый массив. Краевые случаи не обрабатываем. Моя программа вроде как работает, но изображение становится очень темным. Скажите, пожалуйста, что я делаю не так?

Image blur(Image img, int kernel) {
    Image result;
    result.cols = img.cols - kernel + 1;;
    result.rows = img.rows - kernel + 1;;
    result.data = new char * [result.rows];
    for (size_t i = 0; i < result.rows; ++i) {
        result.data[i] = new char[result.cols];
    }

    for (size_t y = 0; y < result.rows; y++) {
        for (size_t x = 0; x < result.cols; x++) {
            int u = 0;
            for (int h = y; h < y + kernel; h++) {
                for (int w = x; w < x + kernel; w++) {
                    result.data[y][x] += (img.data[h][w]) / ((double)kernel*kernel);
                }
            }
        }
    }
    return result;
}

Где Image - это такая структура

struct Image {
    char** data = nullptr;
    size_t rows = 0;
    size_t cols = 0;
    size_t maxPixelValue = 255;
};

Изображение подается в формате .pgm (интервал значений от 0 до 255).


Ответы (1 шт):

Автор решения: user7860670

Постоянное отбрасывание остатка деления при накоплении результата result.data[y][x] += (img.data[h][w]) / ((double)kernel*kernel); явно будет приводить к резкому уменьшению итогового значения при росте kernel. Следует сначала все суммировать, а только потом поделить, причем избегая преобразований в / из числа с плавающей точкой.

Еще значения явно должны быть беззнаковыми char (::std::uint8_t).

→ Ссылка