opencv-ffi 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. data/.gitignore +7 -0
  2. data/Gemfile +15 -0
  3. data/README.md +126 -0
  4. data/Rakefile +52 -0
  5. data/docs/DocsIndex.md +1 -0
  6. data/docs/examples/load_image.rb +25 -0
  7. data/ext/Rakefile +13 -0
  8. data/ext/aishack-sift/.gitignore +4 -0
  9. data/ext/aishack-sift/Descriptor.h +34 -0
  10. data/ext/aishack-sift/KeyPoint.h +38 -0
  11. data/ext/aishack-sift/README +20 -0
  12. data/ext/aishack-sift/SIFT.cpp +1036 -0
  13. data/ext/aishack-sift/SIFT.h +84 -0
  14. data/ext/aishack-sift/example/.gitignore +2 -0
  15. data/ext/aishack-sift/example/Makefile +24 -0
  16. data/ext/aishack-sift/example/MySIFT.cpp +29 -0
  17. data/ext/aishack-sift/mkrf_conf.rb +13 -0
  18. data/ext/aishack-sift/siftlib.cpp +85 -0
  19. data/ext/eigen/.gitignore +4 -0
  20. data/ext/eigen/eigen_polynomial.cpp +41 -0
  21. data/ext/eigen/eigen_svd.cpp +100 -0
  22. data/ext/eigen/mkrf_conf.rb +14 -0
  23. data/ext/mkrf-monkey.rb +85 -0
  24. data/ext/mkrf-rakehelper-monkey.rb +52 -0
  25. data/ext/mkrf_conf.rb +3 -0
  26. data/ext/opencv-ffi/.gitignore +4 -0
  27. data/ext/opencv-ffi/matcher_helper.cpp +56 -0
  28. data/ext/opencv-ffi/mkrf_conf.rb +12 -0
  29. data/ext/opencv-ffi/vector_math.cpp +39 -0
  30. data/ext/opensurf/.gitignore +4 -0
  31. data/ext/opensurf/README +38 -0
  32. data/ext/opensurf/fasthessian.cpp +376 -0
  33. data/ext/opensurf/fasthessian.h +108 -0
  34. data/ext/opensurf/integral.cpp +58 -0
  35. data/ext/opensurf/integral.h +55 -0
  36. data/ext/opensurf/ipoint.cpp +108 -0
  37. data/ext/opensurf/ipoint.h +76 -0
  38. data/ext/opensurf/kmeans.h +172 -0
  39. data/ext/opensurf/mkrf_conf.rb +10 -0
  40. data/ext/opensurf/responselayer.h +92 -0
  41. data/ext/opensurf/surf.cpp +317 -0
  42. data/ext/opensurf/surf.h +66 -0
  43. data/ext/opensurf/surflib.cpp +98 -0
  44. data/ext/opensurf/surflib.h +96 -0
  45. data/ext/opensurf/utils.cpp +357 -0
  46. data/ext/opensurf/utils.h +63 -0
  47. data/lib/.gitignore +1 -0
  48. data/lib/opencv-ffi-ext/eigen.rb +84 -0
  49. data/lib/opencv-ffi-ext/features2d.rb +4 -0
  50. data/lib/opencv-ffi-ext/matcher_helper.rb +24 -0
  51. data/lib/opencv-ffi-ext/opensurf.rb +217 -0
  52. data/lib/opencv-ffi-ext/sift.rb +118 -0
  53. data/lib/opencv-ffi-ext/vector_math.rb +115 -0
  54. data/lib/opencv-ffi-wrappers.rb +7 -0
  55. data/lib/opencv-ffi-wrappers/core.rb +24 -0
  56. data/lib/opencv-ffi-wrappers/core/iplimage.rb +50 -0
  57. data/lib/opencv-ffi-wrappers/core/mat.rb +268 -0
  58. data/lib/opencv-ffi-wrappers/core/misc_draw.rb +44 -0
  59. data/lib/opencv-ffi-wrappers/core/point.rb +286 -0
  60. data/lib/opencv-ffi-wrappers/core/rect.rb +40 -0
  61. data/lib/opencv-ffi-wrappers/core/scalar.rb +104 -0
  62. data/lib/opencv-ffi-wrappers/core/size.rb +88 -0
  63. data/lib/opencv-ffi-wrappers/enumerable.rb +10 -0
  64. data/lib/opencv-ffi-wrappers/features2d.rb +17 -0
  65. data/lib/opencv-ffi-wrappers/features2d/image_patch.rb +322 -0
  66. data/lib/opencv-ffi-wrappers/features2d/star.rb +111 -0
  67. data/lib/opencv-ffi-wrappers/features2d/surf.rb +115 -0
  68. data/lib/opencv-ffi-wrappers/highgui.rb +10 -0
  69. data/lib/opencv-ffi-wrappers/imgproc.rb +4 -0
  70. data/lib/opencv-ffi-wrappers/imgproc/features.rb +35 -0
  71. data/lib/opencv-ffi-wrappers/imgproc/geometric.rb +39 -0
  72. data/lib/opencv-ffi-wrappers/matcher.rb +297 -0
  73. data/lib/opencv-ffi-wrappers/matrix.rb +37 -0
  74. data/lib/opencv-ffi-wrappers/misc.rb +41 -0
  75. data/lib/opencv-ffi-wrappers/misc/params.rb +34 -0
  76. data/lib/opencv-ffi-wrappers/sequence.rb +37 -0
  77. data/lib/opencv-ffi-wrappers/vectors.rb +38 -0
  78. data/lib/opencv-ffi.rb +12 -0
  79. data/lib/opencv-ffi/calib3d.rb +26 -0
  80. data/lib/opencv-ffi/core.rb +15 -0
  81. data/lib/opencv-ffi/core/draw.rb +68 -0
  82. data/lib/opencv-ffi/core/dynamic.rb +13 -0
  83. data/lib/opencv-ffi/core/library.rb +5 -0
  84. data/lib/opencv-ffi/core/operations.rb +122 -0
  85. data/lib/opencv-ffi/core/point.rb +22 -0
  86. data/lib/opencv-ffi/core/types.rb +172 -0
  87. data/lib/opencv-ffi/cvffi.rb +8 -0
  88. data/lib/opencv-ffi/features2d.rb +7 -0
  89. data/lib/opencv-ffi/features2d/library.rb +6 -0
  90. data/lib/opencv-ffi/features2d/star.rb +30 -0
  91. data/lib/opencv-ffi/features2d/surf.rb +38 -0
  92. data/lib/opencv-ffi/highgui.rb +31 -0
  93. data/lib/opencv-ffi/imgproc.rb +9 -0
  94. data/lib/opencv-ffi/imgproc/features.rb +37 -0
  95. data/lib/opencv-ffi/imgproc/geometric.rb +42 -0
  96. data/lib/opencv-ffi/imgproc/library.rb +6 -0
  97. data/lib/opencv-ffi/imgproc/misc.rb +39 -0
  98. data/lib/opencv-ffi/version.rb +3 -0
  99. data/opencv-ffi.gemspec +26 -0
  100. data/test/core/test_draw.rb +46 -0
  101. data/test/core/test_operations.rb +135 -0
  102. data/test/core/test_size.rb +14 -0
  103. data/test/core/test_text.rb +52 -0
  104. data/test/ext/test_eigen.rb +105 -0
  105. data/test/ext/test_opensurf.rb +35 -0
  106. data/test/ext/test_sift.rb +26 -0
  107. data/test/ext/test_vector_math.rb +85 -0
  108. data/test/features2d/test_surf.rb +63 -0
  109. data/test/imgproc/test_goodfeatures.rb +18 -0
  110. data/test/setup.rb +65 -0
  111. data/test/test_calib3d.rb +38 -0
  112. data/test/test_core.rb +26 -0
  113. data/test/test_ext.rb +8 -0
  114. data/test/test_features2d.rb +9 -0
  115. data/test/test_files/images/IMG_7088.JPG +0 -0
  116. data/test/test_files/images/IMG_7088_small.JPG +0 -0
  117. data/test/test_files/images/IMG_7089.JPG +0 -0
  118. data/test/test_highgui.rb +26 -0
  119. data/test/test_imgproc.rb +35 -0
  120. data/test/test_wrappers.rb +8 -0
  121. data/test/wrappers/core/test_draw.rb +41 -0
  122. data/test/wrappers/core/test_mat.rb +40 -0
  123. data/test/wrappers/core/test_operations.rb +35 -0
  124. data/test/wrappers/core/test_types.rb +235 -0
  125. data/test/wrappers/features2d/test_image_patch.rb +108 -0
  126. data/test/wrappers/test_imgproc.rb +87 -0
  127. data/test/wrappers/test_matcher.rb +96 -0
  128. data/test/wrappers/test_star.rb +28 -0
  129. data/test/wrappers/test_surf.rb +36 -0
  130. metadata +234 -0
@@ -0,0 +1,108 @@
1
+ /***********************************************************
2
+ * --- OpenSURF --- *
3
+ * This library is distributed under the GNU GPL. Please *
4
+ * use the contact form at http://www.chrisevansdev.com *
5
+ * for more information. *
6
+ * *
7
+ * C. Evans, Research Into Robust Visual Features, *
8
+ * MSc University of Bristol, 2008. *
9
+ * *
10
+ ************************************************************/
11
+
12
+ #ifndef FASTHESSIAN_H
13
+ #define FASTHESSIAN_H
14
+
15
+ #include <opencv2/core/core.hpp>
16
+ #include <opencv2/core/core_c.h>
17
+ #include "ipoint.h"
18
+
19
+ #include <vector>
20
+
21
+ class ResponseLayer;
22
+ static const int OCTAVES = 5;
23
+ static const int INTERVALS = 4;
24
+ static const float THRES = 0.0004f;
25
+ static const int INIT_SAMPLE = 2;
26
+
27
+
28
+ class FastHessian {
29
+
30
+ public:
31
+
32
+ //! Constructor without image
33
+ FastHessian(std::vector<Ipoint> &ipts,
34
+ const int octaves = OCTAVES,
35
+ const int intervals = INTERVALS,
36
+ const int init_sample = INIT_SAMPLE,
37
+ const float thres = THRES);
38
+
39
+ //! Constructor with image
40
+ FastHessian(IplImage *img,
41
+ std::vector<Ipoint> &ipts,
42
+ const int octaves = OCTAVES,
43
+ const int intervals = INTERVALS,
44
+ const int init_sample = INIT_SAMPLE,
45
+ const float thres = THRES);
46
+
47
+ //! Destructor
48
+ ~FastHessian();
49
+
50
+ //! Save the parameters
51
+ void saveParameters(const int octaves,
52
+ const int intervals,
53
+ const int init_sample,
54
+ const float thres);
55
+
56
+ //! Set or re-set the integral image source
57
+ void setIntImage(IplImage *img);
58
+
59
+ //! Find the image features and write into vector of features
60
+ void getIpoints();
61
+
62
+ private:
63
+
64
+ //---------------- Private Functions -----------------//
65
+
66
+ //! Build map of DoH responses
67
+ void buildResponseMap();
68
+
69
+ //! Calculate DoH responses for supplied layer
70
+ void buildResponseLayer(ResponseLayer *r);
71
+
72
+ //! 3x3x3 Extrema test
73
+ int isExtremum(int r, int c, ResponseLayer *t, ResponseLayer *m, ResponseLayer *b);
74
+
75
+ //! Interpolation functions - adapted from Lowe's SIFT implementation
76
+ void interpolateExtremum(int r, int c, ResponseLayer *t, ResponseLayer *m, ResponseLayer *b);
77
+ void interpolateStep(int r, int c, ResponseLayer *t, ResponseLayer *m, ResponseLayer *b,
78
+ double* xi, double* xr, double* xc );
79
+ CvMat* deriv3D(int r, int c, ResponseLayer *t, ResponseLayer *m, ResponseLayer *b);
80
+ CvMat* hessian3D(int r, int c, ResponseLayer *t, ResponseLayer *m, ResponseLayer *b);
81
+
82
+ //---------------- Private Variables -----------------//
83
+
84
+ //! Pointer to the integral Image, and its attributes
85
+ IplImage *img;
86
+ int i_width, i_height;
87
+
88
+ //! Reference to vector of features passed from outside
89
+ std::vector<Ipoint> &ipts;
90
+
91
+ //! Response stack of determinant of hessian values
92
+ std::vector<ResponseLayer *> responseMap;
93
+
94
+ //! Number of Octaves
95
+ int octaves;
96
+
97
+ //! Number of Intervals per octave
98
+ int intervals;
99
+
100
+ //! Initial sampling step for Ipoint detection
101
+ int init_sample;
102
+
103
+ //! Threshold value for blob resonses
104
+ float thresh;
105
+ };
106
+
107
+
108
+ #endif
@@ -0,0 +1,58 @@
1
+ /***********************************************************
2
+ * --- OpenSURF --- *
3
+ * This library is distributed under the GNU GPL. Please *
4
+ * use the contact form at http://www.chrisevansdev.com *
5
+ * for more information. *
6
+ * *
7
+ * C. Evans, Research Into Robust Visual Features, *
8
+ * MSc University of Bristol, 2008. *
9
+ * *
10
+ ************************************************************/
11
+
12
+ #include <opencv2/imgproc/imgproc_c.h>
13
+
14
+ #include "utils.h"
15
+
16
+ #include "integral.h"
17
+
18
+ //! Computes the integral image of image img. Assumes source image to be a
19
+ //! 32-bit floating point. Returns IplImage of 32-bit float form.
20
+ IplImage *Integral(IplImage *source)
21
+ {
22
+ // convert the image to single channel 32f
23
+ IplImage *img = getGray(source);
24
+ IplImage *int_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_32F, 1);
25
+
26
+ // set up variables for data access
27
+ int height = img->height;
28
+ int width = img->width;
29
+ int step = img->widthStep/sizeof(float);
30
+ float *data = (float *) img->imageData;
31
+ float *i_data = (float *) int_img->imageData;
32
+
33
+ // first row only
34
+ float rs = 0.0f;
35
+ for(int j=0; j<width; j++)
36
+ {
37
+ rs += data[j];
38
+ i_data[j] = rs;
39
+ }
40
+
41
+ // remaining cells are sum above and to the left
42
+ for(int i=1; i<height; ++i)
43
+ {
44
+ rs = 0.0f;
45
+ for(int j=0; j<width; ++j)
46
+ {
47
+ rs += data[i*step+j];
48
+ i_data[i*step+j] = rs + i_data[(i-1)*step+j];
49
+ }
50
+ }
51
+
52
+ // release the gray image
53
+ cvReleaseImage(&img);
54
+
55
+ // return the integral image
56
+ return int_img;
57
+ }
58
+
@@ -0,0 +1,55 @@
1
+ /***********************************************************
2
+ * --- OpenSURF --- *
3
+ * This library is distributed under the GNU GPL. Please *
4
+ * use the contact form at http://www.chrisevansdev.com *
5
+ * for more information. *
6
+ * *
7
+ * C. Evans, Research Into Robust Visual Features, *
8
+ * MSc University of Bristol, 2008. *
9
+ * *
10
+ ************************************************************/
11
+
12
+ #ifndef INTEGRAL_H
13
+ #define INTEGRAL_H
14
+
15
+ #include <algorithm> // req'd for std::min/max
16
+
17
+ // undefine VS macros
18
+ #ifdef min
19
+ #undef min
20
+ #endif
21
+
22
+ #ifdef max
23
+ #undef max
24
+ #endif
25
+
26
+ #include <opencv2/core/core.hpp>
27
+
28
+ //! Computes the integral image of image img. Assumes source image to be a
29
+ //! 32-bit floating point. Returns IplImage in 32-bit float form.
30
+ IplImage *Integral(IplImage *img);
31
+
32
+
33
+ //! Computes the sum of pixels within the rectangle specified by the top-left start
34
+ //! co-ordinate and size
35
+ inline float BoxIntegral(IplImage *img, int row, int col, int rows, int cols)
36
+ {
37
+ float *data = (float *) img->imageData;
38
+ int step = img->widthStep/sizeof(float);
39
+
40
+ // The subtraction by one for row/col is because row/col is inclusive.
41
+ int r1 = std::min(row, img->height) - 1;
42
+ int c1 = std::min(col, img->width) - 1;
43
+ int r2 = std::min(row + rows, img->height) - 1;
44
+ int c2 = std::min(col + cols, img->width) - 1;
45
+
46
+ float A(0.0f), B(0.0f), C(0.0f), D(0.0f);
47
+ if (r1 >= 0 && c1 >= 0) A = data[r1 * step + c1];
48
+ if (r1 >= 0 && c2 >= 0) B = data[r1 * step + c2];
49
+ if (r2 >= 0 && c1 >= 0) C = data[r2 * step + c1];
50
+ if (r2 >= 0 && c2 >= 0) D = data[r2 * step + c2];
51
+
52
+ return std::max(0.f, A - B - C + D);
53
+ }
54
+
55
+ #endif
@@ -0,0 +1,108 @@
1
+ /***********************************************************
2
+ * --- OpenSURF --- *
3
+ * This library is distributed under the GNU GPL. Please *
4
+ * use the contact form at http://www.chrisevansdev.com *
5
+ * for more information. *
6
+ * *
7
+ * C. Evans, Research Into Robust Visual Features, *
8
+ * MSc University of Bristol, 2008. *
9
+ * *
10
+ ************************************************************/
11
+
12
+ #include <opencv2/core/core.hpp>
13
+ #include <opencv2/calib3d/calib3d.hpp>
14
+ #include <vector>
15
+
16
+ #include "ipoint.h"
17
+
18
+ using namespace cv;
19
+
20
+ //! Populate IpPairVec with matched ipts
21
+ void getMatches(IpVec &ipts1, IpVec &ipts2, IpPairVec &matches)
22
+ {
23
+ float dist, d1, d2;
24
+ Ipoint *match;
25
+
26
+ matches.clear();
27
+
28
+ for(unsigned int i = 0; i < ipts1.size(); i++)
29
+ {
30
+ d1 = d2 = FLT_MAX;
31
+
32
+ for(unsigned int j = 0; j < ipts2.size(); j++)
33
+ {
34
+ dist = ipts1[i] - ipts2[j];
35
+
36
+ if(dist<d1) // if this feature matches better than current best
37
+ {
38
+ d2 = d1;
39
+ d1 = dist;
40
+ match = &ipts2[j];
41
+ }
42
+ else if(dist<d2) // this feature matches better than second best
43
+ {
44
+ d2 = dist;
45
+ }
46
+ }
47
+
48
+ // If match has a d1:d2 ratio < 0.65 ipoints are a match
49
+ if(d1/d2 < 0.65)
50
+ {
51
+ // Store the change in position
52
+ ipts1[i].dx = match->x - ipts1[i].x;
53
+ ipts1[i].dy = match->y - ipts1[i].y;
54
+ matches.push_back(std::make_pair(ipts1[i], *match));
55
+ }
56
+ }
57
+ }
58
+
59
+ //
60
+ // This function uses homography with CV_RANSAC (OpenCV 1.1)
61
+ // Won't compile on most linux distributions
62
+ //
63
+
64
+ //-------------------------------------------------------
65
+
66
+ //! Find homography between matched points and translate src_corners to dst_corners
67
+ int translateCorners(IpPairVec &matches, const CvPoint src_corners[4], CvPoint dst_corners[4])
68
+ {
69
+ #ifndef LINUX
70
+ double h[9];
71
+ CvMat _h = cvMat(3, 3, CV_64F, h);
72
+ std::vector<CvPoint2D32f> pt1, pt2;
73
+ CvMat _pt1, _pt2;
74
+
75
+ int n = (int)matches.size();
76
+ if( n < 4 ) return 0;
77
+
78
+ // Set vectors to correct size
79
+ pt1.resize(n);
80
+ pt2.resize(n);
81
+
82
+ // Copy Ipoints from match vector into cvPoint vectors
83
+ for(int i = 0; i < n; i++ )
84
+ {
85
+ pt1[i] = cvPoint2D32f(matches[i].second.x, matches[i].second.y);
86
+ pt2[i] = cvPoint2D32f(matches[i].first.x, matches[i].first.y);
87
+ }
88
+ _pt1 = cvMat(1, n, CV_32FC2, &pt1[0] );
89
+ _pt2 = cvMat(1, n, CV_32FC2, &pt2[0] );
90
+
91
+ // Find the homography (transformation) between the two sets of points
92
+ if(!cvFindHomography(&_pt1, &_pt2, &_h, CV_RANSAC, 5)) // this line requires opencv 1.1
93
+ return 0;
94
+
95
+ // Translate src_corners to dst_corners using homography
96
+ for(int i = 0; i < 4; i++ )
97
+ {
98
+ double x = src_corners[i].x, y = src_corners[i].y;
99
+ double Z = 1./(h[6]*x + h[7]*y + h[8]);
100
+ double X = (h[0]*x + h[1]*y + h[2])*Z;
101
+ double Y = (h[3]*x + h[4]*y + h[5])*Z;
102
+ dst_corners[i] = cvPoint(cvRound(X), cvRound(Y));
103
+ }
104
+ #endif
105
+ return 1;
106
+ }
107
+
108
+
@@ -0,0 +1,76 @@
1
+ /***********************************************************
2
+ * --- OpenSURF --- *
3
+ * This library is distributed under the GNU GPL. Please *
4
+ * use the contact form at http://www.chrisevansdev.com *
5
+ * for more information. *
6
+ * *
7
+ * C. Evans, Research Into Robust Visual Features, *
8
+ * MSc University of Bristol, 2008. *
9
+ * *
10
+ ************************************************************/
11
+
12
+ #ifndef IPOINT_H
13
+ #define IPOINT_H
14
+
15
+ #include <vector>
16
+ #include <math.h>
17
+
18
+ //-------------------------------------------------------
19
+
20
+ class Ipoint; // Pre-declaration
21
+ typedef std::vector<Ipoint> IpVec;
22
+ typedef std::vector<std::pair<Ipoint, Ipoint> > IpPairVec;
23
+
24
+ //-------------------------------------------------------
25
+
26
+ //! Ipoint operations
27
+ void getMatches(IpVec &ipts1, IpVec &ipts2, IpPairVec &matches);
28
+ int translateCorners(IpPairVec &matches, const CvPoint src_corners[4], CvPoint dst_corners[4]);
29
+
30
+ //-------------------------------------------------------
31
+
32
+ class Ipoint {
33
+
34
+ public:
35
+
36
+ //! Destructor
37
+ ~Ipoint() {};
38
+
39
+ //! Constructor
40
+ Ipoint() : orientation(0) {};
41
+
42
+ //! Gets the distance in descriptor space between Ipoints
43
+ float operator-(const Ipoint &rhs)
44
+ {
45
+ float sum=0.f;
46
+ for(int i=0; i < 64; ++i)
47
+ sum += (this->descriptor[i] - rhs.descriptor[i])*(this->descriptor[i] - rhs.descriptor[i]);
48
+ return sqrt(sum);
49
+ };
50
+
51
+ //! Coordinates of the detected interest point
52
+ float x, y;
53
+
54
+ //! Detected scale
55
+ float scale;
56
+
57
+ //! Orientation measured anti-clockwise from +ve x-axis
58
+ float orientation;
59
+
60
+ //! Sign of laplacian for fast matching purposes
61
+ int laplacian;
62
+
63
+ //! Vector of descriptor components
64
+ float descriptor[64];
65
+
66
+ //! Placeholds for point motion (can be used for frame to frame motion analysis)
67
+ float dx, dy;
68
+
69
+ //! Used to store cluster index
70
+ int clusterIndex;
71
+ };
72
+
73
+ //-------------------------------------------------------
74
+
75
+
76
+ #endif
@@ -0,0 +1,172 @@
1
+ /***********************************************************
2
+ * --- OpenSURF --- *
3
+ * This library is distributed under the GNU GPL. Please *
4
+ * use the contact form at http://www.chrisevansdev.com *
5
+ * for more information. *
6
+ * *
7
+ * C. Evans, Research Into Robust Visual Features, *
8
+ * MSc University of Bristol, 2008. *
9
+ * *
10
+ ************************************************************/
11
+
12
+ #include "ipoint.h"
13
+
14
+ #include <vector>
15
+ #include <time.h>
16
+ #include <stdlib.h>
17
+
18
+ //-----------------------------------------------------------
19
+ // Kmeans clustering class (under development)
20
+ // - Can be used to cluster points based on their location.
21
+ // - Create Kmeans object and call Run with IpVec.
22
+ // - Planned improvements include clustering based on motion
23
+ // and descriptor components.
24
+ //-----------------------------------------------------------
25
+
26
+ class Kmeans {
27
+
28
+ public:
29
+
30
+ //! Destructor
31
+ ~Kmeans() {};
32
+
33
+ //! Constructor
34
+ Kmeans() {};
35
+
36
+ //! Do it all!
37
+ void Run(IpVec *ipts, int clusters, bool init = false);
38
+
39
+ //! Set the ipts to be used
40
+ void SetIpoints(IpVec *ipts);
41
+
42
+ //! Randomly distribute 'n' clusters
43
+ void InitRandomClusters(int n);
44
+
45
+ //! Assign Ipoints to clusters
46
+ bool AssignToClusters();
47
+
48
+ //! Calculate new cluster centers
49
+ void RepositionClusters();
50
+
51
+ //! Function to measure the distance between 2 ipoints
52
+ float Distance(Ipoint &ip1, Ipoint &ip2);
53
+
54
+ //! Vector stores ipoints for this run
55
+ IpVec *ipts;
56
+
57
+ //! Vector stores cluster centers
58
+ IpVec clusters;
59
+
60
+ };
61
+
62
+ //-------------------------------------------------------
63
+
64
+ void Kmeans::Run(IpVec *ipts, int clusters, bool init)
65
+ {
66
+ if (!ipts->size()) return;
67
+
68
+ SetIpoints(ipts);
69
+
70
+ if (init) InitRandomClusters(clusters);
71
+
72
+ while (AssignToClusters());
73
+ {
74
+ RepositionClusters();
75
+ }
76
+ }
77
+
78
+ //-------------------------------------------------------
79
+
80
+ void Kmeans::SetIpoints(IpVec *ipts)
81
+ {
82
+ this->ipts = ipts;
83
+ }
84
+
85
+ //-------------------------------------------------------
86
+
87
+ void Kmeans::InitRandomClusters(int n)
88
+ {
89
+ // clear the cluster vector
90
+ clusters.clear();
91
+
92
+ // Seed the random number generator
93
+ srand((int)time(NULL));
94
+
95
+ // add 'n' random ipoints to clusters list as initial centers
96
+ for (int i = 0; i < n; ++i)
97
+ {
98
+ clusters.push_back(ipts->at(rand() % ipts->size()));
99
+ }
100
+ }
101
+
102
+ //-------------------------------------------------------
103
+
104
+ bool Kmeans::AssignToClusters()
105
+ {
106
+ bool Updated = false;
107
+
108
+ // loop over all Ipoints and assign each to closest cluster
109
+ for (unsigned int i = 0; i < ipts->size(); ++i)
110
+ {
111
+ float bestDist = FLT_MAX;
112
+ int oldIndex = ipts->at(i).clusterIndex;
113
+
114
+ for (unsigned int j = 0; j < clusters.size(); ++j)
115
+ {
116
+ float currentDist = Distance(ipts->at(i), clusters[j]);
117
+ if (currentDist < bestDist)
118
+ {
119
+ bestDist = currentDist;
120
+ ipts->at(i).clusterIndex = j;
121
+ }
122
+ }
123
+
124
+ // determine whether point has changed cluster
125
+ if (ipts->at(i).clusterIndex != oldIndex) Updated = true;
126
+ }
127
+
128
+ return Updated;
129
+ }
130
+
131
+ //-------------------------------------------------------
132
+
133
+ void Kmeans::RepositionClusters()
134
+ {
135
+ float x, y, dx, dy, count;
136
+
137
+ for (unsigned int i = 0; i < clusters.size(); ++i)
138
+ {
139
+ x = y = dx = dy = 0;
140
+ count = 1;
141
+
142
+ for (unsigned int j = 0; j < ipts->size(); ++j)
143
+ {
144
+ if (ipts->at(j).clusterIndex == i)
145
+ {
146
+ Ipoint ip = ipts->at(j);
147
+ x += ip.x;
148
+ y += ip.y;
149
+ dx += ip.dx;
150
+ dy += ip.dy;
151
+ ++count;
152
+ }
153
+ }
154
+
155
+ clusters[i].x = x/count;
156
+ clusters[i].y = y/count;
157
+ clusters[i].dx = dx/count;
158
+ clusters[i].dy = dy/count;
159
+ }
160
+ }
161
+
162
+ //-------------------------------------------------------
163
+
164
+ float Kmeans::Distance(Ipoint &ip1, Ipoint &ip2)
165
+ {
166
+ return sqrt(pow(ip1.x - ip2.x, 2)
167
+ + pow(ip1.y - ip2.y, 2)
168
+ /*+ pow(ip1.dx - ip2.dx, 2)
169
+ + pow(ip1.dy - ip2.dy, 2)*/);
170
+ }
171
+
172
+ //-------------------------------------------------------