/InstaFilter/InstaFilter/tools/Histogram/Histogram.cpp

https://gitlab.com/Qbsuran_Alang/instafilter · C++ · 250 lines · 212 code · 25 blank · 13 comment · 53 complexity · 783be0c9af74591efb2d20741b13999b MD5 · raw file

  1. #include <Windows.h>
  2. #include <opencv/cv.h>
  3. #include <opencv/highgui.h>
  4. #include <tchar.h>
  5. #define SIZE 256
  6. #define COLORTYPE 12
  7. #define SCALE (255./360.)
  8. extern "C"
  9. {
  10. __declspec(dllexport)bool _stdcall HistogramProcess(LPWSTR csInputPath, LPWSTR csOutputPath);
  11. }//end extern "C"
  12. typedef struct
  13. {
  14. unsigned char lower;
  15. unsigned char upper;
  16. int index;
  17. } Color;
  18. double splitColor(const IplImage *src, const Color color);
  19. IplImage *convertImageRGBtoHSV(const IplImage *imageRGB);
  20. bool _stdcall HistogramProcess(LPWSTR csInputPath, LPWSTR csOutputPath)
  21. {
  22. char inputPath[SIZE] = "";
  23. WideCharToMultiByte(950, 0, csInputPath, -1, inputPath, SIZE, NULL, NULL);//wchar_t * to char
  24. char outputPath[SIZE] = "";
  25. WideCharToMultiByte(950, 0, csOutputPath, -1, outputPath, SIZE, NULL, NULL);//wchar_t * to char *
  26. //load image
  27. IplImage *img = cvLoadImage(inputPath, 1);
  28. if(!img)
  29. return false;
  30. else
  31. {
  32. IplImage *hsv = convertImageRGBtoHSV(img);
  33. IplImage *H = cvCreateImage(cvGetSize(hsv), 8, 1);
  34. cvSplit(hsv, H, 0, 0, 0);
  35. cvReleaseImage(&img);
  36. cvReleaseImage(&hsv);
  37. Color color[COLORTYPE] = {};
  38. double counter[COLORTYPE] = {};
  39. for(int i = 0, angle = 0 ; i < COLORTYPE ; i++, angle += 30)
  40. {
  41. if(i == 0)
  42. {
  43. color[i].lower = (angle+15) * SCALE;
  44. color[i].upper = (angle-15) * SCALE;
  45. color[i].index = i;
  46. }//end if
  47. else
  48. {
  49. color[i].lower = (angle-15) * SCALE;
  50. color[i].upper = (angle+15) * SCALE;
  51. color[i].index = i;
  52. }//end else
  53. double count = splitColor(H, color[i]);
  54. if(count == -1.0)
  55. {
  56. cvReleaseImage(&H);
  57. return false;
  58. }//end if
  59. else
  60. counter[i] = count;
  61. }//end for
  62. cvReleaseImage(&H);
  63. //§ä³Ì¤j­È©MÁ`©M
  64. double maxValue = -999.0, sum = 0.0;
  65. for(int i = 0 ; i < COLORTYPE ; i++)
  66. {
  67. maxValue = counter[i] > maxValue ? counter[i] : maxValue;
  68. sum += counter[i];
  69. }//end for
  70. //±N³Ì¤j­Èscale¨ì1¥ª¥k
  71. double scale = sum/maxValue;
  72. for(int i = 0 ; i < COLORTYPE ; i++)
  73. counter[i] = ((int)((scale * counter[i] * 100.0) + 0.5))/100.0;//¥|±Ë¤­¤J¨ì¤p¼ÆÂI¤T¦ì
  74. FILE *out = fopen(outputPath, "w+");
  75. if(!out)
  76. return false;
  77. for(int i = 0 ; i < COLORTYPE ; i++)
  78. fprintf(out, "%f ", counter[i]);
  79. fclose(out);
  80. return true;
  81. }//end else
  82. return false;
  83. }//end saveImage
  84. double splitColor(const IplImage *src, const Color color)
  85. {
  86. if(src->nChannels != 1)
  87. return -1.0;
  88. long long int counter = 0;
  89. for(int i = 0 ; i < src->height ; i++)
  90. for(int j = 0 ; j < src->widthStep ; j++)
  91. {
  92. int index = i * src->widthStep + j;
  93. unsigned char data = src->imageData[index];
  94. bool a;
  95. if(color.index == 0)
  96. {
  97. a = data > color.lower && data < color.upper;
  98. a = !a;
  99. }//end if
  100. else
  101. a = data >= color.lower && data <= color.upper;
  102. if(a)
  103. counter++;
  104. }//end for
  105. return (counter/((double)src->widthStep*src->height));
  106. }//end splitColor
  107. IplImage *convertImageRGBtoHSV(const IplImage *imageRGB)
  108. {
  109. float fR, fG, fB;
  110. float fH, fS, fV;
  111. const float FLOAT_TO_BYTE = 255.0f;
  112. const float BYTE_TO_FLOAT = 1.0f / FLOAT_TO_BYTE;
  113. // Create a blank HSV image
  114. IplImage *imageHSV = cvCreateImage(cvGetSize(imageRGB), 8, 3);
  115. if (!imageHSV || imageRGB->depth != 8 || imageRGB->nChannels != 3)
  116. return NULL;
  117. int h = imageRGB->height; // Pixel height.
  118. int w = imageRGB->width; // Pixel width.
  119. int rowSizeRGB = imageRGB->widthStep; // Size of row in bytes, including extra padding.
  120. char *imRGB = imageRGB->imageData; // Pointer to the start of the image pixels.
  121. int rowSizeHSV = imageHSV->widthStep; // Size of row in bytes, including extra padding.
  122. char *imHSV = imageHSV->imageData; // Pointer to the start of the image pixels.
  123. for (int y=0; y<h; y++) {
  124. for (int x=0; x<w; x++) {
  125. // Get the RGB pixel components. NOTE that OpenCV stores RGB pixels in B,G,R order.
  126. uchar *pRGB = (uchar*)(imRGB + y*rowSizeRGB + x*3);
  127. int bB = *(uchar*)(pRGB+0); // Blue component
  128. int bG = *(uchar*)(pRGB+1); // Green component
  129. int bR = *(uchar*)(pRGB+2); // Red component
  130. // Convert from 8-bit integers to floats.
  131. fR = bR * BYTE_TO_FLOAT;
  132. fG = bG * BYTE_TO_FLOAT;
  133. fB = bB * BYTE_TO_FLOAT;
  134. // Convert from RGB to HSV, using float ranges 0.0 to 1.0.
  135. float fDelta;
  136. float fMin, fMax;
  137. int iMax;
  138. // Get the min and max, but use integer comparisons for slight speedup.
  139. if (bB < bG) {
  140. if (bB < bR) {
  141. fMin = fB;
  142. if (bR > bG) {
  143. iMax = bR;
  144. fMax = fR;
  145. }
  146. else {
  147. iMax = bG;
  148. fMax = fG;
  149. }
  150. }
  151. else {
  152. fMin = fR;
  153. fMax = fG;
  154. iMax = bG;
  155. }
  156. }
  157. else {
  158. if (bG < bR) {
  159. fMin = fG;
  160. if (bB > bR) {
  161. fMax = fB;
  162. iMax = bB;
  163. }
  164. else {
  165. fMax = fR;
  166. iMax = bR;
  167. }
  168. }
  169. else {
  170. fMin = fR;
  171. fMax = fB;
  172. iMax = bB;
  173. }
  174. }
  175. fDelta = fMax - fMin;
  176. fV = fMax; // Value (Brightness).
  177. if (iMax != 0) { // Make sure it's not pure black.
  178. fS = fDelta / fMax; // Saturation.
  179. float ANGLE_TO_UNIT = 1.0f / (6.0f * fDelta); // Make the Hues between 0.0 to 1.0 instead of 6.0
  180. if (iMax == bR) { // between yellow and magenta.
  181. fH = (fG - fB) * ANGLE_TO_UNIT;
  182. }
  183. else if (iMax == bG) { // between cyan and yellow.
  184. fH = (2.0f/6.0f) + ( fB - fR ) * ANGLE_TO_UNIT;
  185. }
  186. else { // between magenta and cyan.
  187. fH = (4.0f/6.0f) + ( fR - fG ) * ANGLE_TO_UNIT;
  188. }
  189. // Wrap outlier Hues around the circle.
  190. if (fH < 0.0f)
  191. fH += 1.0f;
  192. if (fH >= 1.0f)
  193. fH -= 1.0f;
  194. }
  195. else {
  196. // color is pure Black.
  197. fS = 0;
  198. fH = 0; // undefined hue
  199. }
  200. // Convert from floats to 8-bit integers.
  201. int bH = (int)(0.5f + fH * 255.0f);
  202. int bS = (int)(0.5f + fS * 255.0f);
  203. int bV = (int)(0.5f + fV * 255.0f);
  204. // Clip the values to make sure it fits within the 8bits.
  205. if (bH > 255)
  206. bH = 255;
  207. if (bH < 0)
  208. bH = 0;
  209. if (bS > 255)
  210. bS = 255;
  211. if (bS < 0)
  212. bS = 0;
  213. if (bV > 255)
  214. bV = 255;
  215. if (bV < 0)
  216. bV = 0;
  217. // Set the HSV pixel components.
  218. uchar *pHSV = (uchar*)(imHSV + y*rowSizeHSV + x*3);
  219. *(pHSV+0) = bH; // H component
  220. *(pHSV+1) = bS; // S component
  221. *(pHSV+2) = bV; // V component
  222. }
  223. }
  224. return imageHSV;
  225. }