簡體   English   中英

OpenCV C++ - 如何用 3x3 鄰域中的灰度平均值替換每個像素的值?

[英]OpenCV C++ - How can I replace the value of each pixel with the average value of the grayscale in a 3x3 neighborhood?

我是 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]

現在我在使用 output 圖像時遇到了一些問題。 我嘗試了各種方式,但沒有辦法讓我找到解決方案。 我試過這個,使用mean() function來獲得通過Rect() 方法得到的第 i,j-th 3x3 矩陣的平均灰度值。 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)));

我得到了這個奇怪的 output:截圖

提前致謝!

編輯:謝謝大家的回答,我還不知道blur() function。 這樣我導入圖像並簡單地調用模糊 function

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

算法的結果(兩種解決方案相同)

只需對圖像應用平滑過濾器 - imgproc模塊中的blur function 應該可以滿足您的需要。 文檔中有一個很好的例子: https://docs.opencv.org/3.4/dc/dd3/tutorial_gausian_median_blur_bilateral_filter.ZFC35FDC70D5FC69D2698Z83A82EC

在這種情況下,您需要的 arguments 是圖像 ( img )、目標圖像 ( dst ) 和 kernel 大小 ( ksize ),在這種情況下為 3:

src = ...
Mat dst = Mat::zeros( src.size(), src.type() )
blur( src, dst, Size( 3, 3 ))

手動平滑不會像以前那樣高效,而且更容易出錯。

祝你好運!

您要做的就是圖像處理中的“框過濾”。 在 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           

默認填充是反映邊界像素,不會扭曲圖像統計信息。 如果您喜歡不同的邊框模式,請參閱文檔

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM