边框图像分割

时间:2017-07-20 18:07:22

标签: c image

我正在尝试创建一个代码来查找另一个图像的边框,如下图所示。

图像

    0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 
   ------------------------------------------------
 0: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . 
 1: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . 
 2: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . 
 3: .  .  .  .  x  .  .  .  .  .  .  .  .  .  .  . 
 4: .  .  .  x  .  x  .  .  .  .  x  .  .  .  .  . 
 5: .  .  x  x  .  .  .  .  .  x  x  x  .  .  .  . 
 6: .  .  .  x  x  x  x  x  .  x  x  x  x  .  .  . 
 7: .  .  .  x  x  x  x  x  .  x  x  x  x  .  .  . 
 8: .  .  .  .  .  x  x  x  x  x  x  x  x  .  .  . 
 9: .  .  .  .  .  x  x  x  x  x  x  x  x  .  .  . 
10: .  .  .  .  .  x  x  x  .  x  x  x  .  .  .  . 
11: .  .  .  .  x  .  x  x  x  x  x  .  .  .  .  . 
12: .  .  .  x  .  .  .  .  x  x  .  .  .  .  .  . 
13: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . 
14: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . 
15: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  . 

我必须标记此图像边框的每个x。 我试图基于邻居做到这一点,但我不知道我应该采取什么样的逻辑。 欢迎各方面的帮助。谢谢。

2 个答案:

答案 0 :(得分:3)

首先,您需要编写一个处理图像的函数。据推测,图像由2d字符数组表示,因此函数需要迭代此数组。可以使用第二函数来确定图像的每个'x'是否在边缘上。结果可以存储在输出数组中。

现在,要编写第二个函数(可能称为is_edge()),您需要确定'x'位于图像边缘的含义。如果第一次尝试与背景像素('.')相邻,则可能在图像的边缘上具有前景像素。这听起来不错,但结果图像可能有点“沉重”:

Image edges (is_edge1):
    0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 
   -------------------------------------------------
 0: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  
 1: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  
 2: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  
 3: .  .  .  .  x  .  .  .  .  .  .  .  .  .  .  .  
 4: .  .  .  x  .  x  .  .  .  .  x  .  .  .  .  .  
 5: .  .  x  x  .  .  .  .  .  x  x  x  .  .  .  .  
 6: .  .  .  x  x  x  x  x  .  x  .  x  x  .  .  .  
 7: .  .  .  x  x  x  .  x  .  x  .  .  x  .  .  .  
 8: .  .  .  .  .  x  .  x  x  x  .  .  x  .  .  .  
 9: .  .  .  .  .  x  .  x  x  x  .  x  x  .  .  .  
10: .  .  .  .  .  x  x  x  .  x  x  x  .  .  .  .  
11: .  .  .  .  x  .  x  x  x  x  x  .  .  .  .  .  
12: .  .  .  x  .  .  .  .  x  x  .  .  .  .  .  .  
13: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  
14: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  
15: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  

这里有一些像素,例如[5] [10],可能已被删除。如果这看起来不太合适,那么您可以重新考虑is_edge()函数。如果相反,前景像素位于边缘上,如果它与不在其一个角落的背景像素相邻会怎么样?这应该删除刚看到的类型的额外像素:

Image edges (is_edge2):
    0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 
   -------------------------------------------------
 0: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  
 1: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  
 2: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  
 3: .  .  .  .  x  .  .  .  .  .  .  .  .  .  .  .  
 4: .  .  .  x  .  x  .  .  .  .  x  .  .  .  .  .  
 5: .  .  x  x  .  .  .  .  .  x  .  x  .  .  .  .  
 6: .  .  .  x  x  x  x  x  .  x  .  .  x  .  .  .  
 7: .  .  .  x  x  .  .  x  .  x  .  .  x  .  .  .  
 8: .  .  .  .  .  x  .  .  x  .  .  .  x  .  .  .  
 9: .  .  .  .  .  x  .  .  x  .  .  .  x  .  .  .  
10: .  .  .  .  .  x  .  x  .  x  .  x  .  .  .  .  
11: .  .  .  .  x  .  x  x  x  .  x  .  .  .  .  .  
12: .  .  .  x  .  .  .  .  x  x  .  .  .  .  .  .  
13: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  
14: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  
15: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  

这种方法在某些方面似乎更好,但它似乎也删除了太多内部像素。请注意,[11] [9]处的像素现已被删除;从原始图像看来,这似乎不应该被删除。如果前景像素与不在其一个角落的背景像素相邻,或者如果它与相对的对角线处的两个背景像素相邻,则修改将考虑前景像素在边缘上。这将保留“桥”像素,例如[11] [9]中的像素:

Image edges (is_edge3):
    0  1  2  3  4  5  6  7  8  9  10 11 12 13 14 15 
   -------------------------------------------------
 0: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  
 1: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  
 2: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  
 3: .  .  .  .  x  .  .  .  .  .  .  .  .  .  .  .  
 4: .  .  .  x  .  x  .  .  .  .  x  .  .  .  .  .  
 5: .  .  x  x  .  .  .  .  .  x  .  x  .  .  .  .  
 6: .  .  .  x  x  x  x  x  .  x  .  .  x  .  .  .  
 7: .  .  .  x  x  .  .  x  .  x  .  .  x  .  .  .  
 8: .  .  .  .  .  x  .  .  x  .  .  .  x  .  .  .  
 9: .  .  .  .  .  x  .  .  x  .  .  .  x  .  .  .  
10: .  .  .  .  .  x  .  x  .  x  .  x  .  .  .  .  
11: .  .  .  .  x  .  x  x  x  x  x  .  .  .  .  .  
12: .  .  .  x  .  .  .  .  x  x  .  .  .  .  .  .  
13: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  
14: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  
15: .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  

这可能是上述替代方案中最好的。但请考虑这个测试用例:

.  .  .  .  .
.  .  x  .  .
.  x  x  x  .
.  .  x  .  .
.  .  .  .  .

在上面提到的三种方法中,只有第二种方法会从图像中心删除x。也许一种方法在某些情况下效果更好,而在另一些情况下则更好。或者也许需要更好的方法。

以下是用于生成上述输出的完整程序。 find_edges()函数将函数指针作为参数,以便可以轻松实现,尝试和比较不同的is_edge()函数。我相信您可以找到改进此代码的方法。

#include <stdio.h>

#define IMAGE_SZ  16

void show_image(char img[][IMAGE_SZ], size_t img_sz);
void find_edges(char in[][IMAGE_SZ],
                char out[][IMAGE_SZ],
                size_t img_sz,
                int (*is_edge)(size_t, size_t, char [][IMAGE_SZ], size_t));
int is_edge1(size_t y, size_t x, char in[][IMAGE_SZ], size_t img_sz);
int is_edge2(size_t y, size_t x, char in[][IMAGE_SZ], size_t img_sz);
int is_edge3(size_t y, size_t x, char in[][IMAGE_SZ], size_t img_sz);

int main(void)
{
    char image_in[IMAGE_SZ][IMAGE_SZ] = { "................",
                                          "................",
                                          "................",
                                          "....x...........",
                                          "...x.x....x.....",
                                          "..xx.....xxx....",
                                          "...xxxxx.xxxx...",
                                          "...xxxxx.xxxx...",
                                          ".....xxxxxxxx...",
                                          ".....xxxxxxxx...",
                                          ".....xxx.xxx....",
                                          "....x.xxxxx.....",
                                          "...x....xx......",
                                          "................",
                                          "................",
                                          "................" };

    char edge_out[IMAGE_SZ][IMAGE_SZ];

    puts("Input image:");
    show_image(image_in, IMAGE_SZ);

    puts("Image edges (is_edge1):");
    find_edges(image_in, edge_out, IMAGE_SZ, is_edge1);
    show_image(edge_out, IMAGE_SZ);

    puts("Image edges (is_edge2):");
    find_edges(image_in, edge_out, IMAGE_SZ, is_edge2);
    show_image(edge_out, IMAGE_SZ);

    puts("Image edges (is_edge3):");
    find_edges(image_in, edge_out, IMAGE_SZ, is_edge3);
    show_image(edge_out, IMAGE_SZ);

    return 0;
}

void show_image(char img[][IMAGE_SZ], size_t img_sz)
{
    /* print top numbers */
    printf("%4c", ' ');
    for (size_t j = 0; j < img_sz; j++) {
        printf("%-3zu", j);
    }
    putchar('\n');

    /* print dashes */
    printf("%4c", '-');
    for (size_t j = 0; j < img_sz; j++) {
        printf("%3s", "---");
    }
    putchar('\n');

    /* print rows */
    for (size_t i = 0; i < img_sz; i++) {
        printf("%2zu: ", i);
        for (size_t j = 0; j < img_sz; j++) {
            printf("%-3c", img[i][j]);
        }
        putchar('\n');
    }
    putchar('\n');
}

void find_edges(char in[][IMAGE_SZ],
                char out[][IMAGE_SZ],
                size_t img_sz,
                int (*is_edge)(size_t, size_t, char [][IMAGE_SZ], size_t))
{
    for (size_t i = 0; i < img_sz; i++) {
        for (size_t j = 0; j < img_sz; j++) {
            out[i][j] = is_edge(i, j, in, img_sz) ? 'x' : '.';
            }
        }
}

/* A pixel is an edge if it is adjacent to a background pixel */
int is_edge1(size_t y, size_t x, char in[][IMAGE_SZ], size_t img_sz)
{
    int edge_found = 0;
    if (in[y][x] == 'x') {
        size_t y_start = (y == 0 ? 0 : y-1);
        size_t y_stop = (y == (img_sz-1) ? img_sz-1: y+1);
        size_t x_start = (x == 0 ? 0 : x-1);
        size_t x_stop = (x == (img_sz-1) ? img_sz-1 : x+1);


        for (size_t i = y_start; i <= y_stop; i++) {
            for (size_t j = x_start; j <= x_stop; j++) {
                if (in[i][j] == '.') {
                    edge_found = 1;
                    break;
                }
            }
            if (edge_found) {
                break;
            }
        }
    }

    return edge_found;
}

/* a pixel is an edge if it is adjacent to a background pixel that is
 * not a corner pixel
 */
int is_edge2(size_t y, size_t x, char in[][IMAGE_SZ], size_t img_sz)
{
    int edge_found = 0;
    if (in[y][x] == 'x') {
        size_t y_start = (y == 0 ? 0 : y-1);
        size_t y_stop = (y == (img_sz-1) ? img_sz-1: y+1);
        size_t x_start = (x == 0 ? 0 : x-1);
        size_t x_stop = (x == (img_sz-1) ? img_sz-1 : x+1);

        edge_found = (in[y_start][x] == '.' ||
                      in[y][x_start] == '.' ||
                      in[y][x_stop] == '.'  ||
                      in[y_stop][x] == '.');
    }

    return edge_found;
}

/* a pixel is an edge if it is adjacent to a background pixel that is
 * not a corner pixel or if it is adjacent to two opposite diagonal
 * corner pixels.
 */
int is_edge3(size_t y, size_t x, char in[][IMAGE_SZ], size_t img_sz)
{
    int edge_found = 0;
    if (in[y][x] == 'x') {
        size_t y_start = (y == 0 ? 0 : y-1);
        size_t y_stop = (y == (img_sz-1) ? img_sz-1: y+1);
        size_t x_start = (x == 0 ? 0 : x-1);
        size_t x_stop = (x == (img_sz-1) ? img_sz-1 : x+1);

        edge_found = (in[y_start][x] == '.' ||
                      in[y][x_start] == '.' ||
                      in[y][x_stop] == '.'  ||
                      in[y_stop][x] == '.');
        if (edge_found == 0) {
            edge_found = ((in[y_start][x_start] == '.' &&
                           in[y_stop][x_stop] == '.') ||
                          (in[y_start][x_stop] == '.' &&
                           in[y_stop][x_start] == '.'));
        }
    }

    return edge_found;
}

答案 1 :(得分:1)

您可以使用try-all算法,测试图像的所有像素。

示例(伪代码):

for i in 0..15 {
    for j in 0..15 {
        if image[i][j] == 'x' {
            /* test the neighbors */
            if (image[i-1][j] == '.' ||
                image[i+1][j] == '.' ||
                image[i][j-1] == '.' ||
                image[i][j+1] == '.') {

                /* It has a '.' neighbor, so this is a border */
                image[i][j] = 'y' /* Mark it */
            }
        }
    }
}
相关问题