Tuesday, September 17, 2013

Image erosion


The image is represented in a two-dimension array. Every pixel of the image can only to assigned to either 0 or 1. If a pixel is 0, just leave it there. If a pixel is 1, we check its four neighbors. If all its four neighbors are 1, leave it there. Otherwise, erode it to 0.
Example:
0 1 1 1 0        0 0 1 0 0
1 1 1 0 0  --> 0 1 0 0 0 
0 1 0 1 1        0 0 0 0 0

Solution:
The difficult part is that every pixel can only be assigned to either 0 or 1. Otherwise, we can assign the 1s which need erosion first to some other value in the first scan. In the second scan, we can change this value to 0.
So here we use to arrays to store the row index and column index for the pixel need erosion.
The problem with this method is that we use to much memory to store the row index and column index. One way to optimize is that we only store the index for two rows. Because the erosion of row 0 will not affect the check for row 2.
bool check (int x, int y, int image[H][M]) {
    if (x>0 && image[x-1][y]==0)
        return true;
    if (x<H-1 && image[x+1][y]==0)
        return true;
    if (y>0 && image[x][y-1]==0)
        return true;
    if (y<W-1 && image[x][y+1]==0)
        return true;
    return false;
}

void erosion_part (vector<int> &row, vector<int> &col, int image[H][M]) {
    for (int i = 0; i < row.size(); i++)
        image[row[i]][col[i]] = 0;
}

void erosion (int image[H][W]) {
    vector<int> row, col;
    for (int i = 0; i < H; i++) {
        for (int j = 0; j < W; j++) {
            if (check(i, j, image)) {
                row.push_back(i);
                col.push_back(j);
            }
        }
    }
    erosion_part (row, col, image);
}

The problem with this method is that we use to much memory to store the row index and column index. One way to optimize is that we only store the index for two rows. Because the erosion of row 0 will not affect the check for row 2.
void erosion_part (vector<int> &row, vector<int> &col, int image[H][M], int end) {
    while (!row.empty()) {
        if (row.front() > end)
            break;
        image[row.front()][col.front()] = 0;
        row.pop_front();
        col.pop_front();
    }
}

void erosion (int image[H][W]) {
    list<int> row, col;
    int start = 0;
    for (int i = 0; i < H; i++) {
        if (i-start >= 2) {
            erosion_part (row, col, image, start);
            row.clear();
            col.clear();
            start++;
        }
        for (int j = 0; j < W; j++) {
            if (check(i, j, image)) {
                row.push_back(i);
                col.push_back(j);
            }
        }
    }
    erosion_part (row, col, H-1);
}

No comments:

Post a Comment