#include "zf_common_headfile.h"
#include "zf_common_debug.h"

#include "DOG_cv.h"

// ṹԪأ3x3
static uint8 kernel[3][3] = {
    {255, 255, 255},
    {255, 255, 255},
    {255, 255, 255}
};

// ֵ
uint8 threshold(struct DOG_CV* this, uint8 input[MT9V03X_H][MT9V03X_W]){
	int histogram[256] = {0}; // Ҷֱͼ
    int total_pixels = MT9V03X_W * MT9V03X_H;
    float sum = 0, sumB = 0;
    float wB = 0, wF = 0, max_var = 0;
    int threshold = 0;

    // ͳƻҶֱͼ
	for(int x = 0;x < MT9V03X_W;x++)
	{
		for(int y = 0;y < MT9V03X_H;y++)
		{
			histogram[input[y][x]]++;
		}
	}

    // ƽҶ
    for (int i = 0; i < 256; i++) {
        sum += i*histogram[i];
    }

    // 3. пֵܵT
    for (int T = 0; T < 256; T++) {
        wB += histogram[T];       // ۼ
        if (wB == 0) continue;

        wF = total_pixels - wB;   // ǰ
        if (wF == 0) break;

        sumB += T * histogram[T]; // Ҷܺ

        float mB = sumB / wB;            // ƽҶ
        float mF = (sum - sumB) / wF;    // ǰƽҶ
        float var = wB * wF * (mB - mF) * (mB - mF); // ䷽

        // 󷽲ֵ
        if (var > max_var) {
            max_var = var;
            threshold = T;
        }
    }
		
	for(int x = 0;x < MT9V03X_W;x++)
	{
		for(int y = 0;y < MT9V03X_H;y++)
		{
			if(input[y][x] >= threshold)
			{
				this -> image_OTSU[y][x] = 255;
			}
			else
			{
				this -> image_OTSU[y][x] = 0;
			}
		}
	}
}

// ͼѧ
void dilate(struct DOG_CV* this, uint8 input[MT9V03X_H][MT9V03X_W]){
	int i, j, m, n;
    int max_val = 0;

    for (i = 1; i < MT9V03X_H - 1; i++) 
	{
        for (j = 1; j < MT9V03X_W - 1; j++) 
		{
            max_val = 0;
            // ṹԪ
            for (m = -1; m <= 1; m++) 
			{
                for (n = -1; n <= 1; n++) 
				{
                    if (kernel[m + 1][n + 1] == 255 && input[i + m][j + n] == 255) 
					{
                        max_val = 255;
                        break;
                    }
                }
                if (max_val == 255) break;
            }
            this -> image_dilate[i][j] = max_val;
        }
    }
}

// ͼѧʴ
void erode(struct DOG_CV* this, uint8 input[MT9V03X_H][MT9V03X_W]){
	int i, j, m, n;
    int min_val;

    // ͼÿأԱ߽磩
    for (i = 1; i < MT9V03X_H - 1; i++)
	{
        for (j = 1; j < MT9V03X_W - 1; j++) 
		{
            min_val = 1; // ʼСֵ
            // ṹԪ
            for (m = -1; m <= 1; m++) 
			{
                for (n = -1; n <= 1; n++) 
				{
                    // ṹԪΪ1ͼжӦΪ0min_valΪ0
                    if (kernel[m + 1][n + 1] == 255 && input[i + m][j + n] == 0) 
					{
                        min_val = 0;
                        break;
                    }
                }
                if (min_val == 0) break; // Ѿҵ0ǰ˳
            }
            this -> image_erode[i][j] = min_val; // ͼֵ
        }
    }
}

// 캯
void cv(struct DOG_CV* this){
	memset(this -> image_OTSU, 0., sizeof(this -> image_OTSU));
	memset(this -> image_dilate, 0., sizeof(this -> image_dilate));
	memset(this -> image_erode, 0., sizeof(this -> image_erode));
	
	/* Ա */
	this -> threshold = threshold;
	this -> dilate = dilate;
	this -> erode = erode;
	
	/* ʼ */
	mt9v03x_init();
}

// 
void _cv(struct DOG_CV* this){
	memset(this -> image_OTSU, 0., sizeof(this -> image_OTSU));
	memset(this -> image_dilate, 0., sizeof(this -> image_dilate));
	memset(this -> image_erode, 0., sizeof(this -> image_erode));
}