我正在尝试创建一个代码来查找另一个图像的边框,如下图所示。
图像
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。 我试图基于邻居做到这一点,但我不知道我应该采取什么样的逻辑。 欢迎各方面的帮助。谢谢。
答案 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 */
}
}
}
}