首页 > 解决方案 > OpenCV C++ - 如何用 3x3 邻域中的灰度平均值替换每个像素的值?

问题描述

我是 OpenCV(在 C++ 中)和图像处理的新手。我想,给定一个灰度图像来替换每个像素的值,计算 3x3 邻域中灰度的平均值。

首先我打开图片

Mat img = imread(samples::findFile(argv[1]), IMREAD_GRAYSCALE);

// Example of image
[4 3 9 1,
 2 9 8 0,
 3 5 2 1,
 7 5 8 3]

为了获得角的 3x3 最接近像素的平均值(左上角、右上角、左下角和右下角),我对图像进行了填充:1x1x1x1 恒定边框

Mat imgPadding;
copyMakeBorder(img, imgPadding, 1,1,1,1, BORDER_CONSTANT, Scalar(0));

// Padding example
[0 0 0 0 0 0,
 0 4 3 9 1 0,
 0 2 9 8 0 0,
 0 3 5 2 1 0,
 0 7 5 8 3 0,
 0 0 0 0 0 0]

现在我在输出图像上遇到了一些问题。我尝试了各种方式,但没有办法让我找到解决方案。我试过这个,使用mean() 函数来获取第 i,j-th 3x3 矩阵的平均灰度值,使用Rect() 方法。for 循环从第一个非填充像素开始,到最后一个非填充像素结束。

Mat imgAvg = Mat::zeros(img.rows, img.cols, img.type());
// initialization of the output Mat object with same input size and type

for (int i = 1; i < imgAvg.rows; i++)
    for (int j = 1; j < imgAvg.cols; j++) 
        imgAvg.at<Scalar>(Point(j - 1, i - 1)) = mean(imgPadding(Rect(j - 1, i - 1, 3, 3)));

但我得到了这个运行时错误

main: malloc.c:2379: sysmalloc: Assertion `(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed.

我也尝试随机减少范围

for (int i = 1; i < imgAvg.rows - 35; i++)
    for (int j = 1; j < imgAvg.cols - 35; j++) 
        imgAvg.at<Scalar>(Point(j - 1, i - 1)) = mean(imgPadding(Rect(j - 1, i - 1, 3, 3)));

我得到了这个奇怪的输出:screenshot

提前致谢!

编辑:谢谢大家的回答,我还不知道这个blur()功能。这样我导入图像并简单地调用模糊函数

Mat img = imread(samples::findFile(argv[1]), IMREAD_GRAYSCALE);
Mat imgAvg = Mat::zeros(img.rows, img.cols, img.type());

blur(img, imgAvg, Size(3, 3));

但是由于我仍然是初学者,并且我认为分配给我的练习的目的是编写“手工”代码,因此我也尝试了这个可行的解决方案

for (int i = 1; i <= imgAvg.rows; i++)
    for (int j = 1; j <= imgAvg.cols; j++) 
        imgAvg.at<uint8_t>(Point(j - 1, i - 1)) = mean(imgPadding(Rect(j - 1, i - 1, 3, 3)))[0];

算法的结果(两种解决方案相同)

标签: c++opencv

解决方案


您要做的就是图像处理中的“框过滤”。在 OpenCV 中,您可以:

cv::blur(src_img, 
         dest_img, // same shape and type as src, cannot be src
         cv::Size(3, 3))  // use a kernel of size 3x3           

默认填充是反映边界像素,不会扭曲图像统计信息。如果您喜欢不同的边框模式,请参阅文档。


推荐阅读