// Color Filter Program:
// Use freely for Research,Educational and Industrial Purposes
// Programmed by Arturo Deza

// 2 Main OpenCV libraries
#include "cv.h"
#include "highgui.h"

// Adding these libraries always comes in handy
#include <math.h>
#include <iostream>
#include <fstream>
#include <ctime>
#include <cstdlib>

using namespace std;

// Separate Color in Images with Thresholds
void separate_clusters(IplImage Main,int R1, int R2, int G1, int G2,int B1, int B2, IplImage Main_R, IplImage Main_G, IplImage Main_B);

// Main function
int main(int argc,  char* argv[])
{
srand((unsigned)time(NULL));

IplImage *frame=cvLoadImage(argv[1]);

// Init Red, Blue and Green IplImages
IplImage *frame_Red=cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,1);
IplImage *frame_Green=cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,1);
IplImage *frame_Blue=cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,1);

separate_clusters(*frame,150,250,50, 150,150, 250,*frame_Red,*frame_Green,*frame_Blue);

// Set Windows
cvNamedWindow("frame",CV_WINDOW_AUTOSIZE);
cvNamedWindow("frame_Red",CV_WINDOW_AUTOSIZE);
cvNamedWindow("frame_Green",CV_WINDOW_AUTOSIZE);
cvNamedWindow("frame_Blue",CV_WINDOW_AUTOSIZE);

// Show Images
cvShowImage("frame",frame);
cvShowImage("frame_Red",frame_Red);
cvShowImage("frame_Green",frame_Green);
cvShowImage("frame_Blue",frame_Blue);

cvWaitKey(0);

// Release Memory
cvReleaseImage(&frame);
cvReleaseImage(&frame_Red);
cvReleaseImage(&frame_Green);
cvReleaseImage(&frame_Blue);

// Destroy Windows
cvDestroyWindow("frame");
cvDestroyWindow("frame_Red");
cvDestroyWindow("frame_Green");
cvDestroyWindow("frame_Blue");
}

// This function separates the image in its three R,G,B channels and shows 3 new images as output for each channel, if it meets the upper 
// and lower Threshold requirements.
void separate_clusters(IplImage Main,int R1, int R2, int G1, int G2,int B1, int B2, IplImage Main_R, IplImage Main_G, IplImage Main_B)
{
// Main : Input Image
// R1 : Lower Red Threshold
// R2 : Upper Red Threshold
// G1 : Lower Green Threshold
// G2 : Upper Green Threshold
// B1 : Lower Blue Threshold
// B2 : Upper Blue Threshold
// Main_R : Red Channel Output Image
// Main_G : Green Channel Output Image
// Main_B : Blue Channel Output Image

int height=Main.height;
int width=Main.width;
int step=Main.widthStep;
int channel=Main.nChannels;
uchar *data;
data=(uchar *)Main.imageData;

int step_Red=Main_R.widthStep;
int step_Green=Main_G.widthStep;
int step_Blue=Main_B.widthStep;

int channel_Red=Main_R.nChannels;
int channel_Green=Main_G.nChannels;
int channel_Blue=Main_B.nChannels;


uchar *data_Red,*data_Green,*data_Blue;
data_Red=(uchar *)Main_R.imageData;
data_Green=(uchar *)Main_G.imageData;
data_Blue=(uchar *)Main_B.imageData;

//Blue Channel
for (int i=0;i<height;i++)
	{for(int j=0; j<width; j++)
		{if((data[i*step+j*channel]>=B1)&&(data[i*step+j*channel]<=B2))
			{data_Blue[i*step_Blue+j*channel_Blue]=255;
			}
		else
			{data_Blue[i*step_Blue+j*channel_Blue]=0;
			}
		}	
	}

//Green Channel
for (int i=0;i<height;i++)
	{for(int j=0; j<width; j++)
		{if((data[i*step+j*channel+1]>=G1)&&(data[i*step+j*channel+1]<=G2))
			{data_Green[i*step_Green+j*channel_Green]=255;
			}
		else
			{data_Green[i*step_Green+j*channel_Green]=0;
			}
		}	
	}

//Red Channel
for (int i=0;i<height;i++)
	{for(int j=0; j<width; j++)
		{if((data[i*step+j*channel+2]>=R1)&&(data[i*step+j*channel+2]<=R2))
			{data_Red[i*step_Red+j*channel_Red]=255;
			}
		else
			{data_Red[i*step_Red+j*channel_Red]=0;
			}
		}	
	}

}
