#include "stdafx.h"
#include "cbr.h"
#include "img.h"
#include <ipl98/cpp/image.h>
#include <ipl98/cpp/algorithms/mask_operation.h>
#include <ipl98/cpp/algorithms/morphology.h>
#include <ostream>
#include <iostream>

/* Without the next line, an object must be declared like this: ipl::CImage Img; */
using namespace ipl;



int threshold=35;

CImage Ip::ComputeDiff(CImage* One, CImage* Two){

    CImage Out(10,10,8);
    Out=*One;
    
    for(unsigned int y=(*One).GetMinY();y<(*One).GetMaxY();y++){
           for(unsigned int x=(*One).GetMinX();x<(*One).GetMaxX();x++){
               if(abs((*One).GetPixel(x,y)-(*Two).GetPixel(x,y))<threshold){
                    Out.SetPixel(x,y,255);
        
               }else{
                    Out.SetPixel(x,y,0);
               }
           }
    }
    return Out;
}

void Ip::HistoEqImages(CImage* One, CImage* Two){   
    double count1=0;
    double count2=0;
    for(unsigned int yy=(*One).GetMinY();yy<(*One).GetMaxY();yy++)
    {
           for(unsigned int xx=(*One).GetMinX();xx<(*One).GetMaxX();xx++)
           {
                count1=(count1+(*One).GetPixel(xx,yy));
                count2=(count2+(*Two).GetPixel(xx,yy));
           }
    }
    double value1;
    double value2;
    value1=count1/(((*One).GetMaxY())*((*One).GetMaxX()));
    value2=count2/(((*One).GetMaxY())*((*One).GetMaxX()));
    int correct1=122-value1;
    int correct2=122-value2;

    for(unsigned int y=(*Two).GetMinY();y<(*Two).GetMaxY();y++)
    {
           for(unsigned int x=(*Two).GetMinX();x<(*Two).GetMaxX();x++)
           {
               if((((*Two).GetPixel(x,y))+correct2)>=255){
    
               }
               else if((((*Two).GetPixel(x,y))+correct2)<=0){
    
               }
               else{
                (*Two).SetPixel(x,y, (((*Two).GetPixel(x,y))+correct2));
               }
               
               if((((*One).GetPixel(x,y))+correct1)>=255){
    
               }
               else if((((*One).GetPixel(x,y))+correct1)<=0){

               }
               else{
                (*One).SetPixel(x,y, (((*One).GetPixel(x,y))+correct1));
               }

           }
    }
    
    count1=0;
    count2=0;
}

void Ip::FindingHistoVar(CImage* img1, CImage* img2, int* minP, int* maxP, double* avgP1, double* avgP2, double* changeP){
    //img1 is the reference image
    //img2 is the alarm image
    long double count1=0;
    long double count2=0;
    int maxtest = 0;
    int mintest = 10000;
    for(unsigned int y=(*img1).GetMinY();y<(*img1).GetMaxY();y++)
    {
           for(unsigned int x=(*img1).GetMinX();x<(*img1).GetMaxX();x++)
           {
              
               
            count1+=(*img1).GetPixel(x,y);     
            count2+=(*img2).GetPixel(x,y);
            
            if((*img2).GetPixel(x,y)>maxtest)
                maxtest=(*img2).GetPixel(x,y);
            
            if((*img2).GetPixel(x,y)<mintest)
                mintest=(*img2).GetPixel(x,y);


           }
    }
    *minP = mintest;
    *maxP = maxtest;

    *avgP1 = count1/(((*img1).GetMaxX()-(*img1).GetMinX())*((*img1).GetMaxY()-(*img1).GetMinY()));
    *avgP2 = count2/(((*img2).GetMaxX()-(*img2).GetMinX())*((*img2).GetMaxY()-(*img2).GetMinY()));

    *changeP = *avgP2-*avgP1;

} 

void Ip::CountNrOfObjects(CImage* Img, long* nrObjects, long* largestObject, double* avgObject){

    int objects[10000];
    int labels=0;
    CImage ImgOut = *Img;

    for(unsigned int yy=(*Img).GetMinY();yy<(*Img).GetMaxY();yy++){ // resetting output image... (skal ikke være nødvendig)
           for(unsigned int xx=(*Img).GetMinX();xx<(*Img).GetMaxX();xx++){
              
                ImgOut.SetPixel(xx,yy,0);
           }
    }

    int counter = 0;
    int test1 = 0;
    int test2 = 0;
    int test3 = 0;
    int test4 = 0;

    for(unsigned int y=(*Img).GetMinY()+1;y<((*Img).GetMaxY()-1);y++){
           for(unsigned int x=(*Img).GetMinX()+1;x<((*Img).GetMaxX()-1);x++){          
               if((*Img).GetPixel(x,y)==0){ //there is a black pixel
                   if(ImgOut.GetPixel(x-1,y)!=0 || ImgOut.GetPixel(x-1,y-1)!=0 || ImgOut.GetPixel(x,y-1)!=0 || ImgOut.GetPixel(x+1,y-1)!=0){ //there is a labeled connected object 
                       
                       if(ImgOut.GetPixel(x-1,y)!=0){
                           ImgOut.SetPixel(x,y,ImgOut.GetPixel(x-1,y));
                           test1=ImgOut.GetPixel(x-1,y);
        
                       }
                       if(ImgOut.GetPixel(x-1,y-1)!=0){
                           ImgOut.SetPixel(x,y,ImgOut.GetPixel(x-1,y-1));
                           test2=ImgOut.GetPixel(x-1,y-1);
        
                       }
                       if(ImgOut.GetPixel(x,y-1)!=0){
                           ImgOut.SetPixel(x,y,ImgOut.GetPixel(x,y-1));
                           test3=ImgOut.GetPixel(x,y-1);
        
                       }
                       if(ImgOut.GetPixel(x+1,y-1)!=0){
                           ImgOut.SetPixel(x,y,ImgOut.GetPixel(x+1,y-1));
                           test4=ImgOut.GetPixel(x+1,y-1);
        
                       }
                      
                       if(test1!=0){
                           if(test1!=test2 && test2!=0){
                               objects[counter]=test1;
                               counter++;
                               objects[counter]=test2;
                               counter++;
                           }
                           else if(test1!=test3 && test3!=0){
                               objects[counter]=test1;
                               counter++;
                               objects[counter]=test3;
                               counter++;
                           }
                           else if(test1!=test4 && test4!=0){
                               objects[counter]=test1;
                               counter++;
                               objects[counter]=test4;
                               counter++;
                           }
                       }
                       else if(test2!=0){
                           if(test2!=test3 && test3!=0){
                               objects[counter]=test2;
                               counter++;
                               objects[counter]=test3;
                               counter++;
                           }
                           else if(test2!=test4 && test4!=0){
                               objects[counter]=test2;
                               counter++;
                               objects[counter]=test4;
                               counter++;
                           }
                       }
                       else if(test3!=0 && test4!=0 && test3!=test4){

                            objects[counter]=test3;
                            counter++;
                            objects[counter]=test4;
                            counter++;
                       }
                       else{}
                       test1=0;
                       test2=0;
                       test3=0;
                       test4=0;
                    }else{
                    ImgOut.SetPixel(x,y,labels);
                    labels++;

                   }    
               }
           }
    }

    int dupl=0;

    for(unsigned int h=counter;h<-2;h=h-2){
        for(unsigned int yyy=(*Img).GetMinY();yyy<(*Img).GetMaxY();yyy++){
            for(unsigned int xxx=(*Img).GetMinX();xxx<(*Img).GetMaxX();xxx++){
                if(ImgOut.GetPixel(xxx,yyy)!=0){
                    if(ImgOut.GetPixel(xxx,yyy)==objects[h]){
                        ImgOut.SetPixel(xxx,yyy,objects[h+1]);
                    }
                }
            }
        }       
    }

    double max[10000];
    double largest[10000];
    int count=0;
    double tete=0;
    for(unsigned int yyyy=(*Img).GetMinY();yyyy<(*Img).GetMaxY();yyyy++)
    {
            for(unsigned int xxxx=(*Img).GetMinX();xxxx<(*Img).GetMaxX();xxxx++)
            {
               
                    if(ImgOut.GetPixel(xxxx,yyyy)>0){
                        for(unsigned int o=0;o<count;o++){
                            if(ImgOut.GetPixel(xxxx,yyyy)==max[o]){
                                tete=1;
                            
                                largest[o]=largest[o]+1;
                            }
                        }
                        if(tete==0){
                            max[count]=(ImgOut.GetPixel(xxxx,yyyy));
                            largest[count]=1;
                            count++;
                            
                        }
                        else{
                            tete=0;
                        }
                    }

            }   
    }
    
    *largestObject=0;
    *avgObject=0;
    int acum = 0;
    for(unsigned int j=0;j<count;j++){
        acum = acum + largest[j];
        if(largest[j]>*largestObject){
            *largestObject=largest[j];
        }
    }


    *nrObjects = count;
    if((*nrObjects==0)){*nrObjects=1;}
    *avgObject = (acum)/(*nrObjects);

}


CImage Ip::ConvertRGBtoGray(CImage* One, int* sizex, int* sizey){

    CImage Out(*sizex,*sizey,8);
        
    for(unsigned int x=(*One).GetMinX();x<(*sizex);x++)
    {
           for(unsigned int y=(*One).GetMinY();y<(*sizey);y++)
           {              
              
               Out.SetPixel(x,y,((0.299*(short)(*One).GetRedComponent(x,y))+(0.587*(short)(*One).GetGreenComponent(x,y))+(0.114*(short)(*One).GetBlueComponent(x,y))  ));
           }
    }

    return Out;
}

void Ip::InitializeStart(){ // skal bruke bilder fra TrollEye som input
    CImage Img1(10,10,24); // image with 24 b/p
    CImage Img2(10,10,24); // image with 24 b/p


    CImage ImgMask(5,5,1);
    ImgMask.Flush(1);
    CMorphology morph;

    Img1.Load("test2/ref.bmp"); // reference image
    Img2.Load("test2/alarm.bmp"); // camera alarm_or_not image

    int maxX1 = Img1.GetMaxX();
    int maxY1 = Img1.GetMaxY();
    int maxX2 = Img2.GetMaxX();
    int maxY2 = Img2.GetMaxY();
//  Img1.Save("loggimg/1.bmp");
//  Img2.Save("loggimg/12.bmp");
    CImage Gray1 = Ip::ConvertRGBtoGray(&Img1, &maxX1 , &maxY1); 
    CImage Gray2 = Ip::ConvertRGBtoGray(&Img2, &maxX2 , &maxY2);

//  Gray1.Save("loggimg/13.bmp");
//  Gray2.Save("loggimg/14.bmp");
    CMaskOperation().MedianFilterFourConnected3x3(Gray2);
    CMaskOperation().MedianFilterDiagonalConnected3x3(Gray2);
    Ip::HistoEqImages(&Gray1, &Gray2);
//  Gray1.Save("loggimg/13histo.bmp");
//  Gray2.Save("loggimg/14histo.bmp");

    CMaskOperation().MedianFilterFourConnected3x3(Gray1);
    CMaskOperation().MedianFilterDiagonalConnected3x3(Gray1);
//  Gray1.Save("loggimg/13med.bmp");
//  Gray2.Save("loggimg/14med.bmp");
    CImage Test = Ip::ComputeDiff(&Gray1, &Gray2);
//  Test.Save("loggimg/15.bmp");
    CMaskOperation().MedianFilterDiagonalConnected3x3(Test);
    CMaskOperation().MedianFilterFourConnected3x3(Test);
    CMaskOperation().MedianFilterDiagonalConnected3x3(Test);
    CMaskOperation().MedianFilterFourConnected3x3(Test);
    CMaskOperation().MedianFilterDiagonalConnected3x3(Test);
    CMaskOperation().MedianFilterFourConnected3x3(Test);
    
//  Test.Save("loggimg/16.bmp");
//  Test.Save("output.bmp");
    

    morph.Erode(ImgMask, Test);
//  Test.Save("loggimg/18.bmp");
    morph.Erode(ImgMask, Test);
//  Test.Save("loggimg/19.bmp");
//  Test.Save("loggimg/20.bmp");
//  Test.Save("loggimg/21.bmp");
    morph.Dilate(ImgMask, Test);
//  Test.Save("loggimg/22.bmp");
    morph.Dilate(ImgMask, Test);
//  Test.Save("loggimg/23.bmp");
    
    int min = 0, max = 0;
    double avg1 = 0, avg2 = 0, change = 0;
    Ip::FindingHistoVar(&Gray1, &Gray2, &min, &max, &avg1, &avg2, &change);

    long nrO;
    long largestO;
    double avgO;
    Ip::CountNrOfObjects(&Test, &nrO, &largestO, &avgO);

    struct Cbr::a_case thecase;
    thecase.nr_of_objects = nrO;
    thecase.largest_object = largestO;
    thecase.avg_object = avgO;
    thecase.alarm_situation = 0;
    thecase.avg_intensity = avg2;
    thecase.change_intensity = change;
   
    Cbr cb;
    cb.Retrieve(thecase);

}


void main(){
    Ip test;
    test.InitializeStart();  
}