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); } }
sets_ptr DistViewModel::subImage(const std::vector<cv::Rect> ®ions, 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; }
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; }
void DistViewModel::addImage(sets_ptr temp,const std::vector<cv::Rect> ®ions, 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); }
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); }
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); } }
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); }
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); }
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); } }
void FalseColorDock::processSelectedColoring() { emit unsubscribeFalseColoring(this, lastShown); GGDBGM( "requesting false color image " << selectedColoring() << endl); requestColoring(selectedColoring()); updateTheButton(); updateProgressBar(); }
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(); }
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? } }
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; } } }
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(); }
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; }
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; } }
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); } }
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); }
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); } }
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); } } }
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(); }
void FalseColorDock::enterState(FalseColoring::Type coloringType, FalseColoringState::Type state) { GGDBGM(coloringType << " entering state " << state << endl); coloringState[coloringType] = state; }