#include "opencv2/opencv.hpp"

void adaptiveThresh(IplImage *src,IplImage *dst,unsigned int subs)
{
  CV_DbgAssert((src->width!=dst->width)||(src->height!=dst->height))

  CvSize sub_size=cvSize(src->width/subs,src->height/subs);
  CvMat *src_header=cvCreateMatHeader(sub_size.width,sub_size.height,CV_8UC1);
  CvMat *dst_header=cvCreateMatHeader(sub_size.width,sub_size.height,CV_8UC1);

  int hist_size[]={255},index=0;
  float ranges[]={0,255},*hist_ranges[]={ranges},deriv[hist_size[0]-1],deriv2[hist_size[0]-1],max=0;
  CvHistogram* hist=cvCreateHist(1,hist_size,CV_HIST_ARRAY,hist_ranges,1);

  for(int k=0;k<subs;k++,max=0,index=0)  
    for(int j=0;j<subs;j++,max=0,index=0)  
    {
    CvRect rect=cvRect(k*sub_size.width,j*sub_size.height,sub_size.width,sub_size.height);
    src_header=cvGetSubRect(src,src_header,rect);
    dst_header=cvGetSubRect(dst,dst_header,rect);

    cvCalcHist((IplImage**)&src_header,hist,0,0);

    for(int i=0;i<hist_size[0]-1;i++)
      deriv[i]=cvGetReal1D(hist->bins,i+1)-cvGetReal1D(hist->bins,i);

    for(int i=0;i<hist_size[0]-1;i++)
    {
      deriv2[i]=deriv[i+1]-deriv[i];
      if (deriv2[i]>max) 
      {
        max=deriv2[i];
        index=i;
      }
    }

    for(int i=0;i<dst_header->width*dst_header->height;i++)
      if (cvGet1D(src_header,i).val[0]>index) 
        cvSet1D(dst_header,i,cvScalar(255));
      else 
        cvSet1D(dst_header,i,cvScalar(0));
    }
  cvReleaseHist(&hist);
}

int main(int argc,char**argv)
{
  IplImage *img=cvLoadImage((argc>1?argv[1]:"lena.png"),CV_LOAD_IMAGE_GRAYSCALE);
  if (!img) return EXIT_FAILURE;

  IplImage *thresh=cvCloneImage(img); 

  for(int i=0;i<thresh->width*thresh->height;i++)
    if (cvGet1D(thresh,i).val[0]>100)
      cvSet1D(thresh,i,cvScalar(255));
    else
      cvSet1D(thresh,i,cvScalar(0));

  cvShowImage("1 pevny prah",thresh);

  cvSet(thresh,cvScalar(127));

  for(int i=0;i<thresh->width*thresh->height;i++)
  {
    uchar val=cvRound(cvGet1D(img,i).val[0]);
    if (val>150) 
      cvSet1D(thresh,i,cvScalar(255));
    else if (val<100) 
      cvSet1D(thresh,i,cvScalar(0));
  }

  cvShowImage("2 pevne prahy",thresh);

  adaptiveThresh(img,thresh,1);
  cvShowImage("Adaptivni pevny prah 1",thresh);

  adaptiveThresh(img,thresh,8);
  cvShowImage("Adaptivni pevny prah 8",thresh);
  cvWaitKey();

  cvReleaseImage(&img);cvReleaseImage(&thresh);
  cvDestroyAllWindows();
  return EXIT_SUCCESS;
}
