Wed, 05 Aug 2009 15:02:31 +0100
PTdecode: add support for uncompressed data (NOTE: *NOT* supported by the PT-2450DX)
1 /*
2 #
3 # File : hough_transform.cpp
4 # ( C++ source file )
5 #
6 # Description : Implementation of the Hough transform.
7 # This file is a part of the CImg Library project.
8 # ( http://cimg.sourceforge.net )
9 #
10 # Copyright : David Tschumperle
11 # ( http://www.greyc.ensicaen.fr/~dtschump/ )
12 #
13 # License : CeCILL v2.0
14 # ( http://www.cecill.info/licences/Licence_CeCILL_V2-en.html )
15 #
16 # This software is governed by the CeCILL license under French law and
17 # abiding by the rules of distribution of free software. You can use,
18 # modify and/ or redistribute the software under the terms of the CeCILL
19 # license as circulated by CEA, CNRS and INRIA at the following URL
20 # "http://www.cecill.info".
21 #
22 # As a counterpart to the access to the source code and rights to copy,
23 # modify and redistribute granted by the license, users are provided only
24 # with a limited warranty and the software's author, the holder of the
25 # economic rights, and the successive licensors have only limited
26 # liability.
27 #
28 # In this respect, the user's attention is drawn to the risks associated
29 # with loading, using, modifying and/or developing or reproducing the
30 # software by the user in light of its specific status of free software,
31 # that may mean that it is complicated to manipulate, and that also
32 # therefore means that it is reserved for developers and experienced
33 # professionals having in-depth computer knowledge. Users are therefore
34 # encouraged to load and test the software's suitability as regards their
35 # requirements in conditions enabling the security of their systems and/or
36 # data to be ensured and, more generally, to use and operate it in the
37 # same conditions as regards security.
38 #
39 # The fact that you are presently reading this means that you have had
40 # knowledge of the CeCILL license and that you accept its terms.
41 #
42 */
44 #include "CImg.h"
45 using namespace cimg_library;
47 // The lines below are necessary when using a non-standard compiler as visualcpp6.
48 #ifdef cimg_use_visualcpp6
49 #define std
50 #endif
51 #ifdef min
52 #undef min
53 #undef max
54 #endif
56 #ifndef cimg_imagepath
57 #define cimg_imagepath "img/"
58 #endif
60 int main(int argc,char **argv) {
62 cimg_usage("Illustration of the Hough transform");
63 CImg<unsigned char> src(cimg_option("-i",cimg_imagepath "parrot_original.ppm","Input image"));
64 CImg<> vote(500,400,1,1,0), img = CImg<>(src).get_pointwise_norm().normalize(0,255).resize(-100,-100,1,2,2);
66 CImgDisplay disp(src,"Image"), dispvote(vote,"Hough Transform");
67 const unsigned char col1[3]={255,255,255}, col2[3]={0,0,0};
68 const double
69 alpha = cimg_option("-a",1.5,"Gradient smoothing"),
70 sigma = cimg_option("-s",0.5,"Hough Transform smoothing"),
71 rhomax = std::sqrt((double)(img.dimx()*img.dimx()+img.dimy()*img.dimy()))/2,
72 thetamax = 2*cimg::valuePI;
74 if (cimg::dialog(cimg::basename(argv[0]),
75 "Instructions : \n"
76 "------------\n\n"
77 "(1) When clicking on the image, all lines crossing the point\n"
78 "will be voted in the Hough Transform image.\n\n"
79 "(2) When clicking on the vote image, the corresponding line is drawn\n"
80 "on the image.\n\n"
81 "(3) When pressing the space bar, the image lines are detected from the\n"
82 "image gradients.\n\n"
83 "Note that a logarithmic scaling is performed for the vote image display.\n"
84 "See also the available options (option '-h')\n","Start !","Quit",0,0,0,0,
85 src.get_resize(100,100,1,3),true)) std::exit(0);
87 while (!disp.is_closed && !dispvote.is_closed && !disp.is_keyQ && !dispvote.is_keyQ && !disp.is_keyESC && !dispvote.is_keyESC) {
89 CImgDisplay::wait(disp,dispvote);
91 // When pressing space bar, the vote is performed from the image gradients.
92 if (dispvote.key==cimg::keySPACE || disp.key==cimg::keySPACE) {
93 CImgList<> grad = img.get_gradient();
94 cimglist_for(grad,l) grad[l].blur((float)alpha);
95 vote.fill(0);
96 cimg_forXY(img,x,y) {
97 const double
98 X = (double)x-img.dimx()/2,
99 Y = (double)y-img.dimy()/2,
100 gx = grad[0](x,y),
101 gy = grad[1](x,y);
102 double
103 theta = std::atan2(gy,gx),
104 rho = std::sqrt(X*X+Y*Y)*std::cos(std::atan2(Y,X)-theta);
105 if (rho<0) { rho=-rho; theta+=cimg::valuePI; }
106 theta = cimg::mod(theta,thetamax);
107 vote((int)(theta*dispvote.dimx()/thetamax),(int)(rho*dispvote.dimy()/rhomax))+=(float)std::sqrt(gx*gx+gy*gy);
108 }
109 vote.blur((float)sigma);
110 CImg<> vote2(vote); { cimg_forXY(vote2,x,y) vote2(x,y) = (float)std::log(1+vote(x,y)); vote2.display(dispvote); }
111 }
113 // When clicking on the vote window.
114 if (dispvote.button) {
115 const double
116 rho = dispvote.mouse_y*rhomax/dispvote.dimy(),
117 theta = dispvote.mouse_x*thetamax/dispvote.dimx(),
118 x = img.dimx()/2 + rho*std::cos(theta),
119 y = img.dimy()/2 + rho*std::sin(theta);
120 const int
121 x0 = (int)(x+1000*std::sin(theta)),
122 y0 = (int)(y-1000*std::cos(theta)),
123 x1 = (int)(x-1000*std::sin(theta)),
124 y1 = (int)(y+1000*std::cos(theta));
125 CImg<unsigned char>(src).
126 draw_line(x0,y0,x1,y1,col1,1.0f,0xF0F0F0F0).draw_line(x0,y0,x1,y1,col2,1.0f,0x0F0F0F0F).
127 draw_line(x0+1,y0,x1+1,y1,col1,1.0f,0xF0F0F0F0).draw_line(x0+1,y0,x1+1,y1,col2,1.0f,0x0F0F0F0F).
128 draw_line(x0,y0+1,x1,y1+1,col1,1.0f,0xF0F0F0F0).draw_line(x0,y0+1,x1,y1+1,col2,1.0f,0x0F0F0F0F).
129 display(disp);
130 }
132 // When clicking on the image.
133 if (disp.button && disp.mouse_x>=0) {
134 const double
135 x0 = (double)disp.mouse_x-disp.dimx()/2,
136 y0 = (double)disp.mouse_y-disp.dimy()/2,
137 rho0 = std::sqrt(x0*x0+y0*y0),
138 theta0 = std::atan2(y0,x0);
140 for (double t=0; t<thetamax; t+=0.001) {
141 double theta = t, rho = rho0*std::cos(theta0-t);
142 if (rho<0) { rho=-rho; theta=cimg::mod(theta+cimg::valuePI,thetamax); }
143 vote((int)(theta*vote.dimx()/thetamax),(int)(rho*vote.dimy()/rhomax))+=1;
144 }
145 CImg<> vote2(vote); cimg_forXY(vote2,x,y) vote2(x,y) = (float)std::log(1+vote(x,y)); vote2.display(dispvote);
146 }
147 dispvote.resize(dispvote);
148 disp.resize(disp);
149 }
151 std::exit(0);
152 return 0;
153 }