void guiJointRealtimeO1BilateralFilterTest(Mat& src_, Mat& guide_)
{

	Mat src, guide;
	if (src_.channels() == 3)
	{
		//cvtColor(src_, guide, COLOR_BGR2GRAY);
		//cvtColor(src_, src, COLOR_BGR2GRAY);
		//src_.copyTo(src);
		guide = guide_;
		src = src_;
	}
	else
	{
		guide = guide_;
		src = src_;
	}

	Mat dest;

	string wname = "realtime O1 bilateral filter";
	namedWindow(wname);
	ConsoleImage ci;

	int a = 0; createTrackbar("a", wname, &a, 100);
	int sw = 0; createTrackbar("switch", wname, &sw, 5);

	//int r = 10; createTrackbar("r",wname,&r,200);
	int space = 100; createTrackbar("space", wname, &space, 2000);
	int color = 300; createTrackbar("color", wname, &color, 2550);
	int bin = 6; createTrackbar("bin", wname, &bin, 256);
	int iter = 3; createTrackbar("iter", wname, &iter, 100);
	int srsize = 4; createTrackbar("sresize", wname, &srsize, 32);
	int rsize = 1; createTrackbar("resize", wname, &rsize, 32);
	int upmethod = 1; createTrackbar("umethod", wname, &upmethod, 4);
	int type = 0; createTrackbar("type", wname, &type, 1);
	int mem = 0; createTrackbar("memory", wname, &mem, 1);
	int sscale = 10; createTrackbar("sscale", wname, &sscale, 100);
	namedWindow("diff");
	int scale = 10; createTrackbar("scale", "diff", &scale, 50);


	int key = 0;
	Mat show;

	RealtimeO1BilateralFilter rbf;
	Mat ref;
	Mat srcf; src.convertTo(srcf, CV_32F);
	//#define DEBUG_32F_RTBF 1
#ifdef DEBUG_32F_RTBF
	bilateralFilter(srcf, ref, cvRound(6.f*space / 10.f) * 2 + 1, color / 10.f, space / 10.0f, BORDER_REFLECT);
#else
	jointBilateralFilter(src, guide, ref, cvRound(3.f*space / 10.f) * 2 + 1, color / 10.f, space / 10.0f, BORDER_REFLECT);
#endif

	while (key != 'q')
	{
		src.convertTo(srcf, CV_32F, sscale / 10.0);
		if (type == 0) rbf.setBinDepth(CV_32F);
		else rbf.setBinDepth(CV_64F);

		if (mem == 0) rbf.isSaveMemory = false;
		else rbf.isSaveMemory = true;

		double tim;
		//cout<<"r="<<r<<": "<<"please change 'sw' for changing the type of implimentations."<<endl;
		float sigma_color = color / 10.f;
		float sigma_space = space / 10.f;
		int d = cvRound(sigma_space*3.f) * 2 + 1;
		rbf.upsampleMethod = upmethod;
		rbf.downsampleSizeBlurring = rsize;
		rbf.downsampleSizeSplatting = srsize;
		if (key == 'r')
		{

#ifdef DEBUG_32F_RTBF
			jointBilateralFilter(src, guide, ref, d, color / 10.f, space / 10.0f, BORDER_REFLECT);
#else
			jointBilateralFilter(src, guide, ref, d, color / 10.f, space / 10.0f, BORDER_REFLECT);
			//jointBilateralFilter(src, guide, ref, Size(d, d), color / 10.f, space / 10.0f, FILTER_CIRCLE, BORDER_REFLECT);
#endif
		}

		if (sw == 0)
		{
			CalcTime t("FIR SP", 0, false);

#ifdef DEBUG_32F_RTBF
			rbf.gaussFIR(srcf, guide, dest, d / 2, sigma_color, sigma_space, bin);
#else
			rbf.gauss_fir(src, guide, dest, d / 2, sigma_color, sigma_space, bin);
#endif
			tim = t.getTime();
		}
		if (sw == 1)
		{
			CalcTime t("IIR AM", 0, false);

#ifdef DEBUG_32F_RTBF
			rbf.gaussIIR(srcf, guide, dest, sigma_color, sigma_space, bin, RealtimeO1BilateralFilter::IIR_AM, iter);
#else
			rbf.gauss_iir(src, guide, dest, sigma_color, sigma_space, bin, RealtimeO1BilateralFilter::IIR_AM, iter);
#endif
			tim = t.getTime();
		}
		if (sw == 2)
		{
			CalcTime t("IIR SR", 0, false);

#ifdef DEBUG_32F_RTBF
			rbf.gaussIIR(srcf, guide, dest, sigma_color, sigma_space, bin, RealtimeO1BilateralFilter::IIR_SR, iter);
#else
			rbf.gauss_iir(src, guide, dest, sigma_color, sigma_space, bin, RealtimeO1BilateralFilter::IIR_SR, iter);
#endif
			tim = t.getTime();
		}
		if (sw == 3)
		{
			CalcTime t("IIR Deriche", 0, false);

#ifdef DEBUG_32F_RTBF
			rbf.gaussIIR(srcf, guide, dest, sigma_color, sigma_space, bin, RealtimeO1BilateralFilter::IIR_Deriche, iter);
#else
			rbf.gauss_iir(src, guide, dest, sigma_color, sigma_space, bin, RealtimeO1BilateralFilter::IIR_Deriche, iter);
#endif
			tim = t.getTime();
		}
		if (sw == 4)
		{
			CalcTime t("IIR YVY", 0, false);

#ifdef DEBUG_32F_RTBF
			rbf.gaussIIR(srcf, guide, dest, sigma_color, sigma_space, bin, RealtimeO1BilateralFilter::IIR_YVY, iter);
#else
			rbf.gauss_iir(src, guide, dest, sigma_color, sigma_space, bin, RealtimeO1BilateralFilter::IIR_YVY, iter);
#endif
			tim = t.getTime();
		}

		ci("d: %d", d);
		//ci("PSNR: %f", PSNRBB(dest, ref, 100, 100));
		ci("PSNR: %f", PSNR64F(dest, ref));
		ci("MSE:  %f", norm(dest, ref, NORM_L2SQR) / (double)dest.size().area());
		ci("time: %f", tim);
		ci.flush();
		alphaBlend(ref, dest, a / 100.0, show);

		if (key == 'p') rbf.showBinIndex();
		if (key == 't')guiMaxMinFilter(src);
		diffshow("diff", dest, ref, (float)scale);
		if (key == 'a')
		{
			guiAlphaBlend(ref, dest);
		}
		if (key == 'd')
		{
			guiAbsDiffCompareGE(ref, dest);
		}
#ifdef DEBUG_32F_RTBF
		Mat show8U;
		show.convertTo(show8U, CV_8U);
		imshow(wname, show8U);
#else
		imshow(wname, show);
#endif
		key = waitKey(1);
	}
	destroyAllWindows();
}
void guiSeparableBilateralFilterTest(Mat& src)
{
	Mat dest;

	string wname = "bilateral filter SP";
	namedWindow(wname);

	int a=0;createTrackbar("a",wname,&a,100);
	int sw = 0; createTrackbar("switch",wname,&sw, 6);
	//int r = 20; createTrackbar("r",wname,&r,200);
	int space = 300; createTrackbar("space",wname,&space,2000);
	int color = 500; createTrackbar("color",wname,&color,2550);
	int rate = 100; createTrackbar("color2 rate",wname,&rate,100);
	//int rate_s = 100; createTrackbar("space2 rate",wname,&rate_s,100);

	//int rate1 = 100; createTrackbar("c3 rate",wname,&rate1,100);
	//int rate2 = 100; createTrackbar("c4 rate",wname,&rate2,100);

	int s = 15; createTrackbar("ssim",wname,&s,200);
	int skip = 10; createTrackbar("skip",wname,&skip,40);

	Mat ref;
	{
		float sigma_color = color/10.f;
		float sigma_space = space/10.f;
		int r = cvRound(sigma_space*3.0)/2;
		int d = 2*r+1;
		bilateralFilter(src, ref, Size(d,d), sigma_color, sigma_space,FILTER_RECTANGLE);
	}
	ConsoleImage ci;

	Mat show;
	int key = 0;
	while(key!='q')
	{
		float sigma_color = color/10.f;
		float sigma_space = space/10.f;
		int r = cvRound(sigma_space*3.0)/2;
		int d = 2*r+1;

		double ssims = s/10.0;
		
		if(key=='r')
		{
			bilateralFilter(src, ref, Size(d,d), sigma_color, sigma_space,FILTER_RECTANGLE);
		}
		
		if(sw==0)
		{
			CalcTime t("bilateral filter: opencv");
			bilateralFilter(src, dest, Size(d,d), sigma_color, sigma_space,FILTER_RECTANGLE);
		}
		else if(sw==1)
		{
			CalcTime t("bilateral filter: opencv sp");
			bilateralFilter(src, dest, Size(d,d), sigma_color, sigma_space,FILTER_SEPARABLE);
		}
		else if(sw==2)
		{
			CalcTime t("bilateral filter: opencv sp HV");
			separableBilateralFilter(src, dest, Size(d,d), sigma_color, sigma_space,rate/100.0,DUAL_KERNEL_HV);
		}
		else if(sw==3)
		{
			CalcTime t("bilateral filter: opencv sp HVVH");
			separableBilateralFilter(src, dest, Size(d,d), sigma_color, sigma_space,rate/100.0,DUAL_KERNEL_HVVH);
		}
		else if(sw==4)
		{
			CalcTime t("bilateral filter: opencv sp HVVH");
			separableBilateralFilter(src, dest, Size(d,d), sigma_color, sigma_space,rate/100.0,DUAL_KERNEL_CROSS);
		}
		else if(sw==5)
		{
			CalcTime t("bilateral filter: opencv sp HVVH");
			separableBilateralFilter(src, dest, Size(d,d), sigma_color, sigma_space,rate/100.0,DUAL_KERNEL_CROSSCROSS);
		}
		else if(sw==6)
		{
			//CalcTime t("bilateral filter: opencv sp HVVH");
			//separableBilateralFilter(src, dest, Size(d,d), sigma_color, sigma_space,rate1/100.0,DUAL_KERNEL_CROSSCROSS);
		}

		if(key=='f')
		{
			a = (a==0) ? 100 : 0;
			setTrackbarPos("a",wname,a);
		}
		ci(format("%f dB",PSNR(ref,dest)));
		ci(format("%f dB",SSIM(ref,dest,ssims)));
//		ci(format("%f %f",getTV(dest),getTV(ref)));
		ci.flush();

		alphaBlend(ref, dest,a/100.0, show);
		imshow(wname,show);
		key = waitKey(1);
	}
}
void guiRealtimeO1BilateralFilterTest(Mat& src)
{
	Mat dest;

	string wname = "realtime O1 bilateral filter";
	namedWindow(wname);
	ConsoleImage ci;

	int a = 0; createTrackbar("a", wname, &a, 100);
	int sw = 2; createTrackbar("filter sw", wname, &sw, 5);

	int space = 100; createTrackbar("space", wname, &space, 2000);
	int color = 300; createTrackbar("color", wname, &color, 2550);
	int bin = 4; createTrackbar("bin", wname, &bin, 256);
	int iter = 3; createTrackbar("iter", wname, &iter, 100);
	int srsize = 1; createTrackbar("sresize", wname, &srsize, 32);
	int rsize = 1; createTrackbar("resize", wname, &rsize, 32);
	int upmethod = 1; createTrackbar("umethod", wname, &upmethod, 4);
	int type = 0; createTrackbar("type32_64", wname, &type, 1);
	int mem = 0; createTrackbar("memory", wname, &mem, 1);

	namedWindow("diff");
	int scale = 10; createTrackbar("scale", "diff", &scale, 50);

	int key = 0;
	Mat show;

	RealtimeO1BilateralFilter rbf;
	Mat ref;

	Mat srcf; src.convertTo(srcf, CV_32F);
	Mat ref2;
#define DEBUG_32F_RTBF 1
#ifdef DEBUG_32F_RTBF
	{
		//bilateralFilter(srcf, ref, cvRound(3.f*space / 10.f) * 2 + 1, color / 10.f, space / 10.0f, BORDER_REPLICATE);
		bilateralFilterL2(srcf, ref, cvRound(3.f*space / 10.f), color / 10.f, space / 10.0f, BORDER_REPLICATE);
		//cout << PSNR64F(ref2, ref) << endl;
		//cout << psnrRGBone(ref, ref) << endl;
	}
#else
	bilateralFilter(src, ref, cvRound(3.f*space / 10.f) * 2 + 1, color / 10.f, space / 10.0f, BORDER_REPLICATE);
#endif

	rbf.setColorNorm(RealtimeO1BilateralFilter::L2);
	while (key != 'q')
	{
		src.convertTo(srcf, CV_32F);
		if (type == 0) rbf.setBinDepth(CV_32F);
		else rbf.setBinDepth(CV_64F);

		if (mem == 0) rbf.isSaveMemory = false;
		else rbf.isSaveMemory = true;

		double tim;
		//cout<<"r="<<r<<": "<<"please change 'sw' for changing the type of implimentations."<<endl;
		float sigma_color = color / 10.f;
		float sigma_space = space / 10.f;
		int d = cvRound(sigma_space*3.f) * 2 + 1;
		rbf.upsampleMethod = upmethod;
		rbf.downsampleSizeBlurring = rsize;
		rbf.downsampleSizeSplatting = srsize;
		if (key == 'r')
		{

			CalcTime t("reftime");
#ifdef DEBUG_32F_RTBF
			//bilateralFilter(srcf, ref, d, color / 10.f, space / 10.0f, BORDER_REPLICATE);
			bilateralFilterL2(srcf, ref, cvRound(3.f*space / 10.f), color / 10.f, space / 10.0f, BORDER_REPLICATE);
#else
			//cp::bilateralFilter(src, ref, Size(d, d), sigma_color, sigma_space, FILTER_DEFAULT, BORDER_REPLICATE);		
			bilateralFilter(src, ref, d, color / 10.f, space / 10.0f, BORDER_REPLICATE);
#endif
		}
		if (sw == 0)
		{
			CalcTime t("FIR SP", 0, false);

#ifdef DEBUG_32F_RTBF
			rbf.gaussFIR(srcf, dest, d / 2, sigma_color, sigma_space, bin);
#else
			rbf.gauss_fir(src, dest, d / 2, sigma_color, sigma_space, bin);
#endif
			tim = t.getTime();
		}
		if (sw == 1)
		{
			CalcTime t("IIR AM", 0, false);

#ifdef DEBUG_32F_RTBF
			rbf.gaussIIR(srcf, dest, sigma_color, sigma_space, bin, RealtimeO1BilateralFilter::IIR_AM, iter);
#else
			rbf.gauss_iir(src, dest, sigma_color, sigma_space, bin, RealtimeO1BilateralFilter::IIR_AM, iter);
#endif
			tim = t.getTime();
		}
		if (sw == 2)
		{
			CalcTime t("IIR SR", 0, false);

#ifdef DEBUG_32F_RTBF
			rbf.gaussIIR(srcf, dest, sigma_color, sigma_space, bin, RealtimeO1BilateralFilter::IIR_SR, iter);
#else
			rbf.gauss_iir(src, dest, sigma_color, sigma_space, bin, RealtimeO1BilateralFilter::IIR_SR, iter);
#endif
			tim = t.getTime();
		}
		if (sw == 3)
		{
			CalcTime t("IIR Deriche", 0, false);

#ifdef DEBUG_32F_RTBF
			rbf.gaussIIR(srcf, dest, sigma_color, sigma_space, bin, RealtimeO1BilateralFilter::IIR_Deriche, iter);
#else
			rbf.gauss_iir(src, dest, sigma_color, sigma_space, bin, RealtimeO1BilateralFilter::IIR_Deriche, iter);
#endif
			tim = t.getTime();
		}
		if (sw == 4)
		{
			CalcTime t("IIR YVY", 0, false);

#ifdef DEBUG_32F_RTBF
			rbf.gaussIIR(srcf, dest, sigma_color, sigma_space, bin, RealtimeO1BilateralFilter::IIR_YVY, iter);
#else
			rbf.gauss_iir(src, dest, sigma_color, sigma_space, bin, RealtimeO1BilateralFilter::IIR_YVY, iter);
#endif
			tim = t.getTime();
		}

		ci("d: %d", d);
		//ci("PSNR: %f", PSNRBB(dest, ref, 100, 100));
		//ci("PSNR: %f", PSNR64F(dest, ref));
		
		ci("PSNR: %f", psnrRGBone(dest, ref));
		cout << psnrRGBone(dest, ref) << endl;
		//ci("MSE:  %f", norm(dest, ref, NORM_L2SQR) / (double)dest.size().area());
		ci("time: %f", tim);
		ci.flush();
		alphaBlend(ref, dest, a / 100.0, show);

		if (key == 'p') rbf.showBinIndex();
		if (key == 't')guiMaxMinFilter(src);
		diffshow("diff", dest, ref, (float)scale);
		if (key == 'a')
		{
			guiAlphaBlend(ref, dest);
		}
		if (key == 'd')
		{
			guiAbsDiffCompareGE(ref, dest);
		}

		if (key == 's')
		{
			cout << "write" << endl;
			showMatInfo(ref);
			imwrite("test.tiff", ref);
			imwrite("test.png", ref);
		}
#ifdef DEBUG_32F_RTBF
		Mat show8U;
		show.convertTo(show8U, CV_8U);
		imshow(wname, show8U);
#else
		imshow(wname, show);
#endif
		key = waitKey(1);
	}
	destroyAllWindows();
}