Пиксельное расстояние заливки

0

Заявление о проблемах:

Ввод представляет собой прямоугольное растровое изображение, подобное этому:

0001
0011
0110

Задача состоит в том, чтобы найти для каждого черного (0) "пиксель", расстояние до ближайшего белого (1) "пикселя". Таким образом, вывод к вышесказанному должен быть:

3 2 1 0
2 1 0 0
1 0 0 1

У меня есть рабочее решение проблемы, которое я разместил здесь, прося совета по повышению производительности. Стремясь реализовать решение @Jerry Coffin (предлагаемое в ответе на вопрос), я написал следующий код, который, к сожалению, производит вывод мусора. Например, вывод для ввода из оператора проблемы

1   1  1 0 
11  11 0 0 
110 0  0 1

Почему код не работает?

#include <iostream>
#include <string>
#include <queue>

using namespace std;

const unsigned short MAX = 200;

typedef unsigned short coordinate;
typedef pair<coordinate,coordinate> coordinates;

//Converts char[] to unsigned int
coordinate atou(char* s) {
    coordinate x = 0;
    while(*s) x = x*10 + *(s++) - '0';
    return x;
}

//Returns array of immediate neighbours of pixel of coordinates c
coordinates* neighbours_of(coordinates c) {
    static coordinates neighbours[7];
    coordinate i = c.first;
    coordinate j = c.second;
    neighbours[0] = coordinates(i+1,j);
    neighbours[1] = coordinates(i+1,j+1);
    neighbours[2] = coordinates(i,j+1);
    neighbours[3] = coordinates(i-1,j+1);
    neighbours[4] = coordinates(i-1,j);
    neighbours[5] = coordinates(i-1,j-1);
    neighbours[6] = coordinates(i,j-1);
    neighbours[7] = coordinates(i+1,j-1);
    return neighbours;
}

int main() {

    unsigned short test_cases, wave_number, initial_wave_size;
    coordinate m, n, i, j;
    int A[MAX][MAX];
    coordinates* directions;
    string row;
    queue<coordinates> ones;
    queue<coordinates> wave;
    coordinates current_coordinates;
    bool found_some_zero;
    cin >> test_cases;

    while(test_cases--) {

        //Input
        cin >> n;
        cin >> m;
        for(i = 0; i < n; i++) {
            cin >> row;
            for(j = 0; j < m; j++) {
                if(row[j] == '1') {
                    A[i][j] = -1;
                    ones.push(coordinates(i,j));
                } else A[i][j] = atou(&row[j]);
            }
        }

        //Initilization
        wave = ones;
        wave_number = 1;
        found_some_zero = true;

        //Filling algorithm
        while(found_some_zero) {
            found_some_zero = false;
            initial_wave_size = wave.size();
            while(initial_wave_size--) {
                current_coordinates = wave.front();
                directions = neighbours_of(current_coordinates);
                //Try all directions
                for(int k = 0; k < 8; k++) {
                    i = directions[k].first;
                    j = directions[k].second;
                    //If on screen and not yet visited
                    if(i < n && j < m && A[i][j] == 0) {
                        //Mark visited
                        A[i][j] = wave_number;
                        //(i,j) will be part the next wave
                        wave.push(coordinates(i,j));
                        found_some_zero = true;
                    }
                }
                wave.pop();
            }
            wave_number++;
        }

        //-1 to 0
        while(!ones.empty()) {
            current_coordinates = ones.front();
            i = current_coordinates.first;
            j = current_coordinates.second;
            A[i][j] = 0;
            ones.pop();
        }

        //Output
        for(i = 0; i < n; i++) {
            for(j = 0; j < m; j++)
                cout << A[i][j] << " ";
            cout << endl;
        }
    }
    return 0;
}
  • 1
    Может оказаться полезным проверить некоторые ссылки на реализации с en.wikipedia.org/wiki/Distance_transform
Теги:
algorithm
flood-fill

1 ответ

1
Лучший ответ

Входной контур неисправен. Вместо

            if(row[j] == '1') {
                A[i][j] = -1;
                ones.push(coordinates(i,j));
            } else A[i][j] = atou(&row[j]);

вам нужно сделать

            if(row[j] == '1') {
                A[i][j] = -1;
                ones.push(coordinates(i,j));
            } else A[i][j] = 0;

Кроме того, neighbors[7] должны быть neighbors[8], и вы должны использовать только четыре основных направления, если вы хотите точно указать указанный результат.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню