PageRenderTime 57ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/extract/extract.h

http://nise.googlecode.com/
C Header | 337 lines | 288 code | 45 blank | 4 comment | 43 complexity | 647e0493293ed4829bee90c88a66c9cc MD5 | raw file
  1. #ifndef NISE_EXTRACT
  2. #define NISE_EXTRACT
  3. #include <cstdio>
  4. #include <iostream>
  5. #include <fstream>
  6. #include <vector>
  7. #include <boost/foreach.hpp>
  8. #include <opencv/cv.h>
  9. #include <opencv/highgui.h>
  10. #include <lshkit.h>
  11. extern "C" {
  12. #include "generic.h"
  13. #include "sift.h"
  14. }
  15. /// Position of a feature
  16. struct Feature {
  17. float x, y, size, dir; // dir in [0,1]
  18. float scale; //
  19. std::vector<float> desc;
  20. };
  21. static const unsigned int BYTE_MAX = 256;
  22. static inline std::istream &operator >> (std::istream &is, Feature &s) {
  23. unsigned dim;
  24. is >> s.x >> s.y >> s.size >> s.dir >> s.scale >> dim;
  25. if (is) {
  26. s.desc.resize(dim);
  27. BOOST_FOREACH(float &v, s.desc) {
  28. is >> v;
  29. }
  30. }
  31. return is;
  32. }
  33. static inline std::ostream &operator << (std::ostream &os, const Feature &s) {
  34. os << s.x << '\t' << s.y << '\t' << s.size << '\t' << s.dir << '\t' << s.scale << '\t' << s.desc.size();
  35. BOOST_FOREACH(float v, s.desc) {
  36. os << '\t' << v;
  37. }
  38. return os;
  39. }
  40. static inline CvScalar rand_color () {
  41. unsigned R = 128;
  42. unsigned G = 128;
  43. unsigned B = 128;
  44. switch (rand() % 3) {
  45. case 0: R += rand() % 128; break;
  46. case 1: G += rand() % 128; break;
  47. case 2: B += rand() % 128; break;
  48. }
  49. return CV_RGB(R, G, B);
  50. }
  51. class Image {
  52. IplImage *cv;
  53. unsigned o_width;
  54. unsigned o_height;
  55. float scale;
  56. public:
  57. Image (unsigned w, unsigned h, unsigned channel = 1)
  58. {
  59. o_width = w;
  60. o_height = h;
  61. scale = 1.0;
  62. cv = cvCreateImage(cvSize(w, h), IPL_DEPTH_8U, channel);
  63. cvSetZero(cv);
  64. }
  65. Image (const std::string &path, int MAX = 0, bool color = false)
  66. {
  67. scale = 1.0;
  68. cv = cvLoadImage(path.c_str(), color ? CV_LOAD_IMAGE_COLOR : CV_LOAD_IMAGE_GRAYSCALE);
  69. //BOOST_VERIFY(cv != 0);
  70. if (cv == 0) throw std::runtime_error("ERROR LOAD IMAGE");
  71. o_width = cv->width;
  72. o_height = cv->height;
  73. if (MAX == 0) return;
  74. if (cv->width <= MAX && cv->height <= MAX) return;
  75. CvSize size;
  76. if (MAX < 0) {
  77. scale = -MAX;
  78. size.width = cv->width / scale;
  79. size.height = cv->height / scale;
  80. }
  81. else if (cv->width < cv->height) {
  82. scale = cv->height / MAX;
  83. size.width = cv->width * MAX / cv->height;
  84. size.height = MAX;
  85. }
  86. else {
  87. scale = cv->width / MAX;
  88. size.width = MAX;
  89. size.height = cv->height * MAX / cv->width;
  90. }
  91. IplImage *old = cv;
  92. cv = cvCreateImage(size, old->depth, old->nChannels);
  93. cvResize(old, cv);
  94. cvReleaseImage(&old);
  95. }
  96. Image (const char *buf, size_t len, int MAX = 0, bool color = false) {
  97. scale = 1.0;
  98. CvMat mat;
  99. cvInitMatHeader(&mat, 1, len, CV_8UC1, const_cast<char*>(buf), len);
  100. cv = cvDecodeImage(&mat, color? CV_LOAD_IMAGE_COLOR : CV_LOAD_IMAGE_GRAYSCALE);
  101. //BOOST_VERIFY(cv != 0);
  102. if (cv == 0) throw std::runtime_error("ERROR LOAD IMAGE");
  103. o_width = cv->width;
  104. o_height = cv->height;
  105. if (MAX == 0) return;
  106. if (cv->width <= MAX && cv->height <= MAX) return;
  107. CvSize size;
  108. if (cv->width < cv->height) {
  109. scale = cv->height / MAX;
  110. size.width = cv->width * MAX / cv->height;
  111. size.height = MAX;
  112. }
  113. else {
  114. scale = cv->width / MAX;
  115. size.width = MAX;
  116. size.height = cv->height * MAX / cv->width;
  117. }
  118. IplImage *old = cv;
  119. cv = cvCreateImage(size, old->depth, old->nChannels);
  120. cvResize(old, cv);
  121. cvReleaseImage(&old);
  122. }
  123. ~Image () {
  124. cvReleaseImage(&cv);
  125. }
  126. void save (const std::string &path) {
  127. cvSaveImage(path.c_str(), cv);
  128. }
  129. unsigned width () const {
  130. return cv->width;
  131. }
  132. unsigned height () const {
  133. return cv->height;
  134. }
  135. unsigned orig_width () const {
  136. return o_width;
  137. }
  138. unsigned orig_height () const {
  139. return o_height;
  140. }
  141. float getScale () const {
  142. return scale;
  143. }
  144. void line (unsigned x1, unsigned y1, unsigned x2, unsigned y2, CvScalar color = CV_RGB(255,255,255)) {
  145. cvLine(cv, cvPoint(x1, y1),
  146. cvPoint(x2, y2),
  147. color);
  148. }
  149. void copy (const Image &im, unsigned x, unsigned y) {
  150. cvSetImageROI(cv,cvRect(x, y, im.cv->width, im.cv->height));
  151. if (cv->nChannels == 3) {
  152. cvSetImageCOI(cv, 1);
  153. cvCopy(im.cv, cv, 0);
  154. cvSetImageCOI(cv, 2);
  155. cvCopy(im.cv, cv, 0);
  156. cvSetImageCOI(cv, 3);
  157. cvCopy(im.cv, cv, 0);
  158. cvSetImageCOI(cv, 0);
  159. }
  160. else {
  161. cvCopy(im.cv, cv, 0);
  162. }
  163. cvResetImageROI(cv);
  164. }
  165. friend class Sift;
  166. void encode (std::string *data) {
  167. CvMat *mat = cvEncodeImage(".jpg", cv , 0);
  168. data->resize(mat->cols);
  169. std::copy(mat->data.ptr, mat->data.ptr + mat->cols, data->begin());
  170. cvReleaseMat(&mat);
  171. }
  172. };
  173. static inline void LoadFeatures (const std::string &path, std::vector<Feature> *list) {
  174. std::ifstream is(path.c_str());
  175. unsigned count;
  176. is >> count;
  177. if (is) {
  178. list->resize(count);
  179. BOOST_FOREACH(Feature &f, *list) {
  180. is >> f;
  181. }
  182. }
  183. }
  184. static inline void SaveFeatures (const std::string &path, const std::vector<Feature> list) {
  185. std::ofstream os(path.c_str());
  186. os << list.size() << std::endl;
  187. if (os) {
  188. BOOST_FOREACH(const Feature &f, list) {
  189. os << f << std::endl;
  190. }
  191. }
  192. }
  193. class Sift {
  194. static const unsigned DIM = SIFT_DIM;
  195. int O, S, omin;
  196. double edge_thresh;
  197. double peak_thresh;
  198. double magnif;
  199. double e_th;
  200. bool do_angle;
  201. unsigned R;
  202. std::vector<std::vector<float> > black_list;
  203. float threshold;
  204. bool checkBlackList (const std::vector<float> &desc) {
  205. lshkit::metric::l2<float> l2(Sift::dim());
  206. BOOST_FOREACH(const std::vector<float> &b, black_list) {
  207. // if (l2(&desc[0], &b[0]) < threshold) return false;
  208. float d = l2(&desc[0], &b[0]);
  209. if (d < threshold) return false;
  210. }
  211. return true;
  212. }
  213. public:
  214. static float entropy (const std::vector<float> &desc) {
  215. std::vector<unsigned> count(256);
  216. fill(count.begin(), count.end(), 0);
  217. BOOST_FOREACH(float v, desc) {
  218. unsigned c = round(v * 255);
  219. if (c < 256) count[c]++;
  220. }
  221. float e = 0;
  222. BOOST_FOREACH(unsigned c, count) {
  223. if (c > 0) {
  224. float pr = (float)c / (float)desc.size();
  225. e += - pr * log2(pr);
  226. }
  227. }
  228. return e;
  229. }
  230. Sift (int O_ = -1, int S_ = 3, int omin_ = -1,
  231. double et_ = -1, double pt_ = 3, double mag_ = -1, double e_th_ = 0, bool do_angle_ = true, unsigned R_ = 256)
  232. : O(O_), S(S_), omin(omin_), edge_thresh(et_), peak_thresh(pt_), magnif(mag_), e_th(e_th_), do_angle(do_angle_), R(R_)
  233. {
  234. }
  235. void setBlackList (const std::string &path, float t) {
  236. threshold = t;
  237. std::vector<float> tmp(Sift::dim());
  238. std::ifstream is(path.c_str(), std::ios::binary);
  239. while (is.read((char *)&tmp[0], sizeof(float) * Sift::dim())) {
  240. black_list.push_back(tmp);
  241. }
  242. }
  243. static unsigned dim () {
  244. return DIM;
  245. }
  246. void extract(Image &image, std::vector<Feature> *list);
  247. };
  248. static inline void binarify (const Feature &f, std::vector<char> *b, float qt) {
  249. unsigned dim = (f.desc.size() + 7) / 8;
  250. b->resize(dim);
  251. unsigned i = 0, j = 0;
  252. BOOST_FOREACH(float v, f.desc) {
  253. if (j == 0) {
  254. b->at(i) = 0;
  255. }
  256. if (v >= qt) b->at(i) |= (1 << j);
  257. ++j;
  258. if (j == 8) {
  259. j = 0;
  260. ++i;
  261. }
  262. }
  263. }
  264. static const unsigned SAMPLE_RANDOM = 0;
  265. static const unsigned SAMPLE_SIZE = 1;
  266. static inline bool sift_by_size (const Feature &f1, const Feature &f2) {
  267. return f1.size > f2.size;
  268. }
  269. static inline void SampleFeature (std::vector<Feature> *sift, unsigned count, unsigned method) {
  270. if (sift->size() < count) return;
  271. if (method == SAMPLE_RANDOM) {
  272. std::random_shuffle(sift->begin(), sift->end());
  273. }
  274. else if (method == SAMPLE_SIZE) {
  275. std::sort(sift->begin(), sift->end(), sift_by_size);
  276. }
  277. else {
  278. BOOST_VERIFY(0);
  279. }
  280. sift->resize(count);
  281. }
  282. static inline void logscale (std::vector<Feature> *v, float l) {
  283. float s = -log(l);
  284. BOOST_FOREACH(Feature &f, *v) {
  285. BOOST_FOREACH(float &d, f.desc) {
  286. if (d < l) d = l;
  287. d = (log(d) + s) / s;
  288. if (d > 1.0) d = 1.0;
  289. }
  290. }
  291. }
  292. #endif