/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
- #include <Windows.h>
- #include <opencv/cv.h>
- #include <opencv/highgui.h>
- #include <tchar.h>
- #define SIZE 256
- #define COLORTYPE 12
- #define SCALE (255./360.)
-
- extern "C"
- {
- __declspec(dllexport)bool _stdcall HistogramProcess(LPWSTR csInputPath, LPWSTR csOutputPath);
- }//end extern "C"
-
- typedef struct
- {
- unsigned char lower;
- unsigned char upper;
- int index;
- } Color;
-
- double splitColor(const IplImage *src, const Color color);
- IplImage *convertImageRGBtoHSV(const IplImage *imageRGB);
-
- bool _stdcall HistogramProcess(LPWSTR csInputPath, LPWSTR csOutputPath)
- {
- char inputPath[SIZE] = "";
- WideCharToMultiByte(950, 0, csInputPath, -1, inputPath, SIZE, NULL, NULL);//wchar_t * to char
- char outputPath[SIZE] = "";
- WideCharToMultiByte(950, 0, csOutputPath, -1, outputPath, SIZE, NULL, NULL);//wchar_t * to char *
-
- //load image
- IplImage *img = cvLoadImage(inputPath, 1);
-
- if(!img)
- return false;
- else
- {
- IplImage *hsv = convertImageRGBtoHSV(img);
- IplImage *H = cvCreateImage(cvGetSize(hsv), 8, 1);
- cvSplit(hsv, H, 0, 0, 0);
- cvReleaseImage(&img);
- cvReleaseImage(&hsv);
-
- Color color[COLORTYPE] = {};
- double counter[COLORTYPE] = {};
-
- for(int i = 0, angle = 0 ; i < COLORTYPE ; i++, angle += 30)
- {
- if(i == 0)
- {
- color[i].lower = (angle+15) * SCALE;
- color[i].upper = (angle-15) * SCALE;
- color[i].index = i;
- }//end if
- else
- {
- color[i].lower = (angle-15) * SCALE;
- color[i].upper = (angle+15) * SCALE;
- color[i].index = i;
- }//end else
-
- double count = splitColor(H, color[i]);
- if(count == -1.0)
- {
- cvReleaseImage(&H);
- return false;
- }//end if
- else
- counter[i] = count;
- }//end for
- cvReleaseImage(&H);
-
- //§ä³Ì¤jÈ©MÁ`©M
- double maxValue = -999.0, sum = 0.0;
- for(int i = 0 ; i < COLORTYPE ; i++)
- {
- maxValue = counter[i] > maxValue ? counter[i] : maxValue;
- sum += counter[i];
- }//end for
-
- //±N³Ì¤jÈscale¨ì1¥ª¥k
- double scale = sum/maxValue;
- for(int i = 0 ; i < COLORTYPE ; i++)
- counter[i] = ((int)((scale * counter[i] * 100.0) + 0.5))/100.0;//¥|±Ë¤¤J¨ì¤p¼ÆÂI¤T¦ì
-
- FILE *out = fopen(outputPath, "w+");
- if(!out)
- return false;
-
- for(int i = 0 ; i < COLORTYPE ; i++)
- fprintf(out, "%f ", counter[i]);
- fclose(out);
-
- return true;
- }//end else
- return false;
- }//end saveImage
-
- double splitColor(const IplImage *src, const Color color)
- {
- if(src->nChannels != 1)
- return -1.0;
- long long int counter = 0;
-
- for(int i = 0 ; i < src->height ; i++)
- for(int j = 0 ; j < src->widthStep ; j++)
- {
- int index = i * src->widthStep + j;
- unsigned char data = src->imageData[index];
- bool a;
- if(color.index == 0)
- {
- a = data > color.lower && data < color.upper;
- a = !a;
- }//end if
- else
- a = data >= color.lower && data <= color.upper;
-
- if(a)
- counter++;
- }//end for
- return (counter/((double)src->widthStep*src->height));
- }//end splitColor
-
- IplImage *convertImageRGBtoHSV(const IplImage *imageRGB)
- {
- float fR, fG, fB;
- float fH, fS, fV;
- const float FLOAT_TO_BYTE = 255.0f;
- const float BYTE_TO_FLOAT = 1.0f / FLOAT_TO_BYTE;
-
- // Create a blank HSV image
- IplImage *imageHSV = cvCreateImage(cvGetSize(imageRGB), 8, 3);
- if (!imageHSV || imageRGB->depth != 8 || imageRGB->nChannels != 3)
- return NULL;
-
- int h = imageRGB->height; // Pixel height.
- int w = imageRGB->width; // Pixel width.
- int rowSizeRGB = imageRGB->widthStep; // Size of row in bytes, including extra padding.
- char *imRGB = imageRGB->imageData; // Pointer to the start of the image pixels.
- int rowSizeHSV = imageHSV->widthStep; // Size of row in bytes, including extra padding.
- char *imHSV = imageHSV->imageData; // Pointer to the start of the image pixels.
- for (int y=0; y<h; y++) {
- for (int x=0; x<w; x++) {
- // Get the RGB pixel components. NOTE that OpenCV stores RGB pixels in B,G,R order.
- uchar *pRGB = (uchar*)(imRGB + y*rowSizeRGB + x*3);
- int bB = *(uchar*)(pRGB+0); // Blue component
- int bG = *(uchar*)(pRGB+1); // Green component
- int bR = *(uchar*)(pRGB+2); // Red component
-
- // Convert from 8-bit integers to floats.
- fR = bR * BYTE_TO_FLOAT;
- fG = bG * BYTE_TO_FLOAT;
- fB = bB * BYTE_TO_FLOAT;
-
- // Convert from RGB to HSV, using float ranges 0.0 to 1.0.
- float fDelta;
- float fMin, fMax;
- int iMax;
- // Get the min and max, but use integer comparisons for slight speedup.
- if (bB < bG) {
- if (bB < bR) {
- fMin = fB;
- if (bR > bG) {
- iMax = bR;
- fMax = fR;
- }
- else {
- iMax = bG;
- fMax = fG;
- }
- }
- else {
- fMin = fR;
- fMax = fG;
- iMax = bG;
- }
- }
- else {
- if (bG < bR) {
- fMin = fG;
- if (bB > bR) {
- fMax = fB;
- iMax = bB;
- }
- else {
- fMax = fR;
- iMax = bR;
- }
- }
- else {
- fMin = fR;
- fMax = fB;
- iMax = bB;
- }
- }
- fDelta = fMax - fMin;
- fV = fMax; // Value (Brightness).
- if (iMax != 0) { // Make sure it's not pure black.
- fS = fDelta / fMax; // Saturation.
- float ANGLE_TO_UNIT = 1.0f / (6.0f * fDelta); // Make the Hues between 0.0 to 1.0 instead of 6.0
- if (iMax == bR) { // between yellow and magenta.
- fH = (fG - fB) * ANGLE_TO_UNIT;
- }
- else if (iMax == bG) { // between cyan and yellow.
- fH = (2.0f/6.0f) + ( fB - fR ) * ANGLE_TO_UNIT;
- }
- else { // between magenta and cyan.
- fH = (4.0f/6.0f) + ( fR - fG ) * ANGLE_TO_UNIT;
- }
- // Wrap outlier Hues around the circle.
- if (fH < 0.0f)
- fH += 1.0f;
- if (fH >= 1.0f)
- fH -= 1.0f;
- }
- else {
- // color is pure Black.
- fS = 0;
- fH = 0; // undefined hue
- }
-
- // Convert from floats to 8-bit integers.
- int bH = (int)(0.5f + fH * 255.0f);
- int bS = (int)(0.5f + fS * 255.0f);
- int bV = (int)(0.5f + fV * 255.0f);
-
- // Clip the values to make sure it fits within the 8bits.
- if (bH > 255)
- bH = 255;
- if (bH < 0)
- bH = 0;
- if (bS > 255)
- bS = 255;
- if (bS < 0)
- bS = 0;
- if (bV > 255)
- bV = 255;
- if (bV < 0)
- bV = 0;
-
- // Set the HSV pixel components.
- uchar *pHSV = (uchar*)(imHSV + y*rowSizeHSV + x*3);
- *(pHSV+0) = bH; // H component
- *(pHSV+1) = bS; // S component
- *(pHSV+2) = bV; // V component
- }
- }
- return imageHSV;
- }