double dist_directional_swc_1_2(V3DLONG & nseg1, V3DLONG & nseg1big, double & sum1big, const NeuronTree *p1, const NeuronTree *p2)
{
	if (!p1 || !p2) return -1;
	V3DLONG p1sz = p1->listNeuron.size(), p2sz = p2->listNeuron.size();
	if (p1sz<2 || p2sz<2) return -1;

	NeuronSWC *tp1, *tp2;
	V3DLONG i, j;
	double sum1=0;
	nseg1=0;
	nseg1big=0;
	sum1big=0;

	QHash<int, int> h1 = generate_neuron_swc_hash(p1); //generate a hash lookup table from a neuron swc graph

	for (i=0;i<p1->listNeuron.size();i++)
	{
		//first find the two ends of a line seg
		tp1 = (NeuronSWC *)(&(p1->listNeuron.at(i)));
		if (tp1->pn < 0 || tp1->pn >= p1sz)
			continue;
		tp2 = (NeuronSWC *)(&(p1->listNeuron.at(h1.value(tp1->pn)))); //use hash table
		//qDebug() << "i="<< i << " pn="<<tp1->pn - 1;

		//now produce a series of points for the line seg
		double len=dist_L2(XYZ(tp1->x,tp1->y,tp1->z), XYZ(tp2->x,tp2->y,tp2->z));
		int N = int(1+len+0.5);
		XYZ ptdiff;
		if (N<=1)
		{
			qDebug() << "detect one very short segment, len=" << len;
			ptdiff = XYZ(0,0,0);
		}
		else
		{
			double N1=1.0/(N-1);
			ptdiff = XYZ(N1,N1,N1) * XYZ(tp2->x-tp1->x, tp2->y-tp1->y, tp2->z-tp1->z);
		}
		qDebug() << "N="<<N << "len=" <<len << "xd="<<ptdiff.x << " yd=" << ptdiff.y << " zd=" << ptdiff.z << " ";
		for (j=0;j<N;j++)
		{
			XYZ curpt(tp1->x + ptdiff.x*j, tp1->y + ptdiff.y*j, tp1->z + ptdiff.z*j);
			double cur_d = dist_pt_to_swc(curpt, p2);
			sum1 += cur_d;
			nseg1++;

			if (cur_d>=2)
			{
				sum1big += cur_d;
				nseg1big++;
			}

		}
	}
	qDebug() << "end directional neuronal distance computing";

	return sum1;
}
bool GenericObjectDetector::RunVOC()
{

	FileInfos imglist;
	db_man.Init(DB_VOC07);
	if( !db_man.GetImageList(imglist) )
		return false;

	for(size_t id=0; id<10; id++)
	{
		double start_t = getTickCount();

		img = imread(imglist[id].filepath);

		// preprocessing
		Preprocess(img);

		segmentor.DoSegmentation(img);
		const vector<visualsearch::SuperPixel>& sps = segmentor.superPixels;

		vector<ImgWin> det_wins;

		// loop all segment
		for (size_t sel_id=0; sel_id<sps.size(); sel_id++)
		{
			// test all window settings
			for(size_t win_id=0; win_id<winconfs.size(); win_id++)
			{
				// compute adjust range
				Point minpt, maxpt;
				if( !WinLocRange(sps[sel_id].box, winconfs[win_id], minpt, maxpt) )
					continue;

				Point curpt(sps[sel_id].box.x+sps[sel_id].box.width/2, sps[sel_id].box.y+sps[sel_id].box.height/2);
				double bestscore = 0;
				ImgWin bestWin;
				// do shifting
				for(int i=0; i<10; i++)
				{
					// generate locations
					vector<ImgWin> wins;
					SampleWinLocs(curpt, winconfs[win_id], minpt, maxpt, 6, wins);
					if(wins.empty())
						continue;

					for(size_t j=0; j<wins.size(); j++)
						wins[j].score = ComputeCenterSurroundMeanColorDiff(wins[j]);

					// sort
					sort(wins.begin(), wins.end());

					const ImgWin selWin = wins[wins.size()-1];
					//cout<<"Best score: "<<selWin.score<<endl;
					if(selWin.score > bestscore)
					{
						// shift to max point
						curpt.x = selWin.x + selWin.width/2;
						curpt.y = selWin.y + selWin.height/2;

						// update
						bestWin = selWin;
					}
				}

				det_wins.push_back(bestWin);
			}
		}

		sort(det_wins.begin(), det_wins.end());

		cout<<"Time for image "<<id<<": "<<(getTickCount()-start_t) / getTickFrequency()<<"s"<<endl;

		// visualize final results
		reverse(det_wins.begin(), det_wins.end());

		visualsearch::ImgVisualizer::DrawImgWins("final", img, det_wins);

		waitKey(0);
	}

	return true;
}
bool GenericObjectDetector::test()
{
	// test oversegmentation
	// get one image and depth map
	FileInfos imglist;
	db_man.Init(DB_VOC07);
	if( !db_man.GetImageList(imglist) )
		return false;
	map<string, vector<ImgWin>> gt_wins;
	db_man.LoadGTWins(imglist, gt_wins);
	img = imread(imglist[58].filepath);
	//db_man.GetDepthmapList(imglist);
	//db_man.LoadDepthData(imglist[0].filepath, depthMap);

	vector<ImgWin> wins;
	a9win.GenerateBlocks(img, wins);
	visualsearch::ImgVisualizer::DrawImgWins("detection", img, wins);

	WindowEvaluator wineval;
	vector<ImgWin> bestWins;
	wineval.FindBestWins(wins, gt_wins[imglist[58].filename], bestWins);
	visualsearch::ImgVisualizer::DrawImgWins("matches", img, bestWins);

	return true;

	// preprocessing
	Preprocess(img);

	segmentor.DoSegmentation(img);
	const vector<visualsearch::SuperPixel>& sps = segmentor.superPixels;

	int cnt = 10;
	while(cnt >= 0)
	{
		// select a segment
		srand(time(NULL));
		int sel_id = rand()%sps.size();
		vector<ImgWin> imgwins;
		// place window at center
		ImgWin curwin;
		curwin.x = sps[sel_id].box.x+sps[sel_id].box.width/2 - winconfs[0].width/2;
		curwin.y = sps[sel_id].box.y+sps[sel_id].box.height/2 - winconfs[0].height/2;
		curwin.width = winconfs[0].width;
		curwin.height = winconfs[0].height;
		imgwins.push_back(curwin);
		curwin = ImgWin(sps[sel_id].box.x, sps[sel_id].box.y, sps[sel_id].box.width, sps[sel_id].box.height);
		imgwins.push_back(curwin);
		visualsearch::ImgVisualizer::DrawImgWins("img", img, imgwins);
		visualsearch::ImgVisualizer::DrawImgWins("seg", segmentor.m_segImg, imgwins);
		visualsearch::ImgVisualizer::DrawImgWins("meancolor", segmentor.m_mean_img, imgwins);

		// compute adjust range
		Point minpt, maxpt;
		if( !WinLocRange(sps[sel_id].box, winconfs[0], minpt, maxpt) )
			continue;

		// check range
		//ImgWin minWin(minpt.x-winconfs[0].width/2, minpt.y-winconfs[0].height/2, winconfs[])

		Point curpt(sps[sel_id].box.x+sps[sel_id].box.width/2, sps[sel_id].box.y+sps[sel_id].box.height/2);
		double bestscore = 0;
		ImgWin bestWin;
		// do shifting
		for(int i=0; i<10; i++)
		{
			// generate locations
			vector<ImgWin> wins;
			SampleWinLocs(curpt, winconfs[0], minpt, maxpt, 6, wins);
			if(wins.empty())
				continue;

			for(size_t j=0; j<wins.size(); j++)
				wins[j].score = ComputeCenterSurroundMeanColorDiff(wins[j]);

			// sort
			sort(wins.begin(), wins.end());
			
			const ImgWin selWin = wins[wins.size()-1];
			cout<<"Best score: "<<selWin.score<<endl;
			if(selWin.score > bestscore)
			{
				// shift to max point
				curpt.x = selWin.x + selWin.width/2;
				curpt.y = selWin.y + selWin.height/2;

				// update
				bestWin = selWin;

				// visualize
				vector<ImgWin> imgwins2;
				ImgWin spwin = ImgWin(sps[sel_id].box.x, sps[sel_id].box.y, sps[sel_id].box.width, sps[sel_id].box.height);
				imgwins2.push_back(spwin);
				imgwins2.push_back(bestWin);
				visualsearch::ImgVisualizer::DrawImgWins("shift", img, imgwins2);
				cv::waitKey(0);
				cv::destroyWindow("shift");

				cout<<"Updated best score."<<endl;
			}

		}

		cnt--;
	}

	return true;
}