Ejemplo n.º 1
0
void PathEvaluator::test_filtering()
{
	/// Export results:
	QString sessionName = QString("session_%1").arg(QDateTime::currentDateTime().toString("dd.MM.yyyy_hh.mm.ss"));
	QString path = "results/" + sessionName;
	QDir d("");	d.mkpath( path ); d.mkpath( path + "/images" );

	int timeLimit = 5000; // ms
	int numInBetweens = 8;
	int numSamplesPerPath = numInBetweens * 3;

	/// Get number of paths to evaluate:
	int numPaths = 0;
	{
		Scheduler defaultSchedule( *b->m_scheduler );

		// Find time it takes for a single path
		QElapsedTimer timer; timer.start();
		{
			defaultSchedule.setSchedule( b->m_scheduler->getSchedule() ); // default
			defaultSchedule.timeStep = 1.0 / numSamplesPerPath;
			defaultSchedule.executeAll();
		}

		// FIXME
		// numPaths = qMax(1.0, double(timeLimit) / timer.elapsed() * omp_get_num_threads());
		numPaths = qMax(1.0, double(timeLimit) / timer.elapsed() * 4);

		// Export source and target images
		QColor inputColor(255,255,255);
		b->renderer->quickRender(defaultSchedule.allGraphs.front(), inputColor).save(path + "/images/source.png");
		b->renderer->quickRender(defaultSchedule.allGraphs.back(), inputColor).save(path + "/images/target.png");
	}

	// Force number of paths
	numPaths = 30;

	// Do this once for input graphs
	QVector<Structure::Graph*> inputGraphs;
	inputGraphs << b->s->inputGraphs[0]->g << b->s->inputGraphs[1]->g;

	ScorerManager r_manager(b->m_gcorr, b->m_scheduler.data(), inputGraphs);
	r_manager.parseConstraintPair();
	r_manager.parseConstraintGroup();
	r_manager.parseGlobalReflectionSymm();

	QVector<ScorerManager::PathScore> ps( numPaths );
	MatrixXd allRanges( numPaths, 3 * 4 );

	QVector<ScheduleType> allPaths = b->m_scheduler->manyRandomSchedules( numPaths );

	QElapsedTimer evalTimer; evalTimer.start();

	//#pragma omp parallel for
	for(int i = 0; i < allPaths.size(); i++)
	{
		// Setup schedule
		Scheduler s( *b->m_scheduler );
		s.setSchedule( allPaths[i] );
		s.timeStep = 1.0 / numSamplesPerPath;

		// Execute blend
		s.executeAll();

		// Compute its score
		ps[i] = r_manager.pathScore( s.allGraphs );

		QVector<QColor> colors;
		colors.push_back(QColor(255,0,0));
		colors.push_back(QColor(0,255,0));
		colors.push_back(QColor(0,0,255));

		// Range of values
		MatrixXd ranges = ps[i].computeRange();

		allRanges.row(i) = VectorXd::Map(ranges.data(), ranges.rows()*ranges.cols());

		//#pragma omp critical
		{
			QImage img(QSize(600,130), QImage::Format_ARGB32);
			img.fill(qRgba(0,0,0,0));

			QPainter painter(&img);
			painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);

			// Text option
			QFont font("Monospace",8);
			font.setStyleHint(QFont::TypeWriter);
			painter.setFont(font);

			QVector<Structure::Graph*> inBetweens = s.topoVaryingInBetweens( numInBetweens );

			QVector< QVector<double> > scores(numInBetweens);

			int imgWidth = 0;

			for(int k = 0; k < numInBetweens; k++)
			{
				inBetweens[k]->moveCenterTo( AlphaBlend(inBetweens[k]->property["t"].toDouble(), 
					inBetweens[k]->property["sourceGraphCenter"].value<Vector3>(), 
					inBetweens[k]->property["targetGraphCenter"].value<Vector3>()), true);

				// Draw images
				QImage inBetween = b->renderer->quickRender(inBetweens[k], Qt::white);
				imgWidth = inBetween.width();

				// Rendered shape
				int newWidth = inBetween.width() * 0.5;
				int startX = k * newWidth;
				painter.drawImage(startX, 0, inBetween);

				// Store scores
				int idx = inBetweens[k]->property["graphIndex"].toInt();
				QVector<double> vals;
				vals << ps[i].connectivity[idx] << ps[i].localSymmetry[idx] << ps[i].globalSymmetry[idx];

				scores[k] = vals;
			}
			
			// Draw score lines
			for(int u = 0; u < scores.front().size(); u++)
			{
				// Graph
				QPainterPath poly;
				int padding = 0;

				QColor clr = colors[u];
				painter.setPen(QPen(clr, 1));

				// Render path
				for(int k = 0; k < numInBetweens; k++)
				{
					// Score graph
					//double minVal = ranges(u,0);
					//double range = ranges(u,2);

					//double val = (scores[k][u] - minVal) / range;
					double val = scores[k][u];

					// Graph line
					int newWidth = imgWidth * 0.5;
					int startX = k * newWidth;
					int x = startX + newWidth;
					int y = padding + (img.height() - (img.height() * val));

					if(k == 0)
						poly.moveTo(x, y);
					else
						poly.lineTo(x, y);

					// Dots
					painter.drawEllipse(QPoint(x,y), 2, 2);
				}

				painter.setBrush(Qt::NoBrush);
				painter.drawPath(poly);
			}

			// Draw ranges
			QStringList vals;
			for(int r = 0; r < 3; r++){
				QStringList curVals;
				for(int c = 0; c < 4; c++)
					curVals << QString::number(ranges(r,c),'f',2);
				vals << curVals.join("  ");
			}

			if( false )
			{
				painter.setPen(Qt::white);
				painter.drawText(11, img.height() - 9, vals.join("   #   "));

				painter.setPen(Qt::black);
				painter.drawText(10, img.height() - 10, vals.join("   #   "));
			}

			img.save( path + QString("/images/%1.png").arg(i) );
		}
	}

	// Get global average for the measures
	Vector3d globalAvg (allRanges.col(9).mean(), allRanges.col(10).mean(), allRanges.col(11).mean());

	// Sort based on score
	QMap<int,double> scoreMap;
	for(int i = 0; i < numPaths; i++) scoreMap[i] = ps[i].score();

	QVector<int> sortedIndices;
	typedef QPair<double,int> ValIdx;
	foreach(ValIdx d, sortQMapByValue( scoreMap )){
		sortedIndices.push_back( d.second );
	}
Ejemplo n.º 2
0
Paths CorrespondenceGenerator::generate()
{
	Paths result;

	auto boxA = a->bbox(), boxB = b->bbox();

	QStringList nodesA, nodesB;
	for (auto n : a->nodes) nodesA << n->id;
	for (auto n : b->nodes) nodesB << n->id;
	for (auto g : a->groups) for (auto nid : g) nodesA.removeAll(nid);
	for (auto g : b->groups) for (auto nid : g) nodesB.removeAll(nid);
	Structure::NodeGroups tmpA, tmpB;
	for (auto nid : nodesA) tmpA.push_back( QVector<QString>() << nid );
	for (auto nid : nodesB) tmpB.push_back( QVector<QString>() << nid );
	for (auto g : a->groups) tmpA.push_back(g);
	for (auto g : b->groups) tmpB.push_back(g);
	a->groups = tmpA;
	b->groups = tmpB;

	/// Build similarity matrix of groups:
	Eigen::MatrixXd similiarity = Eigen::MatrixXd::Ones(a->groups.size(), b->groups.size() + 1);

	for (size_t i = 0; i < similiarity.rows(); i++){
		double minVal = DBL_MAX;
		for (size_t j = 0; j < similiarity.cols(); j++){
			double val = 0;

			if (j < b->groups.size())
			{
				Eigen::AlignedBox3d groupBoxA, groupBoxB;
				for (auto sid : a->groups[i]) groupBoxA.extend(a->getNode(sid)->bbox(1.01));
				for (auto sid : b->groups[j]) groupBoxB.extend(b->getNode(sid)->bbox(1.01));

				Vector3 relativeCenterA = (groupBoxA.center() - boxA.min()).array() / boxA.sizes().array();
				Vector3 relativeCenterB = (groupBoxB.center() - boxB.min()).array() / boxB.sizes().array();

				val = (relativeCenterA - relativeCenterB).norm();

				minVal = std::min(minVal, val);
			}

			similiarity(i, j) = val;
		}
		double maxVal = similiarity.row(i).maxCoeff();
		if (maxVal == 0) maxVal = 1.0;

		for (size_t j = 0; j < b->groups.size(); j++)
			similiarity(i, j) = (similiarity(i, j) - minVal) / maxVal;
	}

	std::vector< std::vector<float> > data;
	for (int i = 0; i < similiarity.rows(); i++){
		std::vector<float> dataRow;
		for (int j = 0; j < similiarity.cols(); j++)
			dataRow.push_back(similiarity(i, j));
		data.push_back(dataRow);
	}
	//if (false) showTableColorMap(data, true); // DEBUG

	// Parameters:
	double similarity_threshold = 0.4;

	if (similiarity.rows() < 4) similarity_threshold = 1.0;

	// Collect good candidates
	Assignments candidates;
	for (size_t i = 0; i < similiarity.rows(); i++){
		QVector<size_t> candidate;
		for (size_t j = 0; j < similiarity.cols(); j++){
			if (similiarity(i, j) < similarity_threshold)
				candidate << j;
		}
		candidates << candidate;
	}

	int count_threshold = 1;

	Assignments assignments;
	if (candidates.size() > 7)
	{
		debugBox(QString("%1 candidates. Too complex (lower similairty?)").arg(candidates.size()));

		similarity_threshold = 0.1;

		Assignments candidates;
		for (size_t i = 0; i < similiarity.rows(); i++){
			QVector<size_t> candidate;
			for (size_t j = 0; j < similiarity.cols(); j++){
				if (similiarity(i, j) < similarity_threshold)
					candidate << j;
			}
			candidates << candidate;
		}

		cart_product(assignments, candidates, 10000);
		count_threshold = 12;
	}
	else
	{
		cart_product(assignments, candidates);
	}

	// Filter assignments
	Assignments filtered;
	for (auto & a : assignments)
	{
		QMap<size_t, size_t> counts;
		bool accept = true;
		auto NOTHING_SEGMENT = similiarity.cols() - 1;

		for (auto i : a) counts[i]++;
		for (auto k : counts.keys())
		{
			if (k != NOTHING_SEGMENT && counts[k] > count_threshold){
				accept = false;
				break;
			}
		}

		if (accept) filtered << a;
	}

	for (auto & assignment : filtered)
	{
		QVector < QStringList > landmarksA, landmarksB;

		for (size_t i = 0; i < assignment.size(); i++)
		{
			if (assignment[i] == b->groups.size()) continue;

			auto grpA = a->groups[i];
			auto grpB = b->groups[assignment[i]];

			// Resolve many-to-many
			if (grpA.size() > 1 && grpB.size() > 1)
			{
				QVector<QString> tmpA, tmpB;

				Eigen::AlignedBox3d groupBoxA, groupBoxB;
				for (auto sid : grpA) groupBoxA.extend(a->getNode(sid)->bbox(1.01));
				for (auto sid : grpB) groupBoxB.extend(b->getNode(sid)->bbox(1.01));

				for (auto nodeid_i : grpA){
					auto nodeA = a->getNode(nodeid_i);

					QMap < QString, double > dists;
					for (auto nodeid_j : grpB){
						auto nodeB = b->getNode(nodeid_j);

						Vector3 posA = (nodeA->position(Eigen::Vector4d(0.5, 0.5, 0, 0)) - boxA.min()).array() / boxA.sizes().array();
						Vector3 posB = (nodeB->position(Eigen::Vector4d(0.5, 0.5, 0, 0)) - boxB.min()).array() / boxB.sizes().array();

						dists[nodeid_j] = (posA - posB).norm();
					}
					auto nodeid_j = sortQMapByValue(dists).first().second;

					landmarksA << (QStringList() << nodeid_i);
					landmarksB << (QStringList() << nodeid_j);
				}
			}
			else
			{
				landmarksA << QStringList::fromVector(grpA);
				landmarksB << QStringList::fromVector(grpB);
			}
		}

		result.push_back( qMakePair(landmarksA, landmarksB) );
	}

    return result;
}