Image_tools.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /**
  2. * @file Image_tools.cpp
  3. * @brief Contains tools for Image_Processing
  4. * @author Alexander Lütz
  5. * @date 18/11/2010
  6. */
  7. #include "Image_tools.h"
  8. // #include "vislearning/cbaselib/MultiDataset.h" //only for showImage()
  9. #include <cmath> //floor
  10. #include <algorithm> //min
  11. using namespace std;
  12. using namespace OBJREC;
  13. using namespace NICE;
  14. /**
  15. * @brief Simple constructor
  16. * @author Alexander Lütz
  17. * @date 18/11/2010
  18. */
  19. Image_tools::Image_tools() {
  20. }
  21. /**
  22. * @brief Simple destructor
  23. * @author Alexander Lütz
  24. * @date 18/11/2010
  25. */
  26. Image_tools::~Image_tools() {
  27. }
  28. /**
  29. * @brief Calculates Gradient-X-Image and Gradient-Y-Image for a Greyscale-Image
  30. * @author Alexander Lütz
  31. * @date 18/11/2010
  32. */
  33. void Image_tools::calculateGradients(const NICE::Image & origImage, NICE::ImageT<float> & grad_x_Image, NICE::ImageT<float> & grad_y_Image )
  34. {
  35. grad_x_Image.resize(origImage.width(), origImage.height());
  36. grad_y_Image.resize(origImage.width(), origImage.height());
  37. //init
  38. grad_x_Image.set(0.0);
  39. grad_y_Image.set(0.0);
  40. //image_border
  41. for (int j = 0; j < origImage.height(); j++)
  42. {
  43. grad_x_Image.setPixel(0,j, 0);
  44. grad_x_Image.setPixel(origImage.width()-1,j,0);
  45. }
  46. for (int i = 0; i < origImage.width(); i++)
  47. {
  48. grad_y_Image.setPixel(i,0,0);
  49. grad_y_Image.setPixel(i,origImage.height()-1, 0);
  50. }
  51. //init
  52. int left = 0;
  53. int actual = 0;
  54. int right = 0;
  55. //inside image
  56. for (int y = 0; y < origImage.height(); y++)
  57. {
  58. actual = origImage(0,y);
  59. right = origImage(1,y);
  60. for (int x = 1; x < (origImage.width()-1); x++)
  61. {
  62. left = actual;
  63. actual = right;
  64. right = origImage(x+1,y);
  65. grad_x_Image.setPixel(x,y,-left+right);
  66. }
  67. }
  68. //inside image
  69. for (int x = 0; x < origImage.width(); x++)
  70. {
  71. actual = origImage(x,0);
  72. right = origImage(x,1);
  73. for (int y = 1; y < (origImage.height()-1); y++)
  74. {
  75. left = actual;
  76. actual = right;
  77. right = origImage(x,y+1);
  78. grad_y_Image.setPixel(x,y,-left+right);
  79. }
  80. }
  81. }
  82. /**
  83. * @brief Calculates Gradient-X-Image and Gradient-Y-Image for a ColorImage (RGB)
  84. * @author Alexander Lütz
  85. * @date 18/11/2010
  86. */
  87. void Image_tools::calculateGradients(NICE::ColorImage origColorImage, NICE::ImageT<float> & grad_x_Image, NICE::ImageT<float> & grad_y_Image)
  88. {
  89. grad_x_Image = NICE::ImageT<float>(origColorImage.width(), origColorImage.height());
  90. grad_y_Image = NICE::ImageT<float>(origColorImage.width(), origColorImage.height());
  91. NICE::ImageT<float> grad_x_Image_R;
  92. NICE::ImageT<float> grad_x_Image_G;
  93. NICE::ImageT<float> grad_x_Image_B;
  94. NICE::ImageT<float> grad_y_Image_R;
  95. NICE::ImageT<float> grad_y_Image_G;
  96. NICE::ImageT<float> grad_y_Image_B;
  97. NICE::Image * channel_Image_R = origColorImage.getChannel(0);
  98. NICE::Image * channel_Image_G = origColorImage.getChannel(1);
  99. NICE::Image * channel_Image_B = origColorImage.getChannel(2);
  100. calculateGradients(*channel_Image_R, grad_x_Image_R, grad_y_Image_R);
  101. calculateGradients(*channel_Image_G, grad_x_Image_G, grad_y_Image_G);
  102. calculateGradients(*channel_Image_B, grad_x_Image_B, grad_y_Image_B);
  103. //use maximum in each pixel
  104. for (int y = 0; y < origColorImage.height(); y++)
  105. for (int x = 0; x < origColorImage.width(); x++)
  106. {
  107. int max_x(grad_x_Image_R.getPixel(x,y));
  108. int max_y(grad_y_Image_R.getPixel(x,y));
  109. if (abs(grad_x_Image_G.getPixel(x,y)) > abs(max_x))
  110. max_x = grad_x_Image_G.getPixel(x,y);
  111. if (abs(grad_y_Image_G.getPixel(x,y)) > abs(max_y))
  112. max_y = grad_y_Image_G.getPixel(x,y);
  113. if (abs(grad_x_Image_B.getPixel(x,y)) > abs(max_x))
  114. max_x = grad_x_Image_B.getPixel(x,y);
  115. if (abs(grad_y_Image_B.getPixel(x,y)) > abs(max_y))
  116. max_y = grad_y_Image_B.getPixel(x,y);
  117. grad_x_Image.setPixel(x,y,max_x);
  118. grad_y_Image.setPixel(x,y,max_y);
  119. }
  120. }
  121. /**
  122. * @brief Calculates Gradient-orientations, only possible, if number_Of_Bins smaller than 256
  123. * @author Alexander Lütz
  124. * @date 18/11/2010
  125. */
  126. void Image_tools::calculateGradientOrientations(const NICE::ImageT<float> & grad_x_Image, const NICE::ImageT<float> & grad_y_Image , const int & number_Of_Bins, NICE::Image & gradient_orientations, const bool unsignedBins)
  127. {
  128. gradient_orientations = NICE::Image(grad_x_Image.width(), grad_x_Image.height());
  129. double bin_width = 180.0/number_Of_Bins;
  130. if (!unsignedBins)
  131. bin_width *= 2.0;
  132. for (int y = 0; y < grad_x_Image.height(); y++)
  133. {
  134. for (int x = 0; x < grad_x_Image.width(); x++)
  135. {
  136. double angle = (atan2(grad_x_Image.getPixel(x,y),grad_y_Image.getPixel(x,y)) + M_PI)*180/M_PI;
  137. //NOTE It would be better, if we would subtract 1/2 binsize, but Anna Bosch hasn't done it in her original paper, so we won't do it as well
  138. // angle = abs (angle*180/M_PI -0.5*bin_width); //atan2 and - 1/2 bin
  139. while (angle >= 360.0)
  140. angle -= 360.0;
  141. while (angle < 0.0) //can not be reached, but doesn't matter
  142. angle += 360.0;
  143. if (unsignedBins)
  144. {
  145. while (angle>=180.0)
  146. angle -= 180.0;
  147. }
  148. //NOTE Update 2011-02-10: ceil is ok, if the indicees are from 1 to number_Of_Bins. Of course we do NOT want this, but instaed we deal with 0 to number_Of_Bins-1. Therefor floor is our choice!
  149. int bin = (int) floor(angle/bin_width );
  150. gradient_orientations.setPixel(x,y,bin);
  151. //TODO some error message, throwing an exception, whatever
  152. if (bin > number_Of_Bins)
  153. cerr << "Image_tools::calculateGradientOrientations bin " << bin << " > number_Of_Bins " << number_Of_Bins << "with angle " << angle << " and bin_width " << bin_width << endl;
  154. }
  155. }
  156. NICE::Image gradient_orientations_visual (grad_x_Image.width(), grad_x_Image.height());
  157. for (int y = 0; y < grad_x_Image.height(); y++)
  158. {
  159. for (int x = 0; x < grad_x_Image.width(); x++)
  160. {
  161. gradient_orientations_visual(x,y) = (int) floor(255 * ((double)gradient_orientations(x,y)/number_Of_Bins));
  162. }
  163. }
  164. // gradient_orientations_visual.writePGM("/home/luetz/foo.pgm");
  165. }
  166. /**
  167. * @brief Calculates Gradient-orientations
  168. * @author Alexander Lütz
  169. * @date 18/11/2010
  170. */
  171. void Image_tools::calculateGradientOrientations(const NICE::GrayImage16s & grad_x_Image, const NICE::GrayImage16s & grad_y_Image , const int & number_Of_Bins, NICE::Image & gradient_orientations, const bool unsignedBins)
  172. {
  173. gradient_orientations = NICE::Image(grad_x_Image.width(), grad_x_Image.height());
  174. double bin_width = 180.0/number_Of_Bins;
  175. if (!unsignedBins)
  176. bin_width *= 2.0;
  177. for (int y = 0; y < grad_x_Image.height(); y++)
  178. {
  179. for (int x = 0; x < grad_x_Image.width(); x++)
  180. {
  181. double angle = (atan2( (double)grad_x_Image.getPixel(x,y),(double)grad_y_Image.getPixel(x,y)) + M_PI)*180/M_PI;
  182. //NOTE It would be better, if we would subtract 1/2 binsize, but Anna Bosch hasn't done it in her original paper, so we won't do it as well
  183. // angle = abs (angle*180/M_PI -0.5*bin_width); //atan2 and - 1/2 bin
  184. while (angle >= 360.0)
  185. angle -= 360.0;
  186. if (unsignedBins)
  187. {
  188. while (angle>=180.0)
  189. angle -= 180.0;
  190. }
  191. //NOTE Update 2011-02-10: ceil is ok, if the indicees are from 1 to number_Of_Bins. Of course we do NOT want this, but instaed we deal with 0 to number_Of_Bins-1. Therefor floor is our choice!
  192. int bin = (int) floor(angle/bin_width );
  193. gradient_orientations.setPixel(x,y,bin);
  194. }
  195. }
  196. /*
  197. NICE::Image gradient_orientations_visual (grad_x_Image.width(), grad_x_Image.height());
  198. for (int y = 0; y < grad_x_Image.height(); y++)
  199. {
  200. for (int x = 0; x < grad_x_Image.width(); x++)
  201. {
  202. gradient_orientations_visual(x,y) = (int) floor(255 * ((double)gradient_orientations(x,y)/number_Of_Bins));
  203. }
  204. }
  205. gradient_orientations_visual.writePGM("/home/luetz/foo.pgm");*/
  206. // showImage(gradient_orientations_visual);
  207. }
  208. /**
  209. * @brief Calculates Gradient-magnitudes
  210. * @author Alexander Lütz
  211. * @date 18/11/2010
  212. */
  213. void Image_tools::calculateGradientMagnitudes(const NICE::ImageT<float> & grad_x_Image, const NICE::ImageT<float> & grad_y_Image, NICE::ImageT<float> & gradient_magnitudes)
  214. {
  215. //init
  216. gradient_magnitudes.resize(grad_x_Image.width(), grad_x_Image.height());
  217. gradient_magnitudes.set(0.0);
  218. for (int y = 0; y < grad_x_Image.height(); y++)
  219. for (int x = 0; x < grad_x_Image.width(); x++)
  220. {
  221. float magnitude = sqrt(pow(grad_x_Image.getPixel(x,y),2) + pow(grad_y_Image.getPixel(x,y),2));
  222. gradient_magnitudes.setPixel(x,y,magnitude);
  223. }
  224. // NICE::Image gradient_magnitudes_visual = NICE::Image(grad_x_Image.width(), grad_x_Image.height());
  225. // for (int y = 0; y < grad_x_Image.height(); y++)
  226. // {
  227. // for (int x = 0; x < grad_x_Image.width(); x++)
  228. // {
  229. // gradient_magnitudes_visual(x,y) = (int) floor( ((double)gradient_magnitudes(x,y)/sqrt(2)));
  230. // }
  231. // }
  232. // showImage(gradient_magnitudes_visual);
  233. }
  234. /**
  235. * @brief Normalized a descriptor Block, using L2-Norm, not implemented completely. Just have a look in the original paper of Dalal and Triggs for further details.
  236. * @author Alexander Lütz
  237. * @date 22/11/2010
  238. */
  239. std::vector<float> Image_tools::normalizeBlockDescriptor(const std::vector<float> & orig_Block_Descriptor, const float epsilon)
  240. {
  241. double sum_of_squares = pow(epsilon,2);
  242. for (std::vector<float>::const_iterator it = orig_Block_Descriptor.begin(); it != orig_Block_Descriptor.end(); it++)
  243. {
  244. sum_of_squares += pow((*it),2);
  245. }
  246. std::vector<float> normalized_Block_Descriptor;
  247. for (std::vector<float>::const_iterator it = orig_Block_Descriptor.begin(); it != orig_Block_Descriptor.end(); it++)
  248. {
  249. normalized_Block_Descriptor.push_back((*it)/sum_of_squares);
  250. }
  251. return normalized_Block_Descriptor;
  252. }
  253. /**
  254. * @brief calculates the resulting HoG-Features for an image by normalizing spatial blocks und storing the resulting normalized histograms in a vector - not implemented up to now
  255. * @author Alexander Lütz
  256. * @date 22/11/2010
  257. */
  258. std::vector< std::vector<float> > Image_tools::calculateResultingHogFeatures(const NICE::Image & gradient_orientations, const NICE::ImageT<float> & gradient_magnitudes, const int & blocksize, const int & cellsize)
  259. {
  260. std::vector< std::vector<float> > HoG_features;
  261. return HoG_features;
  262. }