Попытка «размыть» матрицу в C ++;неисправный алгоритм или код? - PullRequest
1 голос
/ 29 марта 2019

Выпуск

Я пытаюсь «размыть» матрицу (как вы бы сделали изображение), используя koef (см. Ниже), и она не работает так, как я хочу. Я предоставляю матрицу через файл .txt.

Что такое коэф?

Этот сайт прекрасно объясняет, как он работает. Для этого размытия я использую «Blur Light» с коэффициентом 14, который является суммой следующей матрицы 3x3 (которая представляет плотность размытия):

1 2 1
2 2 2
1 2 1

Вероятно, есть более простой способ сделать это вместо того, чтобы жестко кодировать то же самое девять раз. У меня также есть нарисованные от руки диаграммы, представляющие циклические / условные структуры и то, что они на самом деле делают, если это будет полезно.

void blur(int pic[][MAX_COL]/*OUT*/, int height, int width)
{
    int newPic[MAX_ROW][MAX_COL] = {0};

    for (int h = 0; h < height; h++)
    {
        for (int w = 0; w < width; w++)
        {
            if (h == 0 && w == 0)
                newPic[h][w] = (2 * pic[h][w] + 2 * pic[h][w-1] + 2 * pic[h+1][w] + 1 * pic[h+1][w-1])
                                /(pic[h][w] + pic[h][w-1] + pic[h+1][w] + pic[h+1][w-1]);
            else if (h == height - 1 && w == width - 1)
                newPic[h][w] = (2 * pic[h][w] + 2 * pic[h-1][w] + 2 * pic[h][w-1] + 1 * pic[h-1][w-1])
                                /(pic[h][w] + pic[h-1][w] + pic[h][w-1] + pic[h-1][w-1]);
            else if (h == height - 1 && w == 0)
                newPic[h][w] = (2 * pic[h][w] + 2 * pic[h-1][w] + 2 * pic[h][w+1] + 1 * pic[h-1][w+1])
                /(pic[h][w] + pic[h-1][w] + pic[h][w+1] + pic[h-1][w+1]);
            else if (h == 0 && w == width - 1)
                newPic[h][w] = (2 * pic[h][w] + 2 * pic[h][w-1] + 2 * pic[h+1][w] + 1 * pic[h+1][w-1])
                /(pic[h][w] + pic[1][w-1] + pic[h+1][w] + pic[h+1][w-1]);
            else if (h == 0 && (w != 0 && w != width - 1))
                newPic[h][w] = (2 * pic[h][w] + 2 * pic[h+1][w] + 2 * pic[h-1][w] + 2 * pic[h][w+1]
                                + 1 * pic[h+1][w+1] + 1 * pic[h-1][w+1])/(pic[h][w] + pic[h+1][w] + pic[h-1][w]
                                + pic[h][w+1] + pic[h+1][w+1] + pic[h-1][w+1]);
            else if (w == 0 && (h != 0 && h != height - 1))
                newPic[h][w] = (2 * pic[h][w] + 2 * pic[h+1][w] + 2 * pic[h][w+1] + 2 * pic[h][w-1] + 1 * pic[h+1][w+1]
                                + 1 * pic[h+1][w-1])/(pic[h][w] + pic[h+1][w] + pic[h][w+1] + pic[h][w-1]
                                + pic[h+1][w+1] + pic[h+1][w-1]);
            else if (h == height - 1 && (w != 0 && w != width - 1))
                newPic[h][w] = (2 * pic[h][w] + 2 * pic[h+1][w] + 2 * pic[h-1][w] + 2 * pic[h][w-1] + 1 * pic[h+1][w-1]
                                + 1 * pic[h-1][w-1])/(pic[h][w] + pic[h+1][w] + pic[h-1][w] + pic[h][w-1]
                                + pic[h+1][w-1] + pic[h-1][w-1]);
            else if (w == width - 1 && (h != 0 && h != height - 1))
                newPic[h][w] = (2 * pic[h][w] + 2 * pic[h][w+1] + 2 * pic[h][w-1] + 2 * pic[h-1][w] + 1 * pic[h-1][w+1]
                                + 1 * pic[h-1][w-1])/(pic[h][w] + pic[h][w+1] + pic[h][w-1] + pic[h-1][w]
                                + pic[h-1][w+1] + pic[h-1][w-1]);
            else
                newPic[h][w] = (1 * pic[h-1][w-1] + 2 * pic[h-1][w] + 1 * pic[h-1][w+1] + 2 * pic[h][w-1]
                                + 2 * pic[h][w] + 2 * pic[h][w+1] + 1 * pic[h+1][w-1] + 2 * pic[h+1][w] + 1
                                * pic[h+1][w+1]) / (pic[h][w] + pic[h-1][w-1] + pic[h-1][w] + pic[h-1][w+1]
                                + pic[h][w-1] + pic[h][w+1] + pic[h+1][w-1] + pic[h+1][w]);
        }
    }
    memcpy(pic, newPic, sizeof(newPic));
}

Предоставленная матрица

10 100 10 100 10 100
10 100 10 100 10 100
100 10 100 10 100 10
100 10 100 10 100 10

Желаемая матрица после «размытия»

48 46 64 46 64 61
55 48 61 48 61 55
55 61 48 61 48 55
61 64 46 64 46 48

& # x200B;

Фактическая матрица после "размытия"

2 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1
1 1 1 1 1 1

& # x200B;


Редактировать: Я обновил свой код, чтобы отразить две сделанные поправки; первая исправленная ошибка была [w-1] вместо [w + 1] в первом условном блоке, а вторая исправленная ошибка делилась на сумму плотностей соседей (а не сумму значений).

Обновлен кодовый блок

if (h == 0 && w == 0)
  newPic[h][w] = (2 * pic[h][w] + 2 * pic[h][w+1] + 2 * pic[h+1][w] + 1 * pic[h+1][w+1])/7;
else if (h == height - 1 && w == width - 1)
  newPic[h][w] = (2 * pic[h][w] + 2 * pic[h-1][w] + 2 * pic[h][w-1] + 1 * pic[h-1][w-1])/7;
else if (h == height - 1 && w == 0)
  newPic[h][w] = (2 * pic[h][w] + 2 * pic[h-1][w] + 2 * pic[h][w+1] + 1 * pic[h-1][w+1])/7;
else if (h == 0 && w == width - 1)
  newPic[h][w] = (2 * pic[h][w] + 2 * pic[h][w-1] + 2 * pic[h+1][w] + 1 * pic[h+1][w-1])/7;
else if (h == 0 && (w != 0 && w != width - 1))
  newPic[h][w] = (2 * pic[h][w] + 2 * pic[h+1][w] + 2 * pic[h-1][w] + 2 * pic[h][w+1] + 1 * pic[h+1][w+1] + 1 * pic[h-1][w+1])/10;
else if (w == 0 && (h != 0 && h != height - 1))
  newPic[h][w] = (2 * pic[h][w] + 2 * pic[h+1][w] + 2 * pic[h][w+1] + 2 * pic[h][w-1] + 1 * pic[h+1][w+1] + 1 * pic[h+1][w-1])/10;
else if (h == height - 1 && (w != 0 && w != width - 1))
  newPic[h][w] = (2 * pic[h][w] + 2 * pic[h+1][w] + 2 * pic[h-1][w] + 2 * pic[h][w-1] + 1 * pic[h+1][w-1] + 1 * pic[h-1][w-1])/10;
else if (w == width - 1 && (h != 0 && h != height - 1))
  newPic[h][w] = (2 * pic[h][w] + 2 * pic[h][w+1] + 2 * pic[h][w-1] + 2 * pic[h-1][w] + 1 * pic[h-1][w+1] + 1 * pic[h-1][w-1])/10;
else
  newPic[h][w] = (1 * pic[h-1][w-1] + 2 * pic[h-1][w] + 1 * pic[h-1][w+1] + 2 * pic[h][w-1] + 2 * pic[h][w] + 2 * pic[h][w+1] + 1 * pic[h+1][w-1] + 2 * pic[h+1][w] + 1 * pic[h+1][w+1]) / 14;

Обновлен вывод

48  43  34  43  34  61
43  48  61  48  61  43
43  61  48  61  48  43
61  34  43  34  43  48

Edit2: Оказывается, я огромный дурак, и мои ряды и колонны перевернулись в моей голове. Следующее работает правильно, еще раз спасибо всем за помощь!

Обновлен кодовый блок

// top left corner
if (h == 0 && w == 0)
    newPic[h][w] = (2 * pic[h][w] + 2 * pic[h][w+1] + 2 * pic[h+1][w] + 1 * pic[h+1][w+1])/7;
// bottom right corner
else if (h == height - 1 && w == width - 1)
    newPic[h][w] = (2 * pic[h][w] + 2 * pic[h-1][w] + 2 * pic[h][w-1] + 1 * pic[h-1][w-1])/7;
// top right corner
else if (h == height - 1 && w == 0)
    newPic[h][w] = (2 * pic[h][w] + 2 * pic[h-1][w] + 2 * pic[h][w+1] + 1 * pic[h-1][w+1])/7;
// bottom left corner
else if (h == 0 && w == width - 1)
    newPic[h][w] = (2 * pic[h][w] + 2 * pic[h][w-1] + 2 * pic[h+1][w] + 1 * pic[h+1][w-1])/7;
// top edges
else if (h == 0 && (w != 0 && w != width - 1))
    newPic[h][w] = (2 * pic[h][w] + 2 * pic[h][w+1] + 2 * pic[h][w-1] + 2 * pic[h+1][w]
                    + 1 * pic[h+1][w+1] + 1 * pic[h+1][w-1])/10;
// left edges
else if (w == 0 && (h != 0 && h != height - 1))
    newPic[h][w] = (2 * pic[h][w] + 2 * pic[h][w+1] + 2 * pic[h+1][w] + 2 * pic[h-1][w] + 1 * pic[h+1][w+1]
                    + 1 * pic[h-1][w+1])/10;
// bottom edges
else if (h == height - 1 && (w != 0 && w != width - 1))
    newPic[h][w] = (2 * pic[h][w] + 2 * pic[h][w+1] + 2 * pic[h][w-1] + 2 * pic[h-1][w] + 1 * pic[h-1][w+1]
                    + 1 * pic[h-1][w-1])/10;
// right edges
else if (w == width - 1 && (h != 0 && h != height - 1))
    newPic[h][w] = (2 * pic[h][w] + 2 * pic[h+1][w] + 2 * pic[h-1][w] + 2 * pic[h][w-1] + 1 * pic[h+1][w-1]
                    + 1 * pic[h-1][w-1])/10;
// middle cells
else
    newPic[h][w] = (1 * pic[h-1][w-1] + 2 * pic[h-1][w] + 1 * pic[h-1][w+1] + 2 * pic[h][w-1]
                    + 2 * pic[h][w] + 2 * pic[h][w+1] + 1 * pic[h+1][w-1] + 2 * pic[h+1][w] + 1
                    * pic[h+1][w+1]) / 14;

Обновлен вывод

48  46  64  46  64  61
55  48  61  48  61  55
55  61  48  61  48  55
61  64  46  64  46  48

Ответы [ 2 ]

1 голос
/ 29 марта 2019

Вам следует нормализовать (разделить) на сумму весов, а не сумму значений входных пикселей (или значений матрицы, если вы предпочитаете).

Например, первый случай будет:

newPic[h][w] = (2 * pic[h][w] + 2 * pic[h][w-1] + 2 * pic[h+1][w] + 1 * pic[h+1][w-1])
             / (2 + 2 + 2 + 1);
0 голосов
/ 29 марта 2019

Вы делите на слишком большое число. В общем случае вы должны делить на 14.

else
    newPic[h][w] = (1 * pic[h-1][w-1] + 2 * pic[h-1][w] + 1 * pic[h-1][w+1] + 2 * pic[h][w-1]
    + 2 * pic[h][w] + 2 * pic[h][w+1] + 1 * pic[h+1][w-1] + 2 * pic[h+1][w] + 1
    * pic[h+1][w+1]) / 14;

(это потому, что 14 = 1 + 2 + 1 + 2 + 2 + 2 + 1 + 2 + 1)

В остальных случаях делим на любую сумму коэффициентов для этого случая.

...