diff --git a/kstars/ekos/focus/focus.cpp b/kstars/ekos/focus/focus.cpp --- a/kstars/ekos/focus/focus.cpp +++ b/kstars/ekos/focus/focus.cpp @@ -101,13 +101,20 @@ connect(useFullField, &QCheckBox::toggled, [&](bool toggled) { Options::setFocusUseFullField(toggled); + fullFieldInnerRing->setEnabled(toggled); + fullFieldOuterRing->setEnabled(toggled); if (toggled) { useSubFrame->setChecked(false); useAutoStar->setChecked(false); } }); + connect(fullFieldInnerRing, static_cast(&QDoubleSpinBox::valueChanged), + [=](double d) { Options::setFocusFullFieldInnerRadius(d); }); + connect(fullFieldOuterRing, static_cast(&QDoubleSpinBox::valueChanged), + [=](double d) { Options::setFocusFullFieldOuterRadius(d); }); + FocusSettleTime->setValue(Options::focusSettleTime()); connect(FocusSettleTime, static_cast(&QDoubleSpinBox::valueChanged), [=](double d) { Options::setFocusSettleTime(d); }); @@ -247,6 +254,8 @@ darkFrameCheck->setChecked(Options::useFocusDarkFrame()); thresholdSpin->setValue(Options::focusThreshold()); useFullField->setChecked(Options::focusUseFullField()); + fullFieldInnerRing->setValue(Options::focusFullFieldInnerRadius()); + fullFieldOuterRing->setValue(Options::focusFullFieldOuterRadius()); //focusFramesSpin->setValue(Options::focusFrames()); connect(thresholdSpin, static_cast(&QDoubleSpinBox::valueChanged), this, &Ekos::Focus::setThreshold); @@ -792,8 +801,13 @@ Options::setSuspendGuiding(suspendGuideCheck->isChecked()); Options::setUseFocusDarkFrame(darkFrameCheck->isChecked()); Options::setFocusFramesCount(focusFramesSpin->value()); + Options::setFocusUseFullField(useFullField->isChecked()); qCDebug(KSTARS_EKOS_FOCUS) << "Starting focus with box size: " << focusBoxSize->value() + << " Subframe: " << ( useSubFrame->isChecked() ? "yes" : "no" ) + << " Autostar: " << ( useAutoStar->isChecked() ? "yes" : "no" ) + << " Full frame: " << ( useFullField->isChecked() ? "yes" : "no " ) + << " [" << fullFieldInnerRing->value() << "%," << fullFieldOuterRing->value() << "%]" << " Step Size: " << stepIN->value() << " Threshold: " << thresholdSpin->value() << " Tolerance: " << toleranceIN->value() << " Frames: " << 1 /*focusFramesSpin->value()*/ << " Maximum Travel: " << maxTravelIN->value(); @@ -1208,6 +1222,8 @@ focusView->findStars(ALGORITHM_CENTROID); else focusView->findStars(focusDetection); + focusView->filterStars(static_cast (fullFieldInnerRing->value()/100.0), + static_cast (fullFieldOuterRing->value()/100.0)); focusView->updateFrame(); // Get the average HFR of the whole frame @@ -2573,6 +2589,9 @@ starSelected = false; starCenter = QVector3D(); + + if (useFullField->isChecked()) + useFullField->setChecked(!enable); } void Focus::filterChangeWarning(int index) diff --git a/kstars/ekos/focus/focus.ui b/kstars/ekos/focus/focus.ui --- a/kstars/ekos/focus/focus.ui +++ b/kstars/ekos/focus/focus.ui @@ -564,16 +564,6 @@ - - - - - - - Dark Frame - - - @@ -584,7 +574,7 @@ - + Suspend Guiding while autofocus in progress @@ -594,23 +584,68 @@ - + + + + Wait this many seconds before resuming guiding. + + + 60.000000000000000 + + + + - <html><head/><body><p>Measure average HFR from all stars combined in a full frame. This method can be slow.</p></body></html> + <html><head/><body><p>Measure average HFR from all stars combined in a full frame. This method defaults to the Centroid detection, but can use SEP detection too. Its performance decreases as the number of stars increases.</p></body></html> Full Field + + + + <html><body><p>During full field focusing, stars which are inside this percentage of the frame are filtered out of HFR calculation (default 0%). Detection algorithms may also have an inherent filter.</p></body></html> + + + % + + + 1 + + + 10.000000000000000 + + + - + - Wait this many seconds before resuming guiding. + <html><body><p>During full field focusing, stars which are outside this percentage of the frame are filtered out of HFR calculation (default 100%). Detection algorithms may also have an inherent filter.</p></body></html> - - 60.000000000000000 + + % + + + 1 + + + 10.000000000000000 + + + 100.000000000000000 + + + + + + + + + + Dark Frame @@ -1041,8 +1076,6 @@ resetFrameB useAutoStar useSubFrame - useFullField - darkFrameCheck suspendGuideCheck focusBoxSize maxTravelIN diff --git a/kstars/fitsviewer/fitsdata.h b/kstars/fitsviewer/fitsdata.h --- a/kstars/fitsviewer/fitsdata.h +++ b/kstars/fitsviewer/fitsdata.h @@ -220,6 +220,9 @@ void getFloatBuffer(float *buffer, int x, int y, int w, int h); int findSEPStars(const QRect &boundary = QRect()); + // Apply ring filter to searched stars + int filterStars(const float innerRadius, const float outerRadius); + // Half Flux Radius Edge *getMaxHFRStar() const { return maxHFRStar; } double getHFR(HFRType type = HFR_AVERAGE); diff --git a/kstars/fitsviewer/fitsdata.cpp b/kstars/fitsviewer/fitsdata.cpp --- a/kstars/fitsviewer/fitsdata.cpp +++ b/kstars/fitsviewer/fitsdata.cpp @@ -1079,6 +1079,23 @@ return count; } +int FITSData::filterStars(const float innerRadius, const float outerRadius) +{ + long const sqDiagonal = this->width()*this->width()/4 + this->height()*this->height()/4; + long const sqInnerRadius = std::lround(sqDiagonal * innerRadius * innerRadius); + long const sqOuterRadius = std::lround(sqDiagonal * outerRadius * outerRadius); + + starCenters.erase(std::remove_if(starCenters.begin(), starCenters.end(), + [&](Edge *edge) { + long const x = edge->x - this->width()/2; + long const y = edge->y - this->height()/2; + long const sqRadius = x*x + y*y; + return sqRadius < sqInnerRadius || sqOuterRadius < sqRadius; + }), starCenters.end()); + + return starCenters.count(); +} + template int FITSData::findCannyStar(FITSData * data, const QRect &boundary) { diff --git a/kstars/fitsviewer/fitsview.h b/kstars/fitsviewer/fitsview.h --- a/kstars/fitsviewer/fitsview.h +++ b/kstars/fitsviewer/fitsview.h @@ -157,6 +157,7 @@ int findStars(StarAlgorithm algorithm = ALGORITHM_CENTROID, const QRect &searchBox = QRect()); void toggleStars(bool enable); void setStarsEnabled(bool enable); + int filterStars(const float innerRadius, const float outerRadius); // FITS Mode void updateMode(FITSMode fmode); @@ -290,6 +291,12 @@ bool showEQGrid { false }; bool showPixelGrid { false }; + struct { + bool used() const { return innerRadius != 0.0f || outerRadius != 1.0f; } + float innerRadius { 0.0f }; + float outerRadius { 1.0f }; + } starFilter; + CursorMode cursorMode { selectCursor }; bool zooming { false }; int zoomTime { 0 }; diff --git a/kstars/fitsviewer/fitsview.cpp b/kstars/fitsviewer/fitsview.cpp --- a/kstars/fitsviewer/fitsview.cpp +++ b/kstars/fitsviewer/fitsview.cpp @@ -775,6 +775,13 @@ } } +int FITSView::filterStars(float const innerRadius, float const outerRadius) +{ + starFilter.innerRadius = innerRadius; + starFilter.outerRadius = outerRadius; + return starFilter.used()? imageData->filterStars(innerRadius, outerRadius) : imageData->getStarCenters().count(); +} + void FITSView::updateFrame() { bool ok = false; @@ -800,6 +807,22 @@ drawOverlay(&painter); + if (starFilter.used()) + { + double const diagonal = std::sqrt(currentWidth*currentWidth + currentHeight*currentHeight)/2; + int const innerRadius = std::lround(diagonal*starFilter.innerRadius); + int const outerRadius = std::lround(diagonal*starFilter.outerRadius); + QPoint const center(currentWidth/2, currentHeight/2); + painter.save(); + painter.setPen(QPen(Qt::blue, 1, Qt::DashLine)); + painter.setOpacity(0.7); + painter.setBrush(QBrush(Qt::transparent)); + painter.drawEllipse(center, outerRadius, outerRadius); + painter.setBrush(QBrush(Qt::blue, Qt::FDiagPattern)); + painter.drawEllipse(center, innerRadius, innerRadius); + painter.restore(); + } + image_frame->setPixmap(displayPixmap); image_frame->resize(currentWidth, currentHeight); diff --git a/kstars/kstars.kcfg b/kstars/kstars.kcfg --- a/kstars/kstars.kcfg +++ b/kstars/kstars.kcfg @@ -1714,9 +1714,19 @@ true - + false + + + During full field focusing, stars which are inside this percentage of the frame are filtered out of HFR calculation (default 0%). Detection algorithms may also have an inherent filter. + 0.0 + + + + During full field focusing, stars which are outside this percentage of the frame are filtered out of HFR calculation (default 100%). Detection algorithms may also have an inherent filter. + 100.0 + false