├── tryout
├── hough_circle
│ ├── README.md
│ ├── img
│ │ └── United_States_money_coins.jpg
│ ├── hough_circle.h
│ ├── Makefile
│ ├── hough.h
│ ├── hough_circle.cpp
│ ├── hough.cpp
│ └── main.cpp
└── README.TXT
├── img
└── russell-crowe-robin-hood-arrow.jpg
├── README.md
├── Makefile
├── hough.h
├── hough.cpp
└── main.cpp
/tryout/hough_circle/README.md:
--------------------------------------------------------------------------------
1 | hough
2 | =====
3 |
4 | Linear Hough Transformation in C++
5 |
--------------------------------------------------------------------------------
/img/russell-crowe-robin-hood-arrow.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brunokeymolen/hough/HEAD/img/russell-crowe-robin-hood-arrow.jpg
--------------------------------------------------------------------------------
/tryout/hough_circle/img/United_States_money_coins.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/brunokeymolen/hough/HEAD/tryout/hough_circle/img/United_States_money_coins.jpg
--------------------------------------------------------------------------------
/tryout/README.TXT:
--------------------------------------------------------------------------------
1 | hough_circle is just some try-out code.
2 | Somebody asked me if it was possible to do circles and this hack is used to show how that may work.
3 | Use it as a kind of guideline, dont expect it to be even near perfect.
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | hough
2 | =====
3 |
4 | Linear Hough Transformation in C++
5 |
6 |
7 |
8 |
9 | Docker build environment:
10 | https://github.com/brunokeymolen/devops/tree/master/docker-images/hough-transform
11 |
12 |
13 | (C) Bruno Keymolen, bruno.keymolen@gmail.com
14 |
--------------------------------------------------------------------------------
/tryout/hough_circle/hough_circle.h:
--------------------------------------------------------------------------------
1 | /*
2 | * hough_circle.h
3 | *
4 | * Created on: May 4, 2013
5 | * Author: bruno
6 | */
7 |
8 | #ifndef HOUGH_CIRCLE_H_
9 | #define HOUGH_CIRCLE_H_
10 |
11 | #include
12 |
13 | namespace keymolen {
14 |
15 | class HoughCircle {
16 | public:
17 | HoughCircle();
18 | virtual ~HoughCircle();
19 | public:
20 | //img_data: 8 bit edge image ( >250 is edge)
21 | int Transform(unsigned char* img_data, int w, int h, int r);
22 | //threshold: number of pixels in a circle; result[(x, y), r]
23 | int GetCircles(int threshold, std::vector< std::pair< std::pair, int> >& result );
24 | const unsigned int* GetAccu(int *w, int *h);
25 | private:
26 | unsigned int* _accu;
27 | int _accu_w;
28 | int _accu_h;
29 | int _img_w;
30 | int _img_h;
31 | int _r;
32 |
33 | };
34 |
35 | }
36 |
37 | #endif /* HOUGH_CIRCLE_H_ */
38 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # (C)2013, Bruno Keymolen
2 | # http://www.keymolen.com
3 | # http://www.keymolen.com/2013/05/hough-transformation-c-implementation.html
4 | CXX=g++
5 | CC=gcc
6 | OPTFLAGS=-g3 -ggdb -O0
7 | CXXFLAGS=-std=c++11 -Wall -I. -I/usr/local/include $(OPTFLAGS)
8 | CFLAGS=-Wall $(OPTFLAGS)
9 | LDFLAGS= -L/usr/local/lib $(OPTFLAGS)
10 |
11 | #opencv
12 | CXXFLAGS+=`pkg-config opencv --cflags`
13 | LDFLAGS+=`pkg-config opencv --libs`
14 |
15 | SRC = main.o hough.o
16 |
17 | all: hough
18 |
19 | hough: $(SRC) $(MODULES)
20 | $(CXX) $(MODULES) $(SRC) $(LDFLAGS) -o hough
21 |
22 | %.o: %.c %.h
23 | $(CC) $(CFLAGS) -c -o $@ $<
24 |
25 | %.o: %.c
26 | $(CC) $(CFLAGS) -c -o $@ $<
27 |
28 | %.o: %.cpp %.h
29 | $(CXX) $(CXXFLAGS) -c -o $@ $<
30 |
31 | %.o: %.cpp
32 | $(CXX) $(CXXFLAGS) -c -o $@ $<
33 |
34 | clean:
35 | rm -f *.o hough
36 |
37 | PREFIX ?= /usr
38 |
39 | install: all
40 | install -d $(PREFIX)/bin
41 | install hough $(PREFIX)/bin
42 |
43 | dependencies:
44 | sudo apt install libopencv-dev
45 |
46 |
47 | .PHONY: clean all hough install
48 |
--------------------------------------------------------------------------------
/tryout/hough_circle/Makefile:
--------------------------------------------------------------------------------
1 | # (C)2013, Bruno Keymolen
2 | # http://www.keymolen.com
3 | # http://www.keymolen.com/2013/05/hough-transformation-c-implementation.html
4 | CXX=g++
5 | CC=gcc
6 | #OPTFLAGS=-g3 -ggdb -O0
7 | OPTFLAGS=-g0 -O3
8 | CXXFLAGS=-Wall -I. -I/usr/local/include $(OPTFLAGS)
9 | CFLAGS=-Wall $(OPTFLAGS)
10 | LDFLAGS= -L/usr/local/lib $(OPTFLAGS)
11 |
12 | #LDFLAGS+= -L/opt/keymolen/opencv/2.4.8/lib
13 | #CXXFLAGS+= -I/opt/keymolen/opencv/2.4.8/include/
14 | #LDFLAGS+= -lopencv_highgui -lopencv_core -lopencv_calib3d -lopencv_features2d -lopencv_flann -lopencv_imgproc -lopencv_objdetect -lopencv_ts
15 |
16 | CXXFLAGS+=`pkg-config opencv --cflags`
17 | LDFLAGS+=`pkg-config opencv --libs`
18 |
19 |
20 | SRC = main.o hough.o hough_circle.o
21 |
22 | all: hough
23 |
24 | hough: $(SRC) $(MODULES)
25 | $(CXX) $(MODULES) $(SRC) $(LDFLAGS) -o hough
26 |
27 | %.o: %.c %.h
28 | $(CC) $(CFLAGS) -c -o $@ $<
29 |
30 | %.o: %.c
31 | $(CC) $(CFLAGS) -c -o $@ $<
32 |
33 | %.o: %.cpp %.h
34 | $(CXX) $(CXXFLAGS) -c -o $@ $<
35 |
36 | %.o: %.cpp
37 | $(CXX) $(CXXFLAGS) -c -o $@ $<
38 |
39 | clean:
40 | rm -f *.o hough
41 |
42 | PREFIX ?= /usr
43 |
44 | install: all
45 | install -d $(PREFIX)/bin
46 | install hough $(PREFIX)/bin
47 |
48 | .PHONY: clean all hough install
49 |
--------------------------------------------------------------------------------
/hough.h:
--------------------------------------------------------------------------------
1 | // **********************************************************************************
2 | //
3 | // BSD License.
4 | // This file is part of a Hough Transformation tutorial
5 | // see: http://www.keymolen.com/2013/05/hough-transformation-c-implementation.html
6 | //
7 | // Copyright (c) 2013, Bruno Keymolen, email: bruno.keymolen@gmail.com
8 | // All rights reserved.
9 | //
10 | // Redistribution and use in source and binary forms, with or without modification,
11 | // are permitted provided that the following conditions are met:
12 | //
13 | // Redistributions of source code must retain the above copyright notice,
14 | // this list of conditions and the following disclaimer.
15 | // Redistributions in binary form must reproduce the above copyright notice, this
16 | // list of conditions and the following disclaimer in the documentation and/or other
17 | // materials provided with the distribution.
18 | // Neither the name of "Bruno Keymolen" nor the names of its contributors may be
19 | // used to endorse or promote products derived from this software without specific
20 | // prior written permission.
21 | //
22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 | // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26 | // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 | // POSSIBILITY OF SUCH DAMAGE.
32 | //
33 | // **********************************************************************************
34 |
35 | #ifndef HOUGH_H_
36 | #define HOUGH_H_
37 |
38 | #include
39 |
40 | namespace keymolen {
41 |
42 | class Hough {
43 | public:
44 | Hough();
45 | virtual ~Hough();
46 | public:
47 | int Transform(unsigned char* img_data, int w, int h);
48 | std::vector< std::pair< std::pair, std::pair > > GetLines(int threshold);
49 | const unsigned int* GetAccu(int *w, int *h);
50 | private:
51 | unsigned int* _accu;
52 | int _accu_w;
53 | int _accu_h;
54 | int _img_w;
55 | int _img_h;
56 | };
57 |
58 | }
59 |
60 | #endif /* HOUGH_H_ */
61 |
--------------------------------------------------------------------------------
/tryout/hough_circle/hough.h:
--------------------------------------------------------------------------------
1 | // **********************************************************************************
2 | //
3 | // BSD License.
4 | // This file is part of a Hough Transformation tutorial
5 | // see: http://www.keymolen.com/2013/05/hough-transformation-c-implementation.html
6 | //
7 | // Copyright (c) 2013, Bruno Keymolen, email: bruno.keymolen@gmail.com
8 | // All rights reserved.
9 | //
10 | // Redistribution and use in source and binary forms, with or without modification,
11 | // are permitted provided that the following conditions are met:
12 | //
13 | // Redistributions of source code must retain the above copyright notice,
14 | // this list of conditions and the following disclaimer.
15 | // Redistributions in binary form must reproduce the above copyright notice, this
16 | // list of conditions and the following disclaimer in the documentation and/or other
17 | // materials provided with the distribution.
18 | // Neither the name of "Bruno Keymolen" nor the names of its contributors may be
19 | // used to endorse or promote products derived from this software without specific
20 | // prior written permission.
21 | //
22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 | // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26 | // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 | // POSSIBILITY OF SUCH DAMAGE.
32 | //
33 | // **********************************************************************************
34 |
35 | #ifndef HOUGH_H_
36 | #define HOUGH_H_
37 |
38 | #include
39 |
40 | namespace keymolen {
41 |
42 | class Hough {
43 | public:
44 | Hough();
45 | virtual ~Hough();
46 | public:
47 | int Transform(unsigned char* img_data, int w, int h);
48 | std::vector< std::pair< std::pair, std::pair > > GetLines(int threshold);
49 | const unsigned int* GetAccu(int *w, int *h);
50 | private:
51 | unsigned int* _accu;
52 | int _accu_w;
53 | int _accu_h;
54 | int _img_w;
55 | int _img_h;
56 | };
57 |
58 | }
59 |
60 | #endif /* HOUGH_H_ */
61 |
--------------------------------------------------------------------------------
/tryout/hough_circle/hough_circle.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * hough_circle.cpp
3 | *
4 | * Created on: May 4, 2013
5 | * Author: bruno
6 | */
7 |
8 | #include "hough_circle.h"
9 |
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #ifndef DEG2RAD
16 | #define DEG2RAD 0.017453293f
17 | #endif
18 |
19 | namespace keymolen {
20 |
21 | HoughCircle::HoughCircle():_accu(0), _accu_w(0), _accu_h(0), _img_w(0), _img_h(0)
22 | {
23 |
24 | }
25 |
26 | HoughCircle::~HoughCircle() {
27 | if(_accu)
28 | free(_accu);
29 | }
30 |
31 | int HoughCircle::Transform(unsigned char* img_data, int w, int h, int r)
32 | {
33 | _r = r;
34 |
35 | _img_w = w;
36 | _img_h = h;
37 |
38 | //Create the accu
39 | _accu_h = h;
40 | _accu_w = w;
41 |
42 | if(_accu)
43 | free(_accu);
44 | _accu = (unsigned int*)calloc(_accu_h * _accu_w, sizeof(unsigned int));
45 |
46 | for(int y=0;y 250 )
51 | {
52 | for(int t=1;t<=360;t++)
53 | {
54 | int a = ((double)x - ((double)_r * cos((double)t * DEG2RAD)));
55 | int b = ((double)y - ((double)_r * sin((double)t * DEG2RAD)));
56 |
57 | if( (b>=0 && b<_accu_h) && (a>=0 && a<_accu_w))
58 | _accu[(b * _accu_w) + a]++;
59 | }
60 | }
61 | }
62 | }
63 |
64 | return 0;
65 | }
66 |
67 | const unsigned int* HoughCircle::GetAccu(int *w, int *h)
68 | {
69 | *w = _accu_w;
70 | *h = _accu_h;
71 |
72 | return _accu;
73 | }
74 |
75 | int HoughCircle::GetCircles(int threshold, std::vector< std::pair< std::pair, int> >& result )
76 | {
77 | int found = 0;
78 |
79 | if(_accu == 0)
80 | return found;
81 |
82 | for(int b=0;b<_accu_h;b++)
83 | {
84 | for(int a=0;a<_accu_w;a++)
85 | {
86 | if((int)_accu[(b*_accu_w) + a] >= threshold)
87 | {
88 | //Is this point a local maxima (9x9)
89 | int max = _accu[(b*_accu_w) + a];
90 | for(int ly=-4;ly<=4;ly++)
91 | {
92 | for(int lx=-4;lx<=4;lx++)
93 | {
94 | if( (ly+b>=0 && ly+b<_accu_h) && (lx+a>=0 && lx+a<_accu_w) )
95 | {
96 | if( (int)_accu[( (b+ly)*_accu_w) + (a+lx)] > max )
97 | {
98 | max = _accu[( (b+ly)*_accu_w) + (a+lx)];
99 | ly = lx = 5;
100 | }
101 | }
102 | }
103 | }
104 | if(max > (int)_accu[(b*_accu_w) + a])
105 | continue;
106 |
107 | result.push_back(std::pair< std::pair, int>(std::pair(a,b), _r));
108 | found++;
109 |
110 | }
111 | }
112 | }
113 |
114 | std::cout << "result: " << found << " " << threshold << std::endl;
115 |
116 | return found;
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/hough.cpp:
--------------------------------------------------------------------------------
1 | // **********************************************************************************
2 | //
3 | // BSD License.
4 | // This file is part of a Hough Transformation tutorial,
5 | // see: http://www.keymolen.com/2013/05/hough-transformation-c-implementation.html
6 | //
7 | // Copyright (c) 2013, Bruno Keymolen, email: bruno.keymolen@gmail.com
8 | // All rights reserved.
9 | //
10 | // Redistribution and use in source and binary forms, with or without modification,
11 | // are permitted provided that the following conditions are met:
12 | //
13 | // Redistributions of source code must retain the above copyright notice,
14 | // this list of conditions and the following disclaimer.
15 | // Redistributions in binary form must reproduce the above copyright notice, this
16 | // list of conditions and the following disclaimer in the documentation and/or other
17 | // materials provided with the distribution.
18 | // Neither the name of "Bruno Keymolen" nor the names of its contributors may be
19 | // used to endorse or promote products derived from this software without specific
20 | // prior written permission.
21 | //
22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 | // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26 | // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 | // POSSIBILITY OF SUCH DAMAGE.
32 | //
33 | // **********************************************************************************
34 |
35 | #include "hough.h"
36 | #include
37 | #include
38 | #include
39 | #include
40 |
41 |
42 | #define DEG2RAD 0.017453293f
43 |
44 | namespace keymolen {
45 |
46 | Hough::Hough():_accu(0), _accu_w(0), _accu_h(0), _img_w(0), _img_h(0)
47 | {
48 |
49 | }
50 |
51 | Hough::~Hough() {
52 | if(_accu)
53 | free(_accu);
54 | }
55 |
56 |
57 | int Hough::Transform(unsigned char* img_data, int w, int h)
58 | {
59 | _img_w = w;
60 | _img_h = h;
61 |
62 | //Create the accu
63 | double hough_h = ((sqrt(2.0) * (double)(h>w?h:w)) / 2.0);
64 | _accu_h = hough_h * 2.0; // -r -> +r
65 | _accu_w = 180;
66 |
67 | _accu = (unsigned int*)calloc(_accu_h * _accu_w, sizeof(unsigned int));
68 |
69 | double center_x = w/2;
70 | double center_y = h/2;
71 |
72 |
73 | for(int y=0;y 250 )
78 | {
79 | for(int t=0;t<180;t++)
80 | {
81 | double r = ( ((double)x - center_x) * cos((double)t * DEG2RAD)) + (((double)y - center_y) * sin((double)t * DEG2RAD));
82 | _accu[ (int)((round(r + hough_h) * 180.0)) + t]++;
83 | }
84 | }
85 | }
86 | }
87 |
88 | return 0;
89 | }
90 |
91 | std::vector< std::pair< std::pair, std::pair > > Hough::GetLines(int threshold)
92 | {
93 | std::vector< std::pair< std::pair, std::pair > > lines;
94 |
95 | if(_accu == 0)
96 | return lines;
97 |
98 | for(int r=0;r<_accu_h;r++)
99 | {
100 | for(int t=0;t<_accu_w;t++)
101 | {
102 | if((int)_accu[(r*_accu_w) + t] >= threshold)
103 | {
104 | //Is this point a local maxima (9x9)
105 | int max = _accu[(r*_accu_w) + t];
106 | for(int ly=-4;ly<=4;ly++)
107 | {
108 | for(int lx=-4;lx<=4;lx++)
109 | {
110 | if( (ly+r>=0 && ly+r<_accu_h) && (lx+t>=0 && lx+t<_accu_w) )
111 | {
112 | if( (int)_accu[( (r+ly)*_accu_w) + (t+lx)] > max )
113 | {
114 | max = _accu[( (r+ly)*_accu_w) + (t+lx)];
115 | ly = lx = 5;
116 | }
117 | }
118 | }
119 | }
120 | if(max > (int)_accu[(r*_accu_w) + t])
121 | continue;
122 |
123 |
124 | int x1, y1, x2, y2;
125 | x1 = y1 = x2 = y2 = 0;
126 |
127 | if(t >= 45 && t <= 135)
128 | {
129 | //y = (r - x cos(t)) / sin(t)
130 | x1 = 0;
131 | y1 = ((double)(r-(_accu_h/2)) - ((x1 - (_img_w/2) ) * cos(t * DEG2RAD))) / sin(t * DEG2RAD) + (_img_h / 2);
132 | x2 = _img_w - 0;
133 | y2 = ((double)(r-(_accu_h/2)) - ((x2 - (_img_w/2) ) * cos(t * DEG2RAD))) / sin(t * DEG2RAD) + (_img_h / 2);
134 | }
135 | else
136 | {
137 | //x = (r - y sin(t)) / cos(t);
138 | y1 = 0;
139 | x1 = ((double)(r-(_accu_h/2)) - ((y1 - (_img_h/2) ) * sin(t * DEG2RAD))) / cos(t * DEG2RAD) + (_img_w / 2);
140 | y2 = _img_h - 0;
141 | x2 = ((double)(r-(_accu_h/2)) - ((y2 - (_img_h/2) ) * sin(t * DEG2RAD))) / cos(t * DEG2RAD) + (_img_w / 2);
142 | }
143 |
144 | lines.push_back(std::pair< std::pair, std::pair >(std::pair(x1,y1), std::pair(x2,y2)));
145 |
146 | }
147 | }
148 | }
149 |
150 | std::cout << "lines: " << lines.size() << " " << threshold << std::endl;
151 | return lines;
152 | }
153 |
154 | const unsigned int* Hough::GetAccu(int *w, int *h)
155 | {
156 | *w = _accu_w;
157 | *h = _accu_h;
158 |
159 | return _accu;
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/tryout/hough_circle/hough.cpp:
--------------------------------------------------------------------------------
1 | // **********************************************************************************
2 | //
3 | // BSD License.
4 | // This file is part of a Hough Transformation tutorial,
5 | // see: http://www.keymolen.com/2013/05/hough-transformation-c-implementation.html
6 | //
7 | // Copyright (c) 2013, Bruno Keymolen, email: bruno.keymolen@gmail.com
8 | // All rights reserved.
9 | //
10 | // Redistribution and use in source and binary forms, with or without modification,
11 | // are permitted provided that the following conditions are met:
12 | //
13 | // Redistributions of source code must retain the above copyright notice,
14 | // this list of conditions and the following disclaimer.
15 | // Redistributions in binary form must reproduce the above copyright notice, this
16 | // list of conditions and the following disclaimer in the documentation and/or other
17 | // materials provided with the distribution.
18 | // Neither the name of "Bruno Keymolen" nor the names of its contributors may be
19 | // used to endorse or promote products derived from this software without specific
20 | // prior written permission.
21 | //
22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 | // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26 | // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 | // POSSIBILITY OF SUCH DAMAGE.
32 | //
33 | // **********************************************************************************
34 |
35 | #include "hough.h"
36 | #include
37 | #include
38 | #include
39 | #include
40 |
41 |
42 | #define DEG2RAD 0.017453293f
43 |
44 | namespace keymolen {
45 |
46 | Hough::Hough():_accu(0), _accu_w(0), _accu_h(0), _img_w(0), _img_h(0)
47 | {
48 |
49 | }
50 |
51 | Hough::~Hough() {
52 | if(_accu)
53 | free(_accu);
54 | }
55 |
56 |
57 | int Hough::Transform(unsigned char* img_data, int w, int h)
58 | {
59 | _img_w = w;
60 | _img_h = h;
61 |
62 | //Create the accu
63 | double hough_h = ((sqrt(2.0) * (double)(h>w?h:w)) / 2.0);
64 | _accu_h = hough_h * 2.0; // -r -> +r
65 | _accu_w = 180;
66 |
67 | _accu = (unsigned int*)calloc(_accu_h * _accu_w, sizeof(unsigned int));
68 |
69 | double center_x = w/2;
70 | double center_y = h/2;
71 |
72 |
73 | for(int y=0;y 250 )
78 | {
79 | for(int t=0;t<180;t++)
80 | {
81 | double r = ( ((double)x - center_x) * cos((double)t * DEG2RAD)) + (((double)y - center_y) * sin((double)t * DEG2RAD));
82 | _accu[ (int)((round(r + hough_h) * 180.0)) + t]++;
83 | }
84 | }
85 | }
86 | }
87 |
88 | return 0;
89 | }
90 |
91 | std::vector< std::pair< std::pair, std::pair > > Hough::GetLines(int threshold)
92 | {
93 | std::vector< std::pair< std::pair, std::pair > > lines;
94 |
95 | if(_accu == 0)
96 | return lines;
97 |
98 | for(int r=0;r<_accu_h;r++)
99 | {
100 | for(int t=0;t<_accu_w;t++)
101 | {
102 | if((int)_accu[(r*_accu_w) + t] >= threshold)
103 | {
104 | //Is this point a local maxima (9x9)
105 | int max = _accu[(r*_accu_w) + t];
106 | for(int ly=-4;ly<=4;ly++)
107 | {
108 | for(int lx=-4;lx<=4;lx++)
109 | {
110 | if( (ly+r>=0 && ly+r<_accu_h) && (lx+t>=0 && lx+t<_accu_w) )
111 | {
112 | if( (int)_accu[( (r+ly)*_accu_w) + (t+lx)] > max )
113 | {
114 | max = _accu[( (r+ly)*_accu_w) + (t+lx)];
115 | ly = lx = 5;
116 | }
117 | }
118 | }
119 | }
120 | if(max > (int)_accu[(r*_accu_w) + t])
121 | continue;
122 |
123 |
124 | int x1, y1, x2, y2;
125 | x1 = y1 = x2 = y2 = 0;
126 |
127 | if(t >= 45 && t <= 135)
128 | {
129 | //y = (r - x cos(t)) / sin(t)
130 | x1 = 0;
131 | y1 = ((double)(r-(_accu_h/2)) - ((x1 - (_img_w/2) ) * cos(t * DEG2RAD))) / sin(t * DEG2RAD) + (_img_h / 2);
132 | x2 = _img_w - 0;
133 | y2 = ((double)(r-(_accu_h/2)) - ((x2 - (_img_w/2) ) * cos(t * DEG2RAD))) / sin(t * DEG2RAD) + (_img_h / 2);
134 | }
135 | else
136 | {
137 | //x = (r - y sin(t)) / cos(t);
138 | y1 = 0;
139 | x1 = ((double)(r-(_accu_h/2)) - ((y1 - (_img_h/2) ) * sin(t * DEG2RAD))) / cos(t * DEG2RAD) + (_img_w / 2);
140 | y2 = _img_h - 0;
141 | x2 = ((double)(r-(_accu_h/2)) - ((y2 - (_img_h/2) ) * sin(t * DEG2RAD))) / cos(t * DEG2RAD) + (_img_w / 2);
142 | }
143 |
144 | lines.push_back(std::pair< std::pair, std::pair >(std::pair(x1,y1), std::pair(x2,y2)));
145 |
146 | }
147 | }
148 | }
149 |
150 | std::cout << "lines: " << lines.size() << " " << threshold << std::endl;
151 | return lines;
152 | }
153 |
154 | const unsigned int* Hough::GetAccu(int *w, int *h)
155 | {
156 | *w = _accu_w;
157 | *h = _accu_h;
158 |
159 | return _accu;
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/main.cpp:
--------------------------------------------------------------------------------
1 | // **********************************************************************************
2 | //
3 | // BSD License.
4 | // This file is part of a Hough Transformation tutorial,
5 | // see: http://www.keymolen.com/2013/05/hough-transformation-c-implementation.html
6 | //
7 | // Copyright (c) 2013, Bruno Keymolen, email: bruno.keymolen@gmail.com
8 | // All rights reserved.
9 | //
10 | // Redistribution and use in source and binary forms, with or without modification,
11 | // are permitted provided that the following conditions are met:
12 | //
13 | // Redistributions of source code must retain the above copyright notice,
14 | // this list of conditions and the following disclaimer.
15 | // Redistributions in binary form must reproduce the above copyright notice, this
16 | // list of conditions and the following disclaimer in the documentation and/or other
17 | // materials provided with the distribution.
18 | // Neither the name of "Bruno Keymolen" nor the names of its contributors may be
19 | // used to endorse or promote products derived from this software without specific
20 | // prior written permission.
21 | //
22 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23 | // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 | // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 | // IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
26 | // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 | // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 | // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 | // POSSIBILITY OF SUCH DAMAGE.
32 | //
33 | // **********************************************************************************
34 |
35 | #include
36 | #include
37 | #include
38 | #include
39 | #include