// VD_Core.h : main header file for the VD_Core DLL
//

#pragma once

#ifndef __AFXWIN_H__
	#error "include 'stdafx.h' before including this file for PCH"
#endif

#include "resource.h"		// main symbols
#include <cv.h>
#include <HighGUI.h>
#include <math.h>
#include "IniReader.h"
#include "IniWriter.h"
#include <list>
using namespace std;


#define IMAGE_WIDTH		352
#define IMAGE_HEIGHT	144
#define VIEW_WIDTH		704
#define VIEW_HEIGHT		288
#define RES_COEF		2	
#define BOX_WIDTH		4
#define BOX_HEIGHT		4
#define IMAGE_CHANNELS	3
#define BG_INIT			50
#define COUNTING_LINE	IMAGE_HEIGHT*3/5
#define NUMBER_OF_LANES	6
#define ABANDONED_CARS_LEVEL	1
#define LANE_OCCFIELD	500

#define CVCONTOUR_APPROX_LEVEL 2

#define CVCLOSE_ITR		1
//definitions for settings
#define CARCONTOURS		1
#define CARRECTS		1<<1
#define ROADCONTOURS	1<<2
#define ROADSIGNS		1<<3
#define SHADOWMASK		1<<4
#define PATH			1<<5
#define SPEED			1<<6
#define LENGTH			1<<7
#define SHADOWANAL		1<<8
#define LANES			1<<9

#define RELOADINI		1<<10
#define USELANES		1<<11
#define FIXEDLANES		1<<12

#define DAY_NIGHT_SEP	90

template<class T> class Image
{
  private:
  IplImage* imgp;
  public:
  Image(IplImage* img=0) {imgp=img;}
  ~Image(){imgp=0;}
  void operator=(IplImage* img) {imgp=img;}
  inline T* operator[](const int rowIndx) {
    return ((T *)(imgp->imageData + rowIndx*imgp->widthStep));}
};

typedef struct{
  unsigned char b,g,r;
} RgbPixel;

typedef struct{
  float b,g,r;
} RgbPixelFloat;

typedef struct{
	unsigned char h,s,v;
} HsvPixel;

typedef struct{
	float h,s,v;
} HsvPixelFloat;

typedef Image<RgbPixel>       RgbImage;
typedef Image<RgbPixelFloat>  RgbImageFloat;
typedef Image<unsigned char>  BwImage;
typedef Image<float>          BwImageFloat;
typedef Image<HsvPixel>	      HsvImage;
typedef Image<HsvPixelFloat>  HsvImageFloat;

class Light{
public:
	int x;
	int y;
	int area;
	double perim;
	int bestCand;
	int bestDev;
	CvRect borderRect;

public:
	Light() {
		bestCand = -1;
		bestDev = 1000;
	}
};

typedef struct CarLights{
	Light left;
	Light right;
	int deviation;
};

typedef struct Car {
	int x;
	int	y;
	int vx;
	int vy;
	list<CvPoint> path;
	int width;
	int height;
	int area;
	double length;
	double speed;
	bool counted;
	int lane;
	int abandoned;
	CvRect borderRect;
	CvRect prevRect;
	CvScalar color;
	CarLights carLights;
	bool predecessor;
	FILETIME firstTime;
	int duration;
	CvSeq* contour;
	bool compound;
};

typedef struct Lane {
	int index;
	double x1;
	double y1;
	double x2;
	double y2;
	double width;
	double conf;	//0-100%, on 0% the lane is deleted
	double count;
	double speed;
	double occupancy;
	double occfield[LANE_OCCFIELD];
	int occpointer;
	double length;
	double counting_line;
	double density;
};



struct Results{
	int vehCount;
	int carCount;
	int trCount;
	int actCount;
	int avgSpeed[NUMBER_OF_LANES];
	int density[NUMBER_OF_LANES];
	int flow[NUMBER_OF_LANES];
	CString LOS[NUMBER_OF_LANES];
	SYSTEMTIME time;
};

struct {
	double height;
	double ver_angle;	//radians
	double ver_angle_min;
	double air_dist;
	double road_dist;
	double angle_range_y;	//radians
	double angle_range_x;	//radians
	double pix_in_one_rad;
} cameraSettings;

void Clean();
void ImageLoad(char *FileName);

int algSettings=0;
double resCoef_x=2;
double resCoef_y=2;

IplImage *result;
IplImage *result_temp;
IplImage *result_temp2;
IplImage *result_temp3;
IplImage *result_temp4;
IplImage *result_hr;
IplImage *temp_rgb;
IplImage *temp_rgb2;
IplImage *temp_rgb3;
IplImage *temp;
IplImage *temp2;
IplImage *temp3;
IplImage *temp_32F;
IplImage *temp_32F2;
IplImage *temp_32F3;
IplImage *temp_16S;
IplImage *temp_16S2;
IplImage *temp_32S;
IplImage *temp_32S2;
IplImage *temp_rgb32F;
IplImage *tR;
IplImage *tG;
IplImage *tB;

IplImage *bg_gs;
IplImage *bg_rgb;
IplImage *bg_rgb_hr;
IplImage *bg_hsv;
IplImage *bg_hsv32F;

IplImage *bg_Avg;
IplImage *bg_Avg8U;
IplImage *bg_SD;
IplImage *bg_SD8U;
IplImage *bg_SDtemp;
IplImage *bg_SDR;
IplImage *bg_SDG;
IplImage *bg_SDB;
IplImage *cR;
IplImage *cG;
IplImage *cB;

IplImage *fg_mask;
IplImage *mask;

IplImage *image_proc;
IplImage *image_prev;
IplImage *image_rgb;
IplImage *image_rgb_hr;
IplImage *image_hsv;
IplImage *image_gs;
IplImage *image_ratio;
IplImage *shadow;
IplImage *shadow_std;
IplImage *shadow_stdf;

CvSize hrSize;

IplImage *road;
CvSeq* roadContours;
CvScalar roadColor;
IplImage *roadSigns;

IplImage *ForeEdges;
IplImage *BackEdges;
IplImage *ForeEdgesThr;
IplImage *BackEdgesThr;
IplImage *CEdges;
IplImage *CEdgesThr;
IplImage *staticEdges;
IplImage *movingEdges;
IplImage *smoothedEdges;

CvSeq* contoursIn = 0;
CvSeq* contoursSh = 0;
IplImage *carMask;
CvSeq* carContours = 0;

IplImage *maskTemp;
IplImage *maskIn;
IplImage *maskSt;
IplImage *rem;
IplImage *maskT;

int use_lanes;

CvMemStorage* mem_storage = NULL;
CvMemStorage* mem_storage_road = NULL;
CvMemStorage* mem_storageIn = NULL;
CvMemStorage* mem_storageSh = NULL;
CvMemStorage* mem_storageCars = NULL;

CArray<Lane> autoLanes;
CArray<Lane> fixedLanes;
CArray<Car> prevCars;
CArray<Car> actualCars;
CArray<Car> possCars;
CArray<Light> lights;
int vehCounter = 0;
double avgSpeed[NUMBER_OF_LANES];
double density[NUMBER_OF_LANES];
double flow[NUMBER_OF_LANES];
int carCounter = 0;
int truckCounter = 0;

FILETIME currentTime;
CString iniFile;

IplImage *shadowMask;
IplImage *shadowEdges;
CvScalar shadowInfl = cvScalar(0);
double shadowVector_x=0;
double shadowVector_y=0;

bool initialized;
int dayMode = false;

int bg_count = 0;
int obj_id;

int Cars_overall = 0;
int Cars_actual = 0;

IplImage *movementMap_x;
IplImage *movementMap_y;
IplImage *movementMap;

void Show(IplImage *im,char pos=1);

class CVD_CoreApp : public CWinApp
{
private:

public:
	CVD_CoreApp();

// Overrides
public:
	virtual BOOL InitInstance();

	DECLARE_MESSAGE_MAP()
public:
	virtual int ExitInstance();
};
