edtaa3func.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. /*
  2. * edtaa3()
  3. *
  4. * Sweep-and-update Euclidean distance transform of an
  5. * image. Positive pixels are treated as object pixels,
  6. * zero or negative pixels are treated as background.
  7. * An attempt is made to treat antialiased edges correctly.
  8. * The input image must have pixels in the range [0,1],
  9. * and the antialiased image should be a box-filter
  10. * sampling of the ideal, crisp edge.
  11. * If the antialias region is more than 1 pixel wide,
  12. * the result from this transform will be inaccurate.
  13. *
  14. * By Stefan Gustavson ([email protected]).
  15. *
  16. * Originally written in 1994, based on a verbal
  17. * description of the SSED8 algorithm published in the
  18. * PhD dissertation of Ingemar Ragnemalm. This is his
  19. * algorithm, I only implemented it in C.
  20. *
  21. * Updated in 2004 to treat border pixels correctly,
  22. * and cleaned up the code to improve readability.
  23. *
  24. * Updated in 2009 to handle anti-aliased edges.
  25. *
  26. * Updated in 2011 to avoid a corner case infinite loop.
  27. *
  28. */
  29. /*
  30. Copyright (C) 2009 Stefan Gustavson ([email protected])
  31. This program is free software; you can redistribute it and/or modify it
  32. under the terms of the GNU General Public License as published by the
  33. Free Software Foundation; either version 3 of the License, or (at your
  34. option) any later version.
  35. This program is distributed in the hope that it will be useful, but WITHOUT
  36. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  37. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  38. for more details.
  39. The GNU General Public License is available on <http://www.gnu.org/licenses/>.
  40. */
  41. #include <math.h>
  42. /*
  43. * Compute the local gradient at edge pixels using convolution filters.
  44. * The gradient is computed only at edge pixels. At other places in the
  45. * image, it is never used, and it's mostly zero anyway.
  46. */
  47. void computegradient(double *img, int w, int h, double *gx, double *gy)
  48. {
  49. int i,j,k;
  50. double glength;
  51. #define SQRT2 1.4142136
  52. for(i = 1; i < h-1; i++) { // Avoid edges where the kernels would spill over
  53. for(j = 1; j < w-1; j++) {
  54. k = i*w + j;
  55. if((img[k]>0.0) && (img[k]<1.0)) { // Compute gradient for edge pixels only
  56. gx[k] = -img[k-w-1] - SQRT2*img[k-1] - img[k+w-1] + img[k-w+1] + SQRT2*img[k+1] + img[k+w+1];
  57. gy[k] = -img[k-w-1] - SQRT2*img[k-w] - img[k+w-1] + img[k-w+1] + SQRT2*img[k+w] + img[k+w+1];
  58. glength = gx[k]*gx[k] + gy[k]*gy[k];
  59. if(glength > 0.0) { // Avoid division by zero
  60. glength = sqrt(glength);
  61. gx[k]=gx[k]/glength;
  62. gy[k]=gy[k]/glength;
  63. }
  64. }
  65. }
  66. }
  67. // TODO: Compute reasonable values for gx, gy also around the image edges.
  68. // (These are zero now, which reduces the accuracy for a 1-pixel wide region
  69. // around the image edge.) 2x2 kernels would be suitable for this.
  70. }
  71. /*
  72. * A somewhat tricky function to approximate the distance to an edge in a
  73. * certain pixel, with consideration to either the local gradient (gx,gy)
  74. * or the direction to the pixel (dx,dy) and the pixel greyscale value a.
  75. * The latter alternative, using (dx,dy), is the metric used by edtaa2().
  76. * Using a local estimate of the edge gradient (gx,gy) yields much better
  77. * accuracy at and near edges, and reduces the error even at distant pixels
  78. * provided that the gradient direction is accurately estimated.
  79. */
  80. double edgedf(double gx, double gy, double a)
  81. {
  82. double df, glength, temp, a1;
  83. if ((gx == 0) || (gy == 0)) { // Either A) gu or gv are zero, or B) both
  84. df = 0.5-a; // Linear approximation is A) correct or B) a fair guess
  85. } else {
  86. glength = sqrt(gx*gx + gy*gy);
  87. if(glength>0) {
  88. gx = gx/glength;
  89. gy = gy/glength;
  90. }
  91. /* Everything is symmetric wrt sign and transposition,
  92. * so move to first octant (gx>=0, gy>=0, gx>=gy) to
  93. * avoid handling all possible edge directions.
  94. */
  95. gx = fabs(gx);
  96. gy = fabs(gy);
  97. if(gx<gy) {
  98. temp = gx;
  99. gx = gy;
  100. gy = temp;
  101. }
  102. a1 = 0.5*gy/gx;
  103. if (a < a1) { // 0 <= a < a1
  104. df = 0.5*(gx + gy) - sqrt(2.0*gx*gy*a);
  105. } else if (a < (1.0-a1)) { // a1 <= a <= 1-a1
  106. df = (0.5-a)*gx;
  107. } else { // 1-a1 < a <= 1
  108. df = -0.5*(gx + gy) + sqrt(2.0*gx*gy*(1.0-a));
  109. }
  110. }
  111. return df;
  112. }
  113. double distaa3(double *img, double *gximg, double *gyimg, int w, int c, int xc, int yc, int xi, int yi)
  114. {
  115. double di, df, dx, dy, gx, gy, a;
  116. int closest;
  117. closest = c-xc-yc*w; // Index to the edge pixel pointed to from c
  118. a = img[closest]; // Grayscale value at the edge pixel
  119. gx = gximg[closest]; // X gradient component at the edge pixel
  120. gy = gyimg[closest]; // Y gradient component at the edge pixel
  121. if(a > 1.0) a = 1.0;
  122. if(a < 0.0) a = 0.0; // Clip grayscale values outside the range [0,1]
  123. if(a == 0.0) return 1000000.0; // Not an object pixel, return "very far" ("don't know yet")
  124. dx = (double)xi;
  125. dy = (double)yi;
  126. di = sqrt(dx*dx + dy*dy); // Length of integer vector, like a traditional EDT
  127. if(di==0) { // Use local gradient only at edges
  128. // Estimate based on local gradient only
  129. df = edgedf(gx, gy, a);
  130. } else {
  131. // Estimate gradient based on direction to edge (accurate for large di)
  132. df = edgedf(dx, dy, a);
  133. }
  134. return di + df; // Same metric as edtaa2, except at edges (where di=0)
  135. }
  136. // Shorthand macro: add ubiquitous parameters dist, gx, gy, img and w and call distaa3()
  137. #define DISTAA(c,xc,yc,xi,yi) (distaa3(img, gx, gy, w, c, xc, yc, xi, yi))
  138. void edtaa3(double *img, double *gx, double *gy, int w, int h, short *distx, short *disty, double *dist)
  139. {
  140. int x, y, i, c;
  141. int offset_u, offset_ur, offset_r, offset_rd,
  142. offset_d, offset_dl, offset_l, offset_lu;
  143. double olddist, newdist;
  144. int cdistx, cdisty, newdistx, newdisty;
  145. int changed;
  146. double epsilon = 1e-3;
  147. /* Initialize index offsets for the current image width */
  148. offset_u = -w;
  149. offset_ur = -w+1;
  150. offset_r = 1;
  151. offset_rd = w+1;
  152. offset_d = w;
  153. offset_dl = w-1;
  154. offset_l = -1;
  155. offset_lu = -w-1;
  156. /* Initialize the distance images */
  157. for(i=0; i<w*h; i++) {
  158. distx[i] = 0; // At first, all pixels point to
  159. disty[i] = 0; // themselves as the closest known.
  160. if(img[i] <= 0.0)
  161. {
  162. dist[i]= 1000000.0; // Big value, means "not set yet"
  163. }
  164. else if (img[i]<1.0) {
  165. dist[i] = edgedf(gx[i], gy[i], img[i]); // Gradient-assisted estimate
  166. }
  167. else {
  168. dist[i]= 0.0; // Inside the object
  169. }
  170. }
  171. /* Perform the transformation */
  172. do
  173. {
  174. changed = 0;
  175. /* Scan rows, except first row */
  176. for(y=1; y<h; y++)
  177. {
  178. /* move index to leftmost pixel of current row */
  179. i = y*w;
  180. /* scan right, propagate distances from above & left */
  181. /* Leftmost pixel is special, has no left neighbors */
  182. olddist = dist[i];
  183. if(olddist > 0) // If non-zero distance or not set yet
  184. {
  185. c = i + offset_u; // Index of candidate for testing
  186. cdistx = distx[c];
  187. cdisty = disty[c];
  188. newdistx = cdistx;
  189. newdisty = cdisty+1;
  190. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  191. if(newdist < olddist-epsilon)
  192. {
  193. distx[i]=newdistx;
  194. disty[i]=newdisty;
  195. dist[i]=newdist;
  196. olddist=newdist;
  197. changed = 1;
  198. }
  199. c = i+offset_ur;
  200. cdistx = distx[c];
  201. cdisty = disty[c];
  202. newdistx = cdistx-1;
  203. newdisty = cdisty+1;
  204. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  205. if(newdist < olddist-epsilon)
  206. {
  207. distx[i]=newdistx;
  208. disty[i]=newdisty;
  209. dist[i]=newdist;
  210. changed = 1;
  211. }
  212. }
  213. i++;
  214. /* Middle pixels have all neighbors */
  215. for(x=1; x<w-1; x++, i++)
  216. {
  217. olddist = dist[i];
  218. if(olddist <= 0) continue; // No need to update further
  219. c = i+offset_l;
  220. cdistx = distx[c];
  221. cdisty = disty[c];
  222. newdistx = cdistx+1;
  223. newdisty = cdisty;
  224. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  225. if(newdist < olddist-epsilon)
  226. {
  227. distx[i]=newdistx;
  228. disty[i]=newdisty;
  229. dist[i]=newdist;
  230. olddist=newdist;
  231. changed = 1;
  232. }
  233. c = i+offset_lu;
  234. cdistx = distx[c];
  235. cdisty = disty[c];
  236. newdistx = cdistx+1;
  237. newdisty = cdisty+1;
  238. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  239. if(newdist < olddist-epsilon)
  240. {
  241. distx[i]=newdistx;
  242. disty[i]=newdisty;
  243. dist[i]=newdist;
  244. olddist=newdist;
  245. changed = 1;
  246. }
  247. c = i+offset_u;
  248. cdistx = distx[c];
  249. cdisty = disty[c];
  250. newdistx = cdistx;
  251. newdisty = cdisty+1;
  252. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  253. if(newdist < olddist-epsilon)
  254. {
  255. distx[i]=newdistx;
  256. disty[i]=newdisty;
  257. dist[i]=newdist;
  258. olddist=newdist;
  259. changed = 1;
  260. }
  261. c = i+offset_ur;
  262. cdistx = distx[c];
  263. cdisty = disty[c];
  264. newdistx = cdistx-1;
  265. newdisty = cdisty+1;
  266. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  267. if(newdist < olddist-epsilon)
  268. {
  269. distx[i]=newdistx;
  270. disty[i]=newdisty;
  271. dist[i]=newdist;
  272. changed = 1;
  273. }
  274. }
  275. /* Rightmost pixel of row is special, has no right neighbors */
  276. olddist = dist[i];
  277. if(olddist > 0) // If not already zero distance
  278. {
  279. c = i+offset_l;
  280. cdistx = distx[c];
  281. cdisty = disty[c];
  282. newdistx = cdistx+1;
  283. newdisty = cdisty;
  284. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  285. if(newdist < olddist-epsilon)
  286. {
  287. distx[i]=newdistx;
  288. disty[i]=newdisty;
  289. dist[i]=newdist;
  290. olddist=newdist;
  291. changed = 1;
  292. }
  293. c = i+offset_lu;
  294. cdistx = distx[c];
  295. cdisty = disty[c];
  296. newdistx = cdistx+1;
  297. newdisty = cdisty+1;
  298. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  299. if(newdist < olddist-epsilon)
  300. {
  301. distx[i]=newdistx;
  302. disty[i]=newdisty;
  303. dist[i]=newdist;
  304. olddist=newdist;
  305. changed = 1;
  306. }
  307. c = i+offset_u;
  308. cdistx = distx[c];
  309. cdisty = disty[c];
  310. newdistx = cdistx;
  311. newdisty = cdisty+1;
  312. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  313. if(newdist < olddist-epsilon)
  314. {
  315. distx[i]=newdistx;
  316. disty[i]=newdisty;
  317. dist[i]=newdist;
  318. changed = 1;
  319. }
  320. }
  321. /* Move index to second rightmost pixel of current row. */
  322. /* Rightmost pixel is skipped, it has no right neighbor. */
  323. i = y*w + w-2;
  324. /* scan left, propagate distance from right */
  325. for(x=w-2; x>=0; x--, i--)
  326. {
  327. olddist = dist[i];
  328. if(olddist <= 0) continue; // Already zero distance
  329. c = i+offset_r;
  330. cdistx = distx[c];
  331. cdisty = disty[c];
  332. newdistx = cdistx-1;
  333. newdisty = cdisty;
  334. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  335. if(newdist < olddist-epsilon)
  336. {
  337. distx[i]=newdistx;
  338. disty[i]=newdisty;
  339. dist[i]=newdist;
  340. changed = 1;
  341. }
  342. }
  343. }
  344. /* Scan rows in reverse order, except last row */
  345. for(y=h-2; y>=0; y--)
  346. {
  347. /* move index to rightmost pixel of current row */
  348. i = y*w + w-1;
  349. /* Scan left, propagate distances from below & right */
  350. /* Rightmost pixel is special, has no right neighbors */
  351. olddist = dist[i];
  352. if(olddist > 0) // If not already zero distance
  353. {
  354. c = i+offset_d;
  355. cdistx = distx[c];
  356. cdisty = disty[c];
  357. newdistx = cdistx;
  358. newdisty = cdisty-1;
  359. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  360. if(newdist < olddist-epsilon)
  361. {
  362. distx[i]=newdistx;
  363. disty[i]=newdisty;
  364. dist[i]=newdist;
  365. olddist=newdist;
  366. changed = 1;
  367. }
  368. c = i+offset_dl;
  369. cdistx = distx[c];
  370. cdisty = disty[c];
  371. newdistx = cdistx+1;
  372. newdisty = cdisty-1;
  373. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  374. if(newdist < olddist-epsilon)
  375. {
  376. distx[i]=newdistx;
  377. disty[i]=newdisty;
  378. dist[i]=newdist;
  379. changed = 1;
  380. }
  381. }
  382. i--;
  383. /* Middle pixels have all neighbors */
  384. for(x=w-2; x>0; x--, i--)
  385. {
  386. olddist = dist[i];
  387. if(olddist <= 0) continue; // Already zero distance
  388. c = i+offset_r;
  389. cdistx = distx[c];
  390. cdisty = disty[c];
  391. newdistx = cdistx-1;
  392. newdisty = cdisty;
  393. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  394. if(newdist < olddist-epsilon)
  395. {
  396. distx[i]=newdistx;
  397. disty[i]=newdisty;
  398. dist[i]=newdist;
  399. olddist=newdist;
  400. changed = 1;
  401. }
  402. c = i+offset_rd;
  403. cdistx = distx[c];
  404. cdisty = disty[c];
  405. newdistx = cdistx-1;
  406. newdisty = cdisty-1;
  407. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  408. if(newdist < olddist-epsilon)
  409. {
  410. distx[i]=newdistx;
  411. disty[i]=newdisty;
  412. dist[i]=newdist;
  413. olddist=newdist;
  414. changed = 1;
  415. }
  416. c = i+offset_d;
  417. cdistx = distx[c];
  418. cdisty = disty[c];
  419. newdistx = cdistx;
  420. newdisty = cdisty-1;
  421. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  422. if(newdist < olddist-epsilon)
  423. {
  424. distx[i]=newdistx;
  425. disty[i]=newdisty;
  426. dist[i]=newdist;
  427. olddist=newdist;
  428. changed = 1;
  429. }
  430. c = i+offset_dl;
  431. cdistx = distx[c];
  432. cdisty = disty[c];
  433. newdistx = cdistx+1;
  434. newdisty = cdisty-1;
  435. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  436. if(newdist < olddist-epsilon)
  437. {
  438. distx[i]=newdistx;
  439. disty[i]=newdisty;
  440. dist[i]=newdist;
  441. changed = 1;
  442. }
  443. }
  444. /* Leftmost pixel is special, has no left neighbors */
  445. olddist = dist[i];
  446. if(olddist > 0) // If not already zero distance
  447. {
  448. c = i+offset_r;
  449. cdistx = distx[c];
  450. cdisty = disty[c];
  451. newdistx = cdistx-1;
  452. newdisty = cdisty;
  453. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  454. if(newdist < olddist-epsilon)
  455. {
  456. distx[i]=newdistx;
  457. disty[i]=newdisty;
  458. dist[i]=newdist;
  459. olddist=newdist;
  460. changed = 1;
  461. }
  462. c = i+offset_rd;
  463. cdistx = distx[c];
  464. cdisty = disty[c];
  465. newdistx = cdistx-1;
  466. newdisty = cdisty-1;
  467. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  468. if(newdist < olddist-epsilon)
  469. {
  470. distx[i]=newdistx;
  471. disty[i]=newdisty;
  472. dist[i]=newdist;
  473. olddist=newdist;
  474. changed = 1;
  475. }
  476. c = i+offset_d;
  477. cdistx = distx[c];
  478. cdisty = disty[c];
  479. newdistx = cdistx;
  480. newdisty = cdisty-1;
  481. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  482. if(newdist < olddist-epsilon)
  483. {
  484. distx[i]=newdistx;
  485. disty[i]=newdisty;
  486. dist[i]=newdist;
  487. changed = 1;
  488. }
  489. }
  490. /* Move index to second leftmost pixel of current row. */
  491. /* Leftmost pixel is skipped, it has no left neighbor. */
  492. i = y*w + 1;
  493. for(x=1; x<w; x++, i++)
  494. {
  495. /* scan right, propagate distance from left */
  496. olddist = dist[i];
  497. if(olddist <= 0) continue; // Already zero distance
  498. c = i+offset_l;
  499. cdistx = distx[c];
  500. cdisty = disty[c];
  501. newdistx = cdistx+1;
  502. newdisty = cdisty;
  503. newdist = DISTAA(c, cdistx, cdisty, newdistx, newdisty);
  504. if(newdist < olddist-epsilon)
  505. {
  506. distx[i]=newdistx;
  507. disty[i]=newdisty;
  508. dist[i]=newdist;
  509. changed = 1;
  510. }
  511. }
  512. }
  513. }
  514. while(changed); // Sweep until no more updates are made
  515. /* The transformation is completed. */
  516. }