edtaa3func.c 20 KB

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