-
Notifications
You must be signed in to change notification settings - Fork 6
/
hausdorff.c
147 lines (123 loc) · 3.14 KB
/
hausdorff.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/**@file
Binary Hausdorff routine
*/
#include <stdlib.h>
#include <string.h>
static int dilate(unsigned char *binary, int width, int height, unsigned char *sel, int swidth, int sheight);
/**
Binary Hausdorff distance.
The Hausforff distance is the maximum distance from the pixels in A not
in B to the nearest pixel in B, and vice versa. So it is a measure of
image similarity. The half-Hausdorff distance just considers A to B or
B to A, and the Hausdorff distance is trivally the maximum of the two.
@param[in] imagea - the first image
@param[in] imageb - the second image
@param width - image width
@param height - image height
@param[out] halfa - return for half-Hausdorff distance a to b
@param[out] halfb - return for half-Hausdorff distance b to a
@returns The Hausdorff distance between image a and image b.
@note Diagonal steps = 1, not Euclidean distance.
@note return -1 if either image empty.
*/
int binaryhausdorff(unsigned char *imagea, unsigned char *imageb, int width, int height, int *halfa, int *halfb)
{
unsigned char *buff;
unsigned char se[9] = { 1,1,1,1,1,1,1,1,1 };
int maxit;
int halfda = -1;
int halfdb = -1;
int answer;
int i, ii;
buff = malloc(width * height);
if (!buff)
goto out_of_memory;
maxit = width > height ? width : height;
memcpy(buff, imagea, width * height);
for (i = 0; i < maxit; i++)
{
for (ii = 0; ii < width*height; ii++)
if (imageb[ii] && !buff[ii])
break;
if (ii == width * height)
{
halfdb = i;
break;
}
dilate(buff, width, height, se, 3, 3);
}
memcpy(buff, imageb, width * height);
for (i = 0; i < maxit; i++)
{
for (ii = 0; ii < width*height; ii++)
if (imagea[ii] && !buff[ii])
break;
if (ii == width * height)
{
halfda = i;
break;
}
dilate(buff, width, height, se, 3, 3);
}
if (halfda == -1 || halfdb == -1)
answer = -1;
else
answer = halfda > halfdb ? halfda : halfdb;
if (halfa)
*halfa = halfda;
if (halfb)
*halfb = halfdb;
free(buff);
return answer;
out_of_memory:
if (halfa)
*halfa = -1;
if (halfb)
*halfb = -1;
free(buff);
return -1;
}
/*
Dilate operation.
@param[in,out] bianry - the binary image
@param width - image width
@param height - image height
@param sel[in] - the selection element
@param swidth - selection element width
@param sheight - selection element height
@returns 0 on sucess, -1 on error.
*/
static int dilate(unsigned char *binary, int width, int height, unsigned char *sel, int swidth, int sheight)
{
int x, y, sx, sy, ix, iy;
unsigned char *answer;
int i;
int bit;
answer = malloc(width * height);
if (!answer)
return -1;
for (i = 0; i<width*height; i++)
answer[i] = 0;
for (y = 0; y<height; y++)
for (x = 0; x<width; x++)
{
for (sy = 0; sy<sheight; sy++)
for (sx = 0; sx < swidth; sx++)
{
ix = x + sx - swidth / 2;
iy = y + sy - sheight / 2;
if (ix < 0 || ix >= width || iy < 0 || iy >= height)
bit = 0;
else
bit = binary[iy * width + ix];
if (bit == 1 && sel[sy*swidth + sx] == 1)
{
answer[y*width + x] = 1;
}
}
}
for (i = 0; i<width*height; i++)
binary[i] = answer[i];
free(answer);
return 0;
}