Mon, 03 Aug 2009 14:21:23 +0100
added keepme for ptdecode obj directory
philpem@5 | 1 | /* |
philpem@5 | 2 | # |
philpem@5 | 3 | # File : mcf_levelsets.cpp |
philpem@5 | 4 | # ( C++ source file ) |
philpem@5 | 5 | # |
philpem@5 | 6 | # Description : Implementation of the Mean Curvature Flow (classical 2d curve evolution), |
philpem@5 | 7 | # using the framework of Level Sets. |
philpem@5 | 8 | # This file is a part of the CImg Library project. |
philpem@5 | 9 | # ( http://cimg.sourceforge.net ) |
philpem@5 | 10 | # |
philpem@5 | 11 | # Copyright : David Tschumperle |
philpem@5 | 12 | # ( http://www.greyc.ensicaen.fr/~dtschump/ ) |
philpem@5 | 13 | # |
philpem@5 | 14 | # License : CeCILL v2.0 |
philpem@5 | 15 | # ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html ) |
philpem@5 | 16 | # |
philpem@5 | 17 | # This software is governed by the CeCILL license under French law and |
philpem@5 | 18 | # abiding by the rules of distribution of free software. You can use, |
philpem@5 | 19 | # modify and/ or redistribute the software under the terms of the CeCILL |
philpem@5 | 20 | # license as circulated by CEA, CNRS and INRIA at the following URL |
philpem@5 | 21 | # "http://www.cecill.info". |
philpem@5 | 22 | # |
philpem@5 | 23 | # As a counterpart to the access to the source code and rights to copy, |
philpem@5 | 24 | # modify and redistribute granted by the license, users are provided only |
philpem@5 | 25 | # with a limited warranty and the software's author, the holder of the |
philpem@5 | 26 | # economic rights, and the successive licensors have only limited |
philpem@5 | 27 | # liability. |
philpem@5 | 28 | # |
philpem@5 | 29 | # In this respect, the user's attention is drawn to the risks associated |
philpem@5 | 30 | # with loading, using, modifying and/or developing or reproducing the |
philpem@5 | 31 | # software by the user in light of its specific status of free software, |
philpem@5 | 32 | # that may mean that it is complicated to manipulate, and that also |
philpem@5 | 33 | # therefore means that it is reserved for developers and experienced |
philpem@5 | 34 | # professionals having in-depth computer knowledge. Users are therefore |
philpem@5 | 35 | # encouraged to load and test the software's suitability as regards their |
philpem@5 | 36 | # requirements in conditions enabling the security of their systems and/or |
philpem@5 | 37 | # data to be ensured and, more generally, to use and operate it in the |
philpem@5 | 38 | # same conditions as regards security. |
philpem@5 | 39 | # |
philpem@5 | 40 | # The fact that you are presently reading this means that you have had |
philpem@5 | 41 | # knowledge of the CeCILL license and that you accept its terms. |
philpem@5 | 42 | # |
philpem@5 | 43 | */ |
philpem@5 | 44 | |
philpem@5 | 45 | #include "CImg.h" |
philpem@5 | 46 | using namespace cimg_library; |
philpem@5 | 47 | |
philpem@5 | 48 | // The lines below are necessary when using a non-standard compiler as visualcpp6. |
philpem@5 | 49 | #ifdef cimg_use_visualcpp6 |
philpem@5 | 50 | #define std |
philpem@5 | 51 | #endif |
philpem@5 | 52 | #ifdef min |
philpem@5 | 53 | #undef min |
philpem@5 | 54 | #undef max |
philpem@5 | 55 | #endif |
philpem@5 | 56 | |
philpem@5 | 57 | // get_level0() : Retrieve the curve corresponding to the zero level set of the distance function |
philpem@5 | 58 | //------------- |
philpem@5 | 59 | CImg<unsigned char> get_level0(const CImg<>& img) { |
philpem@5 | 60 | CImg<unsigned char> dest(img); |
philpem@5 | 61 | CImg_2x2(I,float); Inn = 0; |
philpem@5 | 62 | cimg_for2x2(img,x,y,0,0,I) if (Icc*Inc<0 || Icc*Icn<0) dest(x,y) = 255; else dest(x,y) = Icc<0?100:0; |
philpem@5 | 63 | return dest; |
philpem@5 | 64 | } |
philpem@5 | 65 | |
philpem@5 | 66 | //----------------- |
philpem@5 | 67 | // Main procedure |
philpem@5 | 68 | //----------------- |
philpem@5 | 69 | int main(int argc,char **argv) { |
philpem@5 | 70 | cimg_usage("Perform a Mean Curvature Flow on closed curves, using Level Sets"); |
philpem@5 | 71 | const float dt = cimg_option("-dt",0.8f,"PDE time step"); |
philpem@5 | 72 | const unsigned int nb_iter = cimg_option("-iter",10000,"Number of iterations"); |
philpem@5 | 73 | |
philpem@5 | 74 | // Create a user-defined closed curve |
philpem@5 | 75 | CImg<unsigned char> curve(256,256,1,2,0); |
philpem@5 | 76 | unsigned char col1[2]={0,255}, col2[2]={200,255}, col3[2]={255,255}; |
philpem@5 | 77 | curve.draw_grid(20,20,0,0,false,false,col1,0.4f,0xCCCCCCCC,0xCCCCCCCC). |
philpem@5 | 78 | draw_text(5,5,"Please draw your curve\nin this window\n(Use your mouse)",col1); |
philpem@5 | 79 | CImgDisplay disp(curve,"Mean curvature flow",0); |
philpem@5 | 80 | int xo=-1,yo=-1,x0=-1,y0=-1,x1=-1,y1=-1; |
philpem@5 | 81 | while (!disp.is_closed && (x0<0 || disp.button)) { |
philpem@5 | 82 | if (disp.button && disp.mouse_x>=0 && disp.mouse_y>=0) { |
philpem@5 | 83 | if (x0<0) { xo = x0 = disp.mouse_x; yo = y0 = disp.mouse_y; } else { |
philpem@5 | 84 | x1 = disp.mouse_x; y1 = disp.mouse_y; |
philpem@5 | 85 | curve.draw_line(x0,y0,x1,y1,col2).display(disp); |
philpem@5 | 86 | x0 = x1; y0 = y1; |
philpem@5 | 87 | } |
philpem@5 | 88 | } |
philpem@5 | 89 | disp.wait(); |
philpem@5 | 90 | if (disp.is_resized) disp.resize(disp); |
philpem@5 | 91 | } |
philpem@5 | 92 | curve.draw_line(x1,y1,xo,yo,col2).channel(0).draw_fill(0,0,col3); |
philpem@5 | 93 | CImg<> img = CImg<>(curve.get_shared_channel(0)).normalize(-1,1); |
philpem@5 | 94 | |
philpem@5 | 95 | // Perform the "Mean Curvature Flow" |
philpem@5 | 96 | img.distance_hamilton(10); |
philpem@5 | 97 | CImg_3x3(I,float); |
philpem@5 | 98 | for (unsigned int iter=0; iter<nb_iter && !disp.is_closed && !disp.is_keyQ; iter++) { |
philpem@5 | 99 | CImg<> veloc(img.dimx(),img.dimy(),img.dimz(),img.dimv()); |
philpem@5 | 100 | cimg_for3x3(img,x,y,0,0,I) { |
philpem@5 | 101 | const float |
philpem@5 | 102 | ix = 0.5f*(Inc-Ipc), |
philpem@5 | 103 | iy = 0.5f*(Icn-Icp), |
philpem@5 | 104 | ixx = Inc+Ipc-2*Icc, |
philpem@5 | 105 | iyy = Icn+Icp-2*Icc, |
philpem@5 | 106 | ixy = 0.25f*(Ipp+Inn-Inp-Ipn), |
philpem@5 | 107 | ngrad = ix*ix+iy*iy, |
philpem@5 | 108 | iee = (ngrad>1e-5)?(( iy*iy*ixx - 2*ix*iy*ixy + ix*ix*iyy )/ngrad):0; |
philpem@5 | 109 | veloc(x,y) = iee; |
philpem@5 | 110 | } |
philpem@5 | 111 | float m, M = veloc.maxmin(m); |
philpem@5 | 112 | const double xdt = dt/cimg::max(cimg::abs(m),cimg::abs(M)); |
philpem@5 | 113 | img+=xdt*veloc; |
philpem@5 | 114 | if (!(iter%10)) { |
philpem@5 | 115 | get_level0(img).resize(disp.dimx(),disp.dimy()).draw_grid(20,20,0,0,false,false,col3,0.4f,0xCCCCCCCC,0xCCCCCCCC). |
philpem@5 | 116 | draw_text(5,5,"Iteration %d",col3,0,1,11,iter).display(disp); |
philpem@5 | 117 | } |
philpem@5 | 118 | if (!(iter%30)) img.distance_hamilton(1,3); |
philpem@5 | 119 | if (disp.is_resized) disp.resize(); |
philpem@5 | 120 | } |
philpem@5 | 121 | |
philpem@5 | 122 | // End of program |
philpem@5 | 123 | return 0; |
philpem@5 | 124 | } |