opencv-ffi 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ //-------------------------------------------------------