17 std::array<int, 4> neighbors;
25 std::array<int, 8> neighbors;
32 std::array<std::array<int, 2>, 4> neighbors;
34 Dilate(input, 4, &neighbors[0], output);
39 std::array<std::array<int, 2>, 8> neighbors;
41 Dilate(input, 8, &neighbors[0], output);
45 std::array<int, 2>
const* neighbors,
Image2<int>& output)
49 LogAssert(&output != &input,
"Input and output must be different.");
58 for (
int y = 0;
y < dim1; ++
y)
60 for (
int x = 0;
x < dim0; ++
x)
64 for (
int j = 0; j < numNeighbors; ++j)
66 int xNbr =
x + neighbors[j][0];
67 int yNbr =
y + neighbors[j][1];
68 if (0 <= xNbr && xNbr < dim0 && 0 <= yNbr && yNbr < dim1)
70 output(xNbr, yNbr) = 1;
81 std::array<std::array<int, 2>, 4> neighbors;
83 Erode(input, zeroExterior, 4, &neighbors[0], output);
89 std::array<std::array<int, 2>, 8> neighbors;
91 Erode(input, zeroExterior, 8, &neighbors[0], output);
95 int numNeighbors, std::array<int, 2>
const* neighbors,
100 LogAssert(&output != &input,
"Input and output must be different.");
109 for (
int y = 0;
y < dim1; ++
y)
111 for (
int x = 0;
x < dim0; ++
x)
115 for (
int j = 0; j < numNeighbors; ++j)
117 int xNbr =
x + neighbors[j][0];
118 int yNbr =
y + neighbors[j][1];
119 if (0 <= xNbr && xNbr < dim0 && 0 <= yNbr && yNbr < dim1)
121 if (
input(xNbr, yNbr) == 0)
127 else if (zeroExterior)
142 Erode4(input, zeroExterior, temp);
150 Erode8(input, zeroExterior, temp);
155 int numNeighbors, std::array<int, 2>
const* neighbors,
159 Erode(input, zeroExterior, numNeighbors, neighbors, temp);
160 Dilate(temp, numNeighbors, neighbors, output);
168 Erode4(temp, zeroExterior, output);
176 Erode8(temp, zeroExterior, output);
180 int numNeighbors, std::array<int, 2>
const* neighbors,
184 Dilate(input, numNeighbors, neighbors, temp);
185 Erode(temp, zeroExterior, numNeighbors, neighbors, output);
189 std::vector<size_t>& boundary)
194 for (i = image.
GetIndex(x, y); i < numPixels; ++i)
207 int const dx[8] = { -1, 0, +1, +1, +1, 0, -1, -1 };
208 int const dy[8] = { -1, -1, -1, 0, +1, +1, +1, 0 };
211 boundary.push_back(i);
215 int x0 = coord[0],
y0 = coord[1];
216 int cx =
x0, cy =
y0;
217 int nx = x0-1,
ny =
y0, dir = 7;
225 for (j = 0, nbr = dir; j < 8; ++j, nbr = (nbr + 1) % 8)
241 if (nx == x0 && ny == y0)
250 boundary.push_back(image.
GetIndex(nx, ny));
258 dir = (j + 5 + dir) % 8;
265 int& xMax,
int& yMax)
269 int const dim0m1 = dim0 - 1;
270 int const dim1m1 = dim1 - 1;
274 bool changeMade =
true;
276 for (distance = 1, xMax = 0, yMax = 0; changeMade; ++
distance)
279 int distanceP1 = distance + 1;
280 for (
int y = 1;
y < dim1m1; ++
y)
282 for (
int x = 1;
x < dim0m1; ++
x)
327 int const dim0m1 = dim0 - 1;
328 int const dim1m1 = dim1 - 1;
335 for (y = 0; y < dim1; ++
y)
337 for (x = 0; x < dim0; ++
x)
339 if (
image(x, y) != 0)
343 dist(x, y) = std::numeric_limits<int>::max();
361 for (y = 0; y < dim1; ++
y)
363 for (x = 0; x < dim0; ++
x)
365 distance = dist(x, y);
368 L2Check(x, y, -1, 0, xNear, yNear, dist);
369 L2Check(x, y, -1, -1, xNear, yNear, dist);
370 L2Check(x, y, 0, -1, xNear, yNear, dist);
374 L2Check(x, y, -2, -1, xNear, yNear, dist);
375 L2Check(x, y, -1, -2, xNear, yNear, dist);
379 L2Check(x, y, -3, -1, xNear, yNear, dist);
380 L2Check(x, y, -3, -2, xNear, yNear, dist);
381 L2Check(x, y, -2, -3, xNear, yNear, dist);
382 L2Check(x, y, -1, -3, xNear, yNear, dist);
386 L2Check(x, y, -4, -1, xNear, yNear, dist);
387 L2Check(x, y, -4, -3, xNear, yNear, dist);
388 L2Check(x, y, -3, -4, xNear, yNear, dist);
389 L2Check(x, y, -1, -4, xNear, yNear, dist);
393 L2Check(x, y, -5, -1, xNear, yNear, dist);
394 L2Check(x, y, -5, -2, xNear, yNear, dist);
395 L2Check(x, y, -5, -3, xNear, yNear, dist);
396 L2Check(x, y, -5, -4, xNear, yNear, dist);
397 L2Check(x, y, -4, -5, xNear, yNear, dist);
398 L2Check(x, y, -2, -5, xNear, yNear, dist);
399 L2Check(x, y, -3, -5, xNear, yNear, dist);
400 L2Check(x, y, -1, -5, xNear, yNear, dist);
406 for (y = dim1m1; y >= 0; --
y)
408 for (x = dim0m1; x >= 0; --
x)
410 distance = dist(x, y);
413 L2Check(x, y, 1, 0, xNear, yNear, dist);
414 L2Check(x, y, 1, 1, xNear, yNear, dist);
415 L2Check(x, y, 0, 1, xNear, yNear, dist);
419 L2Check(x, y, 2, 1, xNear, yNear, dist);
420 L2Check(x, y, 1, 2, xNear, yNear, dist);
424 L2Check(x, y, 3, 1, xNear, yNear, dist);
425 L2Check(x, y, 3, 2, xNear, yNear, dist);
426 L2Check(x, y, 2, 3, xNear, yNear, dist);
427 L2Check(x, y, 1, 3, xNear, yNear, dist);
431 L2Check(x, y, 4, 1, xNear, yNear, dist);
432 L2Check(x, y, 4, 3, xNear, yNear, dist);
433 L2Check(x, y, 3, 4, xNear, yNear, dist);
434 L2Check(x, y, 1, 4, xNear, yNear, dist);
438 L2Check(x, y, 5, 1, xNear, yNear, dist);
439 L2Check(x, y, 5, 2, xNear, yNear, dist);
440 L2Check(x, y, 5, 3, xNear, yNear, dist);
441 L2Check(x, y, 5, 4, xNear, yNear, dist);
442 L2Check(x, y, 4, 5, xNear, yNear, dist);
443 L2Check(x, y, 2, 5, xNear, yNear, dist);
444 L2Check(x, y, 3, 5, xNear, yNear, dist);
445 L2Check(x, y, 1, 5, xNear, yNear, dist);
451 for (y = dim1m1; y >= 0; --
y)
453 for (x = 0; x < dim0; ++
x)
455 distance = dist(x, y);
458 L2Check(x, y, -1, 0, xNear, yNear, dist);
459 L2Check(x, y, -1, 1, xNear, yNear, dist);
460 L2Check(x, y, 0, 1, xNear, yNear, dist);
464 L2Check(x, y, -2, 1, xNear, yNear, dist);
465 L2Check(x, y, -1, 2, xNear, yNear, dist);
469 L2Check(x, y, -3, 1, xNear, yNear, dist);
470 L2Check(x, y, -3, 2, xNear, yNear, dist);
471 L2Check(x, y, -2, 3, xNear, yNear, dist);
472 L2Check(x, y, -1, 3, xNear, yNear, dist);
476 L2Check(x, y, -4, 1, xNear, yNear, dist);
477 L2Check(x, y, -4, 3, xNear, yNear, dist);
478 L2Check(x, y, -3, 4, xNear, yNear, dist);
479 L2Check(x, y, -1, 4, xNear, yNear, dist);
483 L2Check(x, y, -5, 1, xNear, yNear, dist);
484 L2Check(x, y, -5, 2, xNear, yNear, dist);
485 L2Check(x, y, -5, 3, xNear, yNear, dist);
486 L2Check(x, y, -5, 4, xNear, yNear, dist);
487 L2Check(x, y, -4, 5, xNear, yNear, dist);
488 L2Check(x, y, -2, 5, xNear, yNear, dist);
489 L2Check(x, y, -3, 5, xNear, yNear, dist);
490 L2Check(x, y, -1, 5, xNear, yNear, dist);
496 for (y = 0; y < dim1; ++
y)
498 for (x = dim0m1; x >= 0; --
x)
500 distance = dist(x, y);
503 L2Check(x, y, 1, 0, xNear, yNear, dist);
504 L2Check(x, y, 1, -1, xNear, yNear, dist);
505 L2Check(x, y, 0, -1, xNear, yNear, dist);
509 L2Check(x, y, 2, -1, xNear, yNear, dist);
510 L2Check(x, y, 1, -2, xNear, yNear, dist);
514 L2Check(x, y, 3, -1, xNear, yNear, dist);
515 L2Check(x, y, 3, -2, xNear, yNear, dist);
516 L2Check(x, y, 2, -3, xNear, yNear, dist);
517 L2Check(x, y, 1, -3, xNear, yNear, dist);
521 L2Check(x, y, 4, -1, xNear, yNear, dist);
522 L2Check(x, y, 4, -3, xNear, yNear, dist);
523 L2Check(x, y, 3, -4, xNear, yNear, dist);
524 L2Check(x, y, 1, -4, xNear, yNear, dist);
528 L2Check(x, y, 5, -1, xNear, yNear, dist);
529 L2Check(x, y, 5, -2, xNear, yNear, dist);
530 L2Check(x, y, 5, -3, xNear, yNear, dist);
531 L2Check(x, y, 5, -4, xNear, yNear, dist);
532 L2Check(x, y, 4, -5, xNear, yNear, dist);
533 L2Check(x, y, 2, -5, xNear, yNear, dist);
534 L2Check(x, y, 3, -5, xNear, yNear, dist);
535 L2Check(x, y, 1, -5, xNear, yNear, dist);
543 for (y = 0; y < dim1; ++
y)
545 for (x = 0; x < dim0; ++
x)
547 float fdistance = sqrt((
float)dist(x, y));
548 if (fdistance > maxDistance)
550 maxDistance = fdistance;
620 for (
int y = 0;
y < dim1; ++
y)
622 for (
int x = 0;
x < dim0; ++
x)
650 for (
int y = 0;
y < dim1; ++
y)
652 for (
int x = 0;
x < dim0; ++
x)
667 for (
size_t i = 0; i < numPixels; ++i)
677 std::function<
void(
int,
int)>
const& callback)
679 for (
int dy = -thick; dy <= thick; ++dy)
681 for (
int dx = -thick; dx <= thick; ++dx)
683 callback(x + dx, y + dy);
689 std::function<
void(
int,
int)>
const& callback)
695 int dx = x1 -
x0, dy = y1 -
y0;
698 int sx = (dx > 0 ? 1 : (dx < 0 ? -1 : 0));
699 int sy = (dy > 0 ? 1 : (dy < 0 ? -1 : 0));
710 int ax = 2 * dx, ay = 2 * dy;
714 int maxValue = dx, var = 0;
725 for (; ; x += sx, decY += ay)
743 for (; ; y += sy, decX += ax)
763 bool solid, std::function<
void(
int,
int)>
const& callback)
769 int xValue, yMin, yMax, i;
770 for (x = 0, y = radius, dec = 3 - 2*radius; x <=
y; ++
x)
772 xValue = xCenter +
x;
775 for (i = yMin; i <= yMax; ++i)
780 xValue = xCenter -
x;
781 for (i = yMin; i <= yMax; ++i)
786 xValue = xCenter +
y;
789 for (i = yMin; i <= yMax; ++i)
794 xValue = xCenter -
y;
795 for (i = yMin; i <= yMax; ++i)
809 for (x = 0, y = radius, dec = 3 - 2*radius; x <=
y; ++
x)
811 callback(xCenter + x, yCenter + y);
812 callback(xCenter + x, yCenter - y);
813 callback(xCenter - x, yCenter + y);
814 callback(xCenter - x, yCenter - y);
815 callback(xCenter + y, yCenter + x);
816 callback(xCenter + y, yCenter - x);
817 callback(xCenter - y, yCenter + x);
818 callback(xCenter - y, yCenter - x);
830 int yMax,
bool solid, std::function<
void(
int,
int)>
const& callback)
836 for (y = yMin; y <= yMax; ++
y)
838 for (x = xMin; x <= xMax; ++
x)
846 for (x = xMin; x <= xMax; ++
x)
851 for (y = yMin + 1; y <= yMax - 1; ++
y)
860 std::function<
void(
int,
int)>
const& callback)
862 int xExtSqr = xExtent * xExtent, yExtSqr = yExtent * yExtent;
867 dec = 2 * yExtSqr + xExtSqr * (1 - 2 * yExtent);
868 for (; yExtSqr * x <= xExtSqr *
y; ++
x)
870 callback(xCenter + x, yCenter + y);
871 callback(xCenter - x, yCenter + y);
872 callback(xCenter + x, yCenter - y);
873 callback(xCenter - x, yCenter - y);
877 dec += 4 * xExtSqr * (1 -
y);
880 dec += yExtSqr * (4 * x + 6);
882 if (y == 0 && x < xExtent)
887 for (; x <= xExtent; ++
x)
889 callback(xCenter + x, yCenter);
890 callback(xCenter - x, yCenter);
897 dec = 2 * xExtSqr + yExtSqr * (1 - 2 * xExtent);
898 for (; xExtSqr * y <= yExtSqr *
x; ++
y)
900 callback(xCenter + x, yCenter + y);
901 callback(xCenter - x, yCenter + y);
902 callback(xCenter + x, yCenter - y);
903 callback(xCenter - x, yCenter - y);
907 dec += 4 * yExtSqr * (1 -
x);
910 dec += xExtSqr * (4 * y + 6);
912 if (x == 0 && y < yExtent)
917 for (; y <= yExtent; ++
y)
919 callback(xCenter, yCenter + y);
920 callback(xCenter, yCenter - y);
929 std::vector<int> numElements(numPixels);
930 std::vector<size_t> vstack(numPixels);
931 size_t i, numComponents = 0;
933 for (i = 0; i < numPixels; ++i)
940 int&
count = numElements[numComponents + 1];
944 size_t v = vstack[
top];
947 for (j = 0; j < numNeighbors; ++j)
949 size_t adj = v + delta[j];
956 if (j == numNeighbors)
969 if (numComponents > 0)
972 for (i = 1; i <= numComponents; ++i)
978 for (i = 0; i < numPixels; ++i)
980 int value = image[i];
987 ++numElements[
value];
998 int xp = x + dx, yp = y + dy;
999 if (0 <= xp && xp < dim0 && 0 <= yp && yp < dim1)
1001 if (dist(xp, yp) < dist(x, y))
1003 int dx0 = xNear(xp, yp) -
x;
1004 int dy0 = yNear(xp, yp) -
y;
1005 int newDist = dx0*dx0 + dy0*dy0;
1006 if (newDist < dist(x, y))
1008 xNear(x, y) = xNear(xp, yp);
1009 yNear(x, y) = yNear(xp, yp);
1010 dist(x, y) = newDist;
1018 bool b1 = (
image(x, y-1) != 0);
1019 bool b3 = (
image(x+1, y) != 0);
1020 bool b5 = (
image(x, y+1) != 0);
1021 bool b7 = (
image(x-1, y) != 0);
1022 return (b1 && b3) || (b3 && b5) || (b5 && b7) || (b7 && b1);
1027 int numNeighbors = 0;
1028 if (
image(x-1, y) != 0)
1032 if (
image(x+1, y) != 0)
1036 if (
image(x, y-1) != 0)
1040 if (
image(x, y+1) != 0)
1044 return numNeighbors == 3;
1049 return image(x-1, y) != 0
1050 &&
image(x+1, y) != 0
1051 &&
image(x, y-1) != 0
1052 &&
image(x, y+1) != 0;
1060 bool noInterior =
true;
1061 for (
int y = 0; y < dim1; ++
y)
1063 for (
int x = 0; x < dim0; ++
x)
1065 if (
image(x, y) > 0)
1067 if (
function(image, x, y))
1087 if (
image(x-1, y-1) != 0)
1091 if (
image(x, y-1) != 0)
1095 if (
image(x+1, y-1) != 0)
1099 if (
image(x+1, y) != 0)
1103 if (
image(x+1, y+1) != 0)
1107 if (
image(x, y+1) != 0)
1111 if (
image(x-1, y+1) != 0)
1115 if (
image(x-1, y) != 0)
1127 bool noRemoval =
true;
1128 for (
int y = 0; y < dim1; ++
y)
1130 for (
int x = 0; x < dim0; ++
x)
1132 if (
image(x, y) == 1)
1134 bool interiorAdjacent =
1135 image(x-1, y-1) == value ||
1136 image(x , y-1) == value ||
1137 image(x+1, y-1) == value ||
1138 image(x+1, y ) == value ||
1139 image(x+1, y+1) == value ||
1140 image(x , y+1) == value ||
1141 image(x-1, y+1) == value ||
1158 0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,
1159 0,1,1,1,1,1,1,1,0,1,0,0,0,1,0,0,
1160 0,1,1,1,1,1,1,1,0,1,0,0,0,1,0,0,
1161 0,1,1,1,1,1,1,1,0,1,0,0,0,1,0,0,
1162 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1163 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1164 0,1,1,1,1,1,1,1,0,1,0,0,0,1,0,0,
1165 0,1,1,1,1,1,1,1,0,1,0,0,0,1,0,0,
1166 0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,
1167 1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,0,
1168 0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,
1169 0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,
1170 0,0,0,0,1,1,0,0,1,1,0,0,1,1,0,0,
1171 1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,0,
1172 0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,
1173 0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0
static bool IsArticulation(Image2< int > &image, int x, int y)
static void DrawCircle(int xCenter, int yCenter, int radius, bool solid, std::function< void(int, int)> const &callback)
size_t GetIndex(int x, int y) const
static bool ExtractBoundary(int x, int y, Image2< int > &image, std::vector< size_t > &boundary)
static bool Interior4(Image2< int > &image, int x, int y)
static void Open4(Image2< int > const &input, bool zeroExterior, Image2< int > &output)
static void Erode8(Image2< int > const &input, bool zeroExterior, Image2< int > &output)
#define LogAssert(condition, message)
static void GetComponents(int numNeighbors, int const *delta, Image2< int > &image, std::vector< std::vector< size_t >> &components)
static void DrawLine(int x0, int y0, int x1, int y1, std::function< void(int, int)> const &callback)
int GetDimension(int d) const
GLenum GLenum GLsizei void * image
static void Erode(Image2< int > const &input, bool zeroExterior, int numNeighbors, std::array< int, 2 > const *neighbors, Image2< int > &output)
static void GetComponents4(Image2< int > &image, std::vector< std::vector< size_t >> &components)
static void Close8(Image2< int > const &input, bool zeroExterior, Image2< int > &output)
GLsizei const GLfloat * value
GLsizei GLsizei GLfloat distance
static void GetL2Distance(Image2< int > const &image, float &maxDistance, int &xMax, int &yMax, Image2< float > &transform)
static bool ClearInteriorAdjacent(Image2< int > &image, int value)
static void GetComponents8(Image2< int > &image, std::vector< std::vector< size_t >> &components)
static void Erode4(Image2< int > const &input, bool zeroExterior, Image2< int > &output)
static void L2Check(int x, int y, int dx, int dy, Image2< int > &xNear, Image2< int > &yNear, Image2< int > &dist)
static void GetSkeleton(Image2< int > &image)
void GetCoordinates(size_t index, int &x, int &y) const
static void GetL1Distance(Image2< int > &image, int &maxDistance, int &xMax, int &yMax)
GLuint GLsizei const GLchar * label
static void Open8(Image2< int > const &input, bool zeroExterior, Image2< int > &output)
size_t GetNumPixels() const
static bool MarkInterior(Image2< int > &image, int value, bool(*function)(Image2< int > &, int, int))
static void Close4(Image2< int > const &input, bool zeroExterior, Image2< int > &output)
static void Close(Image2< int > const &input, bool zeroExterior, int numNeighbors, std::array< int, 2 > const *neighbors, Image2< int > &output)
static void DrawEllipse(int xCenter, int yCenter, int xExtent, int yExtent, std::function< void(int, int)> const &callback)
static void Dilate4(Image2< int > const &input, Image2< int > &output)
static bool Interior2(Image2< int > &image, int x, int y)
static void DrawRectangle(int xMin, int yMin, int xMax, int yMax, bool solid, std::function< void(int, int)> const &callback)
GLuint GLfloat GLfloat GLfloat x1
static void Dilate(Image2< int > const &input, int numNeighbors, std::array< int, 2 > const *neighbors, Image2< int > &output)
GLenum GLenum GLenum input
GLenum GLenum GLuint components
void GetNeighborhood(std::array< int, 4 > &nbr) const
GLuint GLfloat GLfloat y0
static int const msArticulation[256]
static void DrawThickPixel(int x, int y, int thick, std::function< void(int, int)> const &callback)
static void Open(Image2< int > const &input, bool zeroExterior, int numNeighbors, std::array< int, 2 > const *neighbors, Image2< int > &output)
GLuint GLenum GLenum transform
static void Dilate8(Image2< int > const &input, Image2< int > &output)
GLdouble GLdouble GLdouble GLdouble top
static bool Interior3(Image2< int > &image, int x, int y)