首页 > 解决方案 > 试图在 C++ 中“模糊”矩阵;有缺陷的算法或代码?

问题描述

问题

我正在尝试使用 koef (见下文)“模糊”一个矩阵(就像你对图像一样),但它没有按照我想要的方式工作。我通过 .txt 文件提供矩阵。

什么是koef?

这个网站很好地解释了它是如何工作的。对于这种模糊,我使用 koef 为 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

​</p>

“模糊”后的实际矩阵

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

​</p>


编辑:我更新了我的代码以反映所做的两个更正;第一个修正是第一个条件块中的 [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

标签: c++image-processingmatrixblur

解决方案


您应该通过权重的总和进行归一化(除以),而不是输入像素值(或矩阵值,如果您愿意)的总和。

例如,第一种情况是:

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);

推荐阅读