コード例 #1
0
ファイル: falsecolormodel.cpp プロジェクト: ribalda/gerbil
void FalseColorModel::requestColoring(FalseColoring::Type coloringType, bool recalc)
{
	GGDBG_CALL();

	// check if we are already initialized and should deal with that request
	foreach(representation::t repr, representation::all()) {
		if (FalseColoring::isBasedOn(coloringType, repr) && !representationInit[repr]) {
			GGDBGM("request for " << coloringType <<
				   ": representation " << repr << " not initialized, deferring request"<< endl);
			pendingRequests[coloringType] = true;
			return;
		}
	}

	FalseColoringCache::iterator cacheIt = cache.find(coloringType);
	if(cacheIt != cache.end() && cacheIt->valid()) {
		if(recalc &&
				// recalc makes sense only for SOM, the other representations
				// are deterministic -> no need to recompute
				!FalseColoring::isDeterministic(coloringType))
		{
			GGDBGM("have valid cached image, but re-calc requested for "
				   << coloringType << ", computing" << endl);
			cache[coloringType].invalidate();
			computeColoring(coloringType);
		} else {
			GGDBGM("have valid cached image for " << coloringType
				   << ", emitting falseColoringUpdate" << endl);
			emit falseColoringUpdate(coloringType, cacheIt->pixmap());
		}
	} else {
		GGDBGM("invalid cache for "<< coloringType << ", computing." << endl);
		computeColoring(coloringType);
	}
}
コード例 #2
0
ファイル: distviewmodel.cpp プロジェクト: ajaskier/gerbil
sets_ptr DistViewModel::subImage(const std::vector<cv::Rect> &regions,
								 cv::Rect roi)
{
	sets_ptr temp(new SharedData<std::vector<BinSet> >(NULL));
	inbetween = true;
	// FIXME need proper check if subImage is a valid operation in current state.
	if (!context) {
		GGDBGM(type << " no context" << endl);
		return temp;
	}
	if (!image || (**image).empty()) {
		GGDBGM(type << " no image" << endl);
		return temp;
	}
	SharedDataLock ctxlock(context->mutex);
	ViewportCtx args = **context;
	GGDBGM(args.type << endl);
	ctxlock.unlock();

	BackgroundTaskPtr taskBins(new DistviewBinsTbb(
		image, labels, labelColors, illuminant, args, context, binsets,
		temp, regions,
		std::vector<cv::Rect>(), cv::Mat1b(), false, false));
	queue->push(taskBins);

	return temp;
}
コード例 #3
0
ファイル: distviewmodel.cpp プロジェクト: ajaskier/gerbil
QPolygonF DistViewModel::getPixelOverlay(int y, int x)
{
	// FIXME need proper check if getPixelOverlay is a valid operation in current state.
	if (!image || (**image).empty()) {
		GGDBGM(type << " no image" << endl);
		return QPolygonF();
	}
	if (!context){
		GGDBGM(type << " no context" << endl);
		return QPolygonF();
	}

	SharedDataLock imagelock(image->mutex);
	SharedDataLock ctxlock(context->mutex);
	if (y >= (*image)->height ||
		x >= (*image)->width)
	{
		return QPolygonF();
	}

	const multi_img::Pixel &pixel = (**image)(y, x);
	QPolygonF points((*image)->size());

	for (unsigned int d = 0; d < (*image)->size(); ++d) {
		// note: do not apply illuminant correction here! no binning involved!
		points[d] = QPointF(d,
			Compute::curpos(pixel[d], d,
							(*context)->minval, (*context)->binsize));
	}
	return points;
}
コード例 #4
0
ファイル: distviewmodel.cpp プロジェクト: ajaskier/gerbil
void DistViewModel::addImage(sets_ptr temp,const std::vector<cv::Rect> &regions,
							 cv::Rect roi)
{
	inbetween = false;
	// FIXME need proper check if addImage is a valid operation in current state.
	if (!context) {
		GGDBGM(type << " no context" << endl);
		return;
	}
	if (!image || (**image).empty()) {
		GGDBGM(type << " no image" << endl);
		return;
	}
	SharedDataLock ctxlock(context->mutex);
	ViewportCtx args = **context;
	GGDBGM(args.type << endl);
	ctxlock.unlock();

	args.valid = false;

	args.reset.fetch_and_store(1);
	args.wait.fetch_and_store(1);

	BackgroundTaskPtr taskBins(new DistviewBinsTbb(
		image, labels, labelColors, illuminant, args, context,
		binsets, temp, std::vector<cv::Rect>(), regions,
		cv::Mat1b(), false, true));
	// connect to propagateBinningRange as this operation can change range
	QObject::connect(taskBins.get(), SIGNAL(finished(bool)),
					 this, SLOT(propagateBinningRange(bool)));
	queue->push(taskBins);
}
コード例 #5
0
ファイル: viewport.cpp プロジェクト: ribalda/gerbil
void Viewport::prepareLines()
{
	if (!ctx) {
		GGDBGM("no ctx" << endl);
		return;
	}
	if (!sets) {
		GGDBGM("no sets" << endl);
		return;
	}

	// lock context and sets
	SharedDataLock ctxlock(ctx->mutex);
	SharedDataLock setslock(sets->mutex);
	(*ctx)->wait.fetch_and_store(0); // set to zero: our data will be usable
	if ((*ctx)->reset.fetch_and_store(0)) // is true if it was 1 before
		reset();

	// first step (cpu only)
	Compute::preparePolylines(**ctx, **sets, shuffleIdx);

	// second step (cpu -> gpu)
	target->makeCurrent();
	Compute::storeVertices(**ctx, **sets, shuffleIdx, vb,
	                       drawMeans->isChecked(), illuminantAppl);

}
コード例 #6
0
void FalseColorDock::processComputationCancelled(FalseColoring::Type coloringType)
{
	if(coloringState[coloringType] == FalseColoringState::ABORTING) {
		coloringProgress[coloringType] = 0;
		GGDBGM("enterState():"<<endl);
		enterState(coloringType, FalseColoringState::UNKNOWN);
		updateTheButton();
		updateProgressBar();
	} else if(coloringState[coloringType] == FalseColoringState::CALCULATING) {
		enterState(coloringType, FalseColoringState::UNKNOWN);
		GGDBGM("restarting cancelled computation"<<endl);
		requestColoring(coloringType);
	}
}
コード例 #7
0
ファイル: distviewmodel.cpp プロジェクト: ajaskier/gerbil
void DistViewModel::setImage(SharedMultiImgPtr img, cv::Rect roi, int bins)
{
	GGDBGM(type << endl);
	inbetween = false;
	image = img;
	//GGDBGM(format("image.get()=%1%\n") %image.get());

	SharedDataLock ctxlock(context->mutex);
	ViewportCtx args = **context;
	ctxlock.unlock();

	args.type = type;
	args.ignoreLabels = ignoreLabels;

	args.nbins = bins;

	args.valid = false;

	args.reset.fetch_and_store(1);
	args.wait.fetch_and_store(1);

	assert(context);
	BackgroundTaskPtr taskBins(new DistviewBinsTbb(
		image, labels, labelColors, illuminant, args, context, binsets,
		sets_ptr(new SharedData<std::vector<BinSet> >(NULL)),
		std::vector<cv::Rect>(), std::vector<cv::Rect>(),
		cv::Mat1b(), false, true));
	// connect to propagateBinningRange, new image may have new range
	QObject::connect(taskBins.get(), SIGNAL(finished(bool)),
					 this, SLOT(propagateBinningRange(bool)));
	queue->push(taskBins);
}
コード例 #8
0
ファイル: distviewmodel.cpp プロジェクト: ajaskier/gerbil
void DistViewModel::updateBinning(int bins)
{
	SharedDataLock ctxlock(context->mutex);
	ViewportCtx args = **context;
	GGDBGM(args.type << endl);
	ctxlock.unlock();

	if (bins > 0) {
		args.nbins = bins;
	}

	args.valid = false;

	args.reset.fetch_and_store(1);
	args.wait.fetch_and_store(1);

	if (!image.get())
		return;

	BackgroundTaskPtr taskBins(new DistviewBinsTbb(
		image, labels, labelColors, illuminant, args, context, binsets));
	QObject::connect(taskBins.get(), SIGNAL(finished(bool)),
					 this, SLOT(propagateBinning(bool)), Qt::QueuedConnection);
	queue->push(taskBins);
}
コード例 #9
0
void FalseColorDock::processApplyClicked()
{
	if(coloringState[selectedColoring()] == FalseColoringState::CALCULATING) {
		GGDBGM("enterState():"<<endl);
		enterState(selectedColoring(), FalseColoringState::ABORTING);

		if (lastShown == selectedColoring()) {
			// Cancel after re-calc
			enterState(selectedColoring(), FalseColoringState::UNKNOWN);
			emit unsubscribeFalseColoring(this, selectedColoring());
			updateProgressBar();
			updateTheButton();
		} else {
			emit unsubscribeFalseColoring(this, selectedColoring());

			// go back to last shown coloring
			if(coloringUpToDate[lastShown]) {
				uisel->sourceBox->setCurrentIndex(int(lastShown));
				requestColoring(lastShown);
			} else { // or fall back to CMF, e.g. after ROI change
				uisel->sourceBox->setCurrentIndex(FalseColoring::CMF);
				requestColoring(FalseColoring::CMF);
			}
		}
	} else if( coloringState[selectedColoring()] == FalseColoringState::FINISHED ||
			  coloringState[selectedColoring()] == FalseColoringState::UNKNOWN )
	{
		requestColoring(selectedColoring(), /* recalc */ true);

	}
}
コード例 #10
0
void FalseColorDock::processSelectedColoring()
{
	emit unsubscribeFalseColoring(this, lastShown);
	GGDBGM( "requesting false color image " << selectedColoring() << endl);
	requestColoring(selectedColoring());
	updateTheButton();
	updateProgressBar();
}
コード例 #11
0
void FalseColorDock::requestColoring(FalseColoring::Type coloringType, bool recalc)
{
	if (coloringState[coloringType] != FalseColoringState::FINISHED || recalc) {
			GGDBGM("enterState():"<<endl);
			enterState(coloringType, FalseColoringState::CALCULATING);
			updateTheButton();
	}
	if (recalc) {
		GGDBGM("recalc " << coloringType << endl);
		emit subscribeFalseColoring(this, coloringType);
		emit falseColoringRecalcRequested(coloringType);
	} else {
		GGDBGM("subscribe " << coloringType << endl);
		emit subscribeFalseColoring(this, coloringType);
	}
	updateProgressBar();
	updateTheButton();
}
コード例 #12
0
void DistViewGUI::fold(bool folded)
{
	if (folded) { // fold
		GGDBGM(type << " folding" << endl);

		// let the controller know we do not need our image representation
		emit unsubscribeRepresentation(this, type);

		// fold GUI and set size policy for proper arrangement
		ui->gv->setHidden(true);
		ui->topBar->fold();
		frame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);

		// reset title
		setTitle(type);

		// TODO: send signals that will destroy unused data!

		// TODO: let viewport clean itself up!
		//(*binsets)->clear(); // clear the vector, not re-create shareddata!
		//viewport->shuffleIdx.clear();
		//viewport->vb.destroy();
		emit foldingStateChanged(type, true);

	} else { // unfold
		GGDBGM(type << " unfolding" << endl);

		emit needBinning(type);
		// let the controller know we need our image representation
		emit subscribeRepresentation(this, type);

		// unfold GUI and set size policy for proper arrangement
		ui->gv->setVisible(true);
		ui->topBar->unfold();
		QSizePolicy pol(QSizePolicy::Preferred, QSizePolicy::Expanding);
		pol.setVerticalStretch(1);
		frame->setSizePolicy(pol);

		emit foldingStateChanged(type, false);

		// TODO: trigger calculation of data?
	}
}
コード例 #13
0
ファイル: distviewcompute.cpp プロジェクト: ajaskier/gerbil
void Compute::GenerateVertices::operator()(const tbb::blocked_range<size_t> &r) const
{
	for (tbb::blocked_range<size_t>::const_iterator i = r.begin();
		 i != r.end();
		 ++i)
	{
		const std::pair<size_t, BinSet::HashKey> &idx = index[i];
		if ( !(0 <= idx.first || idx.first < sets.size())) {
			GGDBGM("bad sets index"<< endl);
			return;
		}
		const BinSet &s = sets[idx.first];
		const BinSet::HashKey &K = idx.second;
		// concurrent_hash_map::equal_range may not be used for concurrent
		// access.
		// See http://www.threadingbuildingblocks.org/docs/help/reference/containers_overview/concurrent_hash_map_cls.htm
		// However, this is part of a read-only iteration, where the BinSet is
		// never modified. Thus using concurrent_hash_map::equal_range seems
		// OK.
		std::pair<BinSet::HashMap::const_iterator,
				  BinSet::HashMap::const_iterator>
				binitp = s.bins.equal_range(K);
		if (s.bins.end() == binitp.first) {
			GGDBGM("no bin"<< endl);
			return;
		}
		const Bin &b = binitp.first->second;
		int vidx = i * 2 * dimensionality;
		for (size_t d = 0; d < dimensionality; ++d) {
			qreal curpos;
			if (drawMeans) {
				curpos = ((b.means[d] / b.weight) - minval) / binsize;
			} else {
				curpos = (unsigned char)K[d] + 0.5;
				if (!illuminant.empty())
					curpos *= illuminant[d];
			}
			varr[vidx++] = d;
			varr[vidx++] = curpos;
		}
	}
}
コード例 #14
0
ファイル: openrecent.cpp プロジェクト: philippefoubert/gerbil
void OpenRecent::browseForFile()
{
	// see QFileDialog::getOpenFileName()
	static const QString fileTypesString =
			"Images(*.png *.tif *.jpg *.txt);;"
			"All files (*)";
	QFileDialog::Options options;
	options &=  ! QFileDialog::HideNameFilterDetails;

	// Try to get path for open file dialog from line edit. If this does not
	// yield a valid path, try recentPath which is either the last used
	// directory or the user's home.
	QString dir = ui->fileLineEdit->text();
	QFileInfo fi(dir);
	if (dir.isEmpty()) {
		dir = recentPath;
	} else if (! fi.isDir()) {
		dir = fi.path();
		GGDBGM("not a dir, using path component " << dir.toStdString() << endl);
	}
	fi = QFileInfo(dir);
	GGDBGM("trying " << dir.toStdString() << endl);
	if (! fi.isDir() || ! QDir(dir).exists()) {
		GGDBGM("still not a dir, using recent path or home "
			   << recentPath.toStdString() << endl);
		dir = recentPath;
	}

	QString fileName = QFileDialog::getOpenFileName(
				this,
				"Open Image",
				dir,
				fileTypesString,
				0,
				options);
	GGDBGM("dialog returned \"" << fileName.toStdString() << "\"" << endl);
	if (! fileName.isEmpty()) {
		ui->fileLineEdit->setText(fileName);
		accept();
	}
	ui->fileLineEdit->setFocus();
}
コード例 #15
0
ファイル: falsecolormodel.cpp プロジェクト: ribalda/gerbil
void FalseColorModel::processImageUpdate(representation::t type,
										 SharedMultiImgPtr,
										 bool duplicate)
{
	GGDBGM("representation " << type << ", "
		   << "duplicate: " << duplicate << endl);
	if (duplicate) {
		return;
	}
	// make sure no computations based on old image data make it into the
	// cache
	FalseColorModelPayloadMap::iterator payloadIt;
	for (payloadIt = payloads.begin(); payloadIt != payloads.end(); payloadIt++) {
		FalseColoring::Type coloringType = payloadIt.key();
		if(FalseColoring::isBasedOn(coloringType, type)) {
			GGDBGM("abandoning payload " << coloringType << endl);
			abandonPayload(coloringType);
			// remember to restart the calculation
			pendingRequests[coloringType] = true;
		}
	}

	// invalidate affected cache entries:
	FalseColoringCache::iterator it;
	for (it=cache.begin(); it != cache.end(); it++) {
		FalseColoring::Type coloringType = it.key();
		if(FalseColoring::isBasedOn(coloringType, type)) {
			GGDBGM("invalidate cache for " << type << endl);
			it.value().invalidate();
		}
	}

	foreach(FalseColoring::Type c, FalseColoring::all()) {
		if (FalseColoring::isBasedOn(c, type) && pendingRequests[c]) {
			GGDBGM("processing pending request for " << c << endl);
			pendingRequests[c] = false;
			computeColoring(c);
		}
	}

	representationInit[type] = true;
}
コード例 #16
0
void FalseColorDock::processFalseColoringUpdate(FalseColoring::Type coloringType, QPixmap p)
{
	GGDBGM("enterState():"<<endl);
	GGDBGM("receiving coloring " << coloringType << endl);
	enterState(coloringType, FalseColoringState::FINISHED);
	coloringUpToDate[coloringType] = true;
	updateTheButton();
	updateProgressBar();
	sw->doneAction()->setEnabled(false);
	if (coloringType == selectedColoring()) {
		//GGDBGM("updating " << coloringType << endl);
		view->setEnabled(true);
		scene->setPixmap(p);
		view->update();
		// good idea but seems distracting right now
		//view->setToolTip(prettyFalseColorNames[coloringType]);
		this->setWindowTitle(prettyFalseColorNames[coloringType]);
		lastShown = coloringType;
	}
}
コード例 #17
0
ファイル: distviewmodel.cpp プロジェクト: ajaskier/gerbil
void DistViewModel::updateLabelsPartially(const cv::Mat1s &newLabels,
											 const cv::Mat1b &mask, bool active)
{
	// save old configuration for partial updates
	cv::Mat1s oldLabels = labels.clone();
	// just override the whole thing
	labels = newLabels.clone();

	if (!active || !image.get())
		return;

	SharedDataLock ctxlock(context->mutex);
	ViewportCtx args = **context;
	GGDBGM(args.type << endl);
	ctxlock.unlock();

	args.wait.fetch_and_store(1);

	// we calculate into temp, then from temp in the second round
	sets_ptr temp(new SharedData<std::vector<BinSet> >(NULL));
	{	// first round: delete all pixels from their *previous* labels
		std::vector<cv::Rect> sub;
		sub.push_back(cv::Rect(0, 0, mask.cols, mask.rows));
		BackgroundTaskPtr taskBins(new DistviewBinsTbb(
			image, oldLabels, labelColors, illuminant, args,
			context, binsets, temp, sub, std::vector<cv::Rect>(),
			mask, false, false));
		queue->push(taskBins);
	}

	{	// second round: now add them back according to their current labels
		/* we do not clone labels, as labels is never changed, only replaced
		 * TODO: write that down at the appropriate place so people will
		 * adhere to that */
		std::vector<cv::Rect> add;
		add.push_back(cv::Rect(0, 0, mask.cols, mask.rows));
		BackgroundTaskPtr taskBins(new DistviewBinsTbb(
			image, labels, labelColors, illuminant, args,
			context, binsets, temp, std::vector<cv::Rect>(), add,
			mask, false, true));

		// final signal
		QObject::connect(taskBins.get(), SIGNAL(finished(bool)),
				 this, SLOT(propagateBinning(bool)), Qt::QueuedConnection);
		queue->push(taskBins);
	}
}
コード例 #18
0
ファイル: distviewmodel.cpp プロジェクト: ajaskier/gerbil
void DistViewModel::updateLabels(const cv::Mat1s &newLabels, bool active)
{
	if (!newLabels.empty())
		labels = newLabels.clone();

	// check if we are ready to compute anything and not within ROI change
	if (!active || inbetween || !image.get() || labels.empty())
		return;

	SharedDataLock ctxlock(context->mutex);
	ViewportCtx args = **context;
	GGDBGM(args.type << endl);
	ctxlock.unlock();

	args.wait.fetch_and_store(1);

	BackgroundTaskPtr taskBins(new DistviewBinsTbb(
		image, labels, labelColors, illuminant, args, context, binsets));
	QObject::connect(taskBins.get(), SIGNAL(finished(bool)),
					 this, SLOT(propagateBinning(bool)), Qt::QueuedConnection);
	queue->push(taskBins);
}
コード例 #19
0
ファイル: openrecent.cpp プロジェクト: philippefoubert/gerbil
void OpenRecent::keyPressEvent(QKeyEvent *event)
{
	// If up/down key pressed in line edit focus on listView and forward
	// event.
	if (! ui->recentFilesListView->hasFocus() &&
			(event->key() == Qt::Key_Up || event->key() == Qt::Key_Down))
	{
		GGDBGM("got QKeyEvent Up/Down" << endl);
		event->accept();
		ui->recentFilesListView->setFocus();
		// Is there any clever way to clone an event?
		QKeyEvent *evclone = new QKeyEvent(event->type(),
										   event->key(),
										   event->modifiers(),
										   event->text(),
										   event->isAutoRepeat(),
										   event->count());
		QApplication::postEvent(ui->recentFilesListView, evclone);
	} else {
		QDialog::keyPressEvent(event);
	}
}
コード例 #20
0
ファイル: viewport_drawing.cpp プロジェクト: ajaskier/gerbil
void Viewport::drawBins(QPainter &painter, QTimer &renderTimer,
                        unsigned int &renderedLines, unsigned int renderStep,
                        bool highlight)
{
	SharedDataLock ctxlock(ctx->mutex);
	// TODO: this also locks shuffleIdx implicitely, better do it explicitely?
	SharedDataLock setslock(sets->mutex);

	// Stopwatch watch("drawBins");

	/* initialize painting in GL, vertex buffer */
	target->makeCurrent();
	painter.beginNativePainting();
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	bool success = vb.bind();
	if (!success) {
		GerbilApplication::internalError(
		            "Vertex buffer could not be bound in viewport drawBins().",
		            false);
		painter.endNativePainting();
		return;
	}
	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(2, GL_FLOAT, 0, 0);
	size_t iD = renderedLines * (*ctx)->dimensionality;

	/* determine drawing range. could be expanded to only draw spec. labels */
	// make sure that viewport draws "unlabeled" data in ignore-label case
	int start = ((showUnlabeled || (*ctx)->ignoreLabels == 1) ? 0 : 1);
	int end = (showLabeled ? (int)(*sets)->size() : 1);

	size_t total = shuffleIdx.size();
	size_t first = renderedLines;
	size_t last = std::min((size_t)(renderedLines + renderStep), total);

	// loop over all elements in vertex index, update element and vector indices
	for (size_t i = first; i < last;
	     ++i, iD += (*ctx)->dimensionality) {
		std::pair<int, BinSet::HashKey> &idx = shuffleIdx[i];

		// filter out according to label
		bool filter = ((idx.first < start || idx.first >= end));
		// do not filter out highlighted label(s)
		if (!(*ctx)->ignoreLabels) {
			filter = filter && !highlightLabels.contains(idx.first);
		}
		if (filter) {
			// increase loop count to achieve renderStep
			if (last < total)
				++last;
			continue;
		}

		BinSet::HashKey &K = idx.second;

		// highlight mode (foreground buffer)
		if (highlight) {

			//test if we are part of the highlight
			bool highlighted = false;
			if (limiterMode) {
				highlighted = true;
				for (size_t i = 0; i < (*ctx)->dimensionality; ++i) {
					unsigned char k = K[i];
					if (k < limiters[i].first || k > limiters[i].second)
						highlighted = false;
				}
			} else if ((unsigned char)K[selection] == hover) {
				highlighted = true;
			}

			// filter out
			if (!highlighted) {
				// increase loop count to achieve renderStep
				if (last < total)
					++last;
				continue;
			}
		}

		// grab binset and bin according to key
		BinSet &s = (**sets)[idx.first];
		std::pair<BinSet::HashMap::const_iterator, BinSet::HashMap::const_iterator> binitp =
		        s.bins.equal_range(K);
		if (s.bins.end() == binitp.first) {
			// FIXME this is an error and should be treated accordingly
			GGDBGM("no bin"<< endl);
			return;
		}
		Bin const &b = s.bins.equal_range(K).first->second;

		// set color
		QColor color = determineColor((drawRGB->isChecked() ? b.rgb : s.label),
		                              b.weight, s.totalweight,
		                              highlight,
		                              highlightLabels.contains(idx.first));
		target->qglColor(color);

		// draw polyline
		glDrawArrays(GL_LINE_STRIP, (GLsizei)iD, (GLint)(*ctx)->dimensionality);
	}
	vb.release();
	painter.endNativePainting();

	// setup succeeding incremental drawing
	renderedLines += (unsigned int)(last - first);
	if (renderedLines < total) {
		if (renderedLines <= renderStep) {
			renderTimer.start(150);
		} else {
			renderTimer.start(0);
		}
	}
}
コード例 #21
0
ファイル: controller.cpp プロジェクト: ribalda/gerbil
Controller::Controller(const QString &filename,
                       bool limited_mode,
                       const QString &labelfile,
                       QObject *parent)

    : QObject(parent),
      // initialize all pointers so we don't access them too early w/o notice
      im(nullptr), lm(nullptr), fm(nullptr), illumm(nullptr),
      gsm(nullptr),
#ifdef WITH_SEG_MEANSHIFT
      cm(nullptr),
#endif
      dvc(nullptr),
      queuethread(nullptr),
      subs(new Subscriptions)
{
	// reset internal ROI state tracking
	resetROISpawned();

	// start background task queue thread
	connect(&queue, SIGNAL(exception(std::exception_ptr, bool)),
	        GerbilApplication::instance(),
	        SLOT(handle_exception(std::exception_ptr,bool)),
	        Qt::BlockingQueuedConnection);
	startQueue();

	im = new ImageModel(queue, limited_mode, this);
	// load image
	cv::Rect dimensions = im->loadImage(filename);
	imgSize = cv::Size(dimensions.width, dimensions.height);

	// create gui (perform initUI before connecting signals!)
	window = new MainWindow();
	window->initUI(filename);

	// initialize models
	initImage();
	fm = new FalseColorModel();
	initFalseColor(); // depends on ImageModel / initImage()

	// The order of connection is crucial for fm and Controller.
	// fm needs to get the signal first. Otherwise it will
	// hand out invalid cached data.
	connect(im, SIGNAL(imageUpdate(representation::t,SharedMultiImgPtr,bool)),
	        fm, SLOT(processImageUpdate(representation::t,SharedMultiImgPtr,bool)));
	connect(im, SIGNAL(imageUpdate(representation::t,SharedMultiImgPtr,bool)),
	        this, SLOT(processImageUpdate(representation::t,SharedMultiImgPtr,bool)));

	lm = new LabelingModel(this);
	initLabeling(dimensions);
	illumm = new IllumModel(&queue, this);
	initIlluminant();
	gsm = new GraphSegmentationModel(&queue, this);
	initGraphSegmentation(); // depends on ImageModel / initImage()
#ifdef WITH_SEG_MEANSHIFT
	cm = new ClusteringModel(this);
#endif /* WITH_SEG_MEANSHIFT */

	// initialize sub-controllers (after initializing the models...)
	dvc = new DistViewController(this, &queue, im);
	dvc->init();

	// init dock widgets
	initDocks();

	// connect slots/signals
	window->initSignals(this, dvc);

	/* TODO: better place. But do not use init model functions:
	 * dvc are created after these are called
	 */
	connect(dvc, SIGNAL(requestOverlay(cv::Mat1b)),
	        this, SIGNAL(requestOverlay(cv::Mat1b)));
	connect(lm,
	        SIGNAL(newLabeling(const cv::Mat1s&, const QVector<QColor>&, bool)),
	        dvc, SLOT(updateLabels(cv::Mat1s,QVector<QColor>,bool)));
	connect(lm, SIGNAL(partialLabelUpdate(const cv::Mat1s&,const cv::Mat1b&)),
			dvc, SLOT(updateLabelsPartially(const cv::Mat1s&,const cv::Mat1b&)));
	connect(dvc, SIGNAL(alterLabelRequested(short,cv::Mat1b,bool)),
	        lm, SLOT(alterLabel(short,cv::Mat1b,bool)));
	connect(illumm, SIGNAL(newIlluminantCurve(QVector<multi_img::Value>)),
	        dvc, SIGNAL(newIlluminantCurve(QVector<multi_img::Value>)));
	connect(illumm, SIGNAL(newIlluminantApplied(QVector<multi_img::Value>)),
	        dvc, SIGNAL(newIlluminantApplied(QVector<multi_img::Value>)));

#ifdef WITH_SEG_MEANSHIFT
	connect(cm, SIGNAL(subscribeRepresentation(QObject*,representation::t)),
	        this, SLOT(subscribeRepresentation(QObject*,representation::t)));
	connect(cm, SIGNAL(unsubscribeRepresentation(QObject*,representation::t)),
	        this, SLOT(unsubscribeRepresentation(QObject*,representation::t)));
	connect(im, SIGNAL(imageUpdate(representation::t,SharedMultiImgPtr,bool)),
	        cm, SLOT(processImageUpdate(representation::t,SharedMultiImgPtr,bool)));
#endif

	connect(this, SIGNAL(preROISpawn(cv::Rect,cv::Rect,std::vector<cv::Rect>,std::vector<cv::Rect>,bool)),
	        dvc, SLOT(processPreROISpawn(cv::Rect,cv::Rect,std::vector<cv::Rect>,std::vector<cv::Rect>,bool)));
	connect(this, SIGNAL(postROISpawn(cv::Rect,cv::Rect,std::vector<cv::Rect>,std::vector<cv::Rect>,bool)),
	        dvc, SLOT(processPostROISpawn(cv::Rect,cv::Rect,std::vector<cv::Rect>,std::vector<cv::Rect>,bool)));

	/* start with initial label or provided labeling
	 * Do this after all signals are connected, and before initial ROI spawn!
	 */
	if (labelfile.isEmpty()) {
		lm->addLabel();
	} else {
		lm->loadLabeling(labelfile);
	}

	/* Initial ROI images spawning. Do it before showing the window but after
	 * all signals were connected! */
	//GGDBGM("dimensions " << dimensions << endl);
	roi = dimensions; // initial ROI is image size, except:
	if (roi.area() > 262144) {
		// image is bigger than 512x512, start with a smaller ROI in center
		roi.width = std::min(roi.width, 512);
		roi.height = std::min(roi.height, 512);
		roi.x = 0.5*(dimensions.width - roi.width);
		roi.y = 0.5*(dimensions.height - roi.height);
	}

	GGDBGM("roi " << roi  << endl);
	spawnROI();

	// The IMG representation must always be subscribed. Otherwise all the logic
	// in ImageModel fails. So we subscribe the Controller forever.
	subscribeRepresentation(this, representation::IMG);

	GGDBGM("init distview subscriptions" << endl);
	dvc->initSubscriptions();

	GGDBGM("init done, showing mainwindow" << endl);

	// we're done! show window
	window->show();
}
コード例 #22
0
void FalseColorDock::enterState(FalseColoring::Type coloringType, FalseColoringState::Type state)
{
	GGDBGM(coloringType << " entering state " << state << endl);
	coloringState[coloringType] = state;
}