/**
 * \brief Radon Transform
 */
cv::Mat	radon(const char *filename, int width, int height) {
	// read the image
	cv::Mat	inimg = cv::imread(std::string(filename));
	//std::cout << "reading image " << filename << std::endl;

	// convert the image to grayscale
	cv::Mat ingray(inimg.rows, inimg.cols, CV_64FC1);
	cv::cvtColor(inimg, ingray, CV_BGR2GRAY);

	// now apply the windowing function (in place)
	cv::Point2d	center(inimg.cols / 2, inimg.rows / 2);
	double	r = min(center.x, center.y);
	for (int x = 0; x < inimg.cols; x++) {
		for (int y = 0; y < inimg.rows; y++) {
			double	l = hypot(x - center.x, y - center.y) / r;
			double	f = window2(l);
			unsigned char	v = ingray.at<unsigned char>(y, x);
			v = v * f;
			ingray.at<unsigned char>(y, x) = f * v;
		}
	}
	cv::imwrite(std::string("masked.jpg"), ingray);
	Grid	grid(ingray.cols, ingray.rows);

	// create a new image that will take the Radon transform
	cv::Mat	radon(width, height, CV_64FC1);

	// compute the radon transform
	double	anglestep = M_PI / height;
	double	srange = 2 * grid.maxS();
	double	sstep = srange / width;
	int	y = 0, x = 0;
	double	norm = hypot(width, height) / 1.5;
	for (double angle = 0; y < height; angle += anglestep, y++) {
		//std::cout << "y = " << y << std::endl;
		x = 0;
		for (double s = -srange / 2; x < width; x++, s += sstep) {
			GridRay	ray(grid, angle, s);
			GridIterator	i(ray);
			double	S = 0;
			try {
				//std::cout << "iterator over ray " << ray << std::endl;
#if 1
				for (i = ray.begin(); i != ray.end(); ++i) {
					S += i.weight * ingray.at<unsigned char>(i.y, i.x);
				}
#endif
			} catch (std::exception& x) {
				//std::cerr << "exception: " << x.what() << std::endl;
			}
			unsigned char	value = S / norm;
			radon.at<double>(y, x) = value;
			//std::cout << "[" << x << "," << y << "] = " << S / norm << std::endl;
		}
	}

	// return the result
	return radon;
}
//-----------------------------------------------------------------------------
void module(unsigned char *imagedata, int image_height, int image_width)
{
    int	i;
    unsigned char	(*cin)[size]=new unsigned char [size][size];
    double	(*fin)[Nray]=new double [Nview][Nray];
    //double	count=0,count2=0,count3=0,count4=0,count5=0;
    //double	sum=0,min=1.e10;
    for(i=0; i<1024; i++) {
        timage[i]=(COMPLEX *) calloc(1024,sizeof(COMPLEX));
    }
    for(i=0; i<512; i++) {
        inimage[i]=(COMPLEX *) calloc(512,sizeof(COMPLEX));
        image[i]=(COMPLEX *) calloc(512,sizeof(COMPLEX));
    }


    // 2000.10.11 - [email protected]
    for(i=0; i<size; i++)
        for(int j=0; j<size; j++)
            cin[i][j] = imagedata[i*image_width+j];


    radon(cin,fin,Nray,Nview);
    //dc=(dc)*(dc);	// 2001.01.31 - [email protected]

    feature(fin,vec,dvec);	// feature extraction

    for(i=0; i<1024; i++)
        free(timage[i]);
    for(i=0; i<512; i++) {
        free(inimage[i]);
        free(image[i]);
    }


    delete	[]	fin;
    delete	[]	cin;

    //////////////////////////////////////////////
    // quantization of features min max extract.//
    //////////////////////////////////////////////

    quantization();


}
int	main(int argc, char *argv[]) {
	int	c;
	int	width = 512;
	int	height = 512;
	double	scale = 1;
	bool	mask = false;

	while (EOF != (c = getopt(argc, argv, "w:h:m:M:s:")))
		switch (c) {
		case 'w':
			width = atoi(optarg);
			break;
		case 'h':
			height = atoi(optarg);
			break;
		case 'm':
			margin = atof(optarg);
			break;
		case 'M':
			mask = true;
			break;
		case 's':
			scale = atof(optarg);
			break;
		}	

	if ((argc - optind) != 2) {
		std::cerr << "need exactly two file name arguments" << std::endl;
		exit(EXIT_FAILURE);
	}

	const char	*infile = argv[optind++];
	const char	*outfile = argv[optind];

	// read the image
	cv::Mat	r = radon(infile, width, height, scale, mask);

	// write the result
	imwrite(std::string(outfile), r);
}