OpenCV / C++ - редактировать все изолированные пиксели

У меня есть изображение в градациях серого, которое содержит только черный и белый. Из-за шума есть отдельные черные пиксели, от которых я бы хотел избавиться. Я знаю, что открытие и закрытие может быть решением, но я чувствую, что они не являются оптимальными для моего имиджа. Итак, я написал это:

for (int i = 1; i < pixels.rows; ++i) {
    for (int j = 1; j < pixels.cols; ++j) {
        if ((pixels.at<char>(i, j) == 0) && 
            (pixels.at<char>(i - 1, j) == 255) && 
            (pixels.at<char>(i, j - 1) == 255) && 
            (pixels.at<char>(i + 1, j) == 255) && 
            (pixels.at<char>(i, j + 1) == 255)) {
            pixels.at<char>(i, j) = 255;
        }
    }
}

Предполагается, что он пробежит по моему изображению и проверит, является ли пиксель черным, а его окрестности белым. Если это так, пиксель также должен быть превращен в белый. Я запустил это на тестовом изображении, которое было создано этим матом:

Mat pixels = (Mat_<float>(5, 5) <<
    255, 255, 255, 255, 255,
    255, 0, 255, 0, 255,
    255, 255, 255, 255, 255,
    255, 0, 255, 0, 255,
    255, 255, 255, 255, 255);

Когда я запустил код, ничего не произошло, появилось только оригинальное изображение...

Когда я запустил более простую версию кода, она работала, поэтому синтаксис должен быть правильным:

    for (int i = 1; i < pixels.rows; ++i) {
    for (int j = 1; j < pixels.cols; ++j) {
        if ((pixels.at<char>(i, j) == 0)) {
            pixels.at<char>(i, j) = 255;
        }
    }
}

Кто-нибудь находит мою ошибку в этом?

1 ответ

Решение

Процедура в основном правильная, но вы создаете Mat из float и вы получаете доступ к нему как char, Вам нужно, чтобы тип был таким же.

Также ваши итерационные диапазоны должны быть зафиксированы. Вы также можете проверить 8-соединение, иначе ваше изображение с центральным пикселем, установленным в 0, не будет работать должным образом

Помните также, что char диапазон [-128, +127], поэтому он никогда не будет сравниваться равным 255.

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

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;

int main()
{
    Mat pixels = (Mat_<uchar>(5, 5) <<
        255, 255, 255, 255, 255,
        255, 0, 255, 0, 255,
        255, 255, 255, 255, 255,
        255, 0, 255, 0, 255,
        255, 255, 255, 255, 255);

    for (int i = 1; i < pixels.rows - 1; ++i) {
        for (int j = 1; j < pixels.cols - 1; ++j)
        {
            if ((pixels.at<uchar>(i, j) == 0) &&
                (pixels.at<uchar>(i - 1, j - 1) == 255) &&      // Top Left
                (pixels.at<uchar>(i - 1, j + 0) == 255) &&      // Top 
                (pixels.at<uchar>(i - 1, j + 1) == 255) &&      // Top Right
                (pixels.at<uchar>(i + 0, j - 1) == 255) &&      // Left
                (pixels.at<uchar>(i + 0, j + 1) == 255) &&      // Right
                (pixels.at<uchar>(i + 1, j - 1) == 255) &&      // Bottom Left
                (pixels.at<uchar>(i + 1, j + 0) == 255) &&      // Bottom
                (pixels.at<uchar>(i + 1, j + 1) == 255)         // Bottom Right
                )
            {
                pixels.at<uchar>(i, j) = 255;
            }
        }
    }

    std::cout << pixels;

    return 0;
}
Другие вопросы по тегам