7#include "darkprocessor.h"
8#include "darklibrary.h"
9#include "ekos/auxiliary/opticaltrainsettings.h"
13#include "ekos_debug.h"
22 emit darkFrameCompleted(m_Watcher.result());
31 uint16_t offsetX, uint16_t offsetY)
33 switch (lightData->dataType())
36 normalizeDefectsInternal<uint8_t>(defectMap, lightData, offsetX, offsetY);
40 normalizeDefectsInternal<int16_t>(defectMap, lightData, offsetX, offsetY);
44 normalizeDefectsInternal<uint16_t>(defectMap, lightData, offsetX, offsetY);
48 normalizeDefectsInternal<int32_t>(defectMap, lightData, offsetX, offsetY);
52 normalizeDefectsInternal<uint32_t>(defectMap, lightData, offsetX, offsetY);
56 normalizeDefectsInternal<float>(defectMap, lightData, offsetX, offsetY);
60 normalizeDefectsInternal<int64_t>(defectMap, lightData, offsetX, offsetY);
64 normalizeDefectsInternal<double>(defectMap, lightData, offsetX, offsetY);
80 T *lightBuffer =
reinterpret_cast<T *
>(lightData->getWritableImageBuffer());
81 const uint32_t width = lightData->width();
87 for (BadPixelSet::const_iterator onePixel = defectMap->hotThreshold();
88 onePixel != defectMap->hotPixels().cend(); ++onePixel)
90 const uint16_t x = (*onePixel).x;
91 const uint16_t y = (*onePixel).y;
93 if (x <= offsetX || y <= offsetY)
96 uint32_t offset = (x - offsetX) + (y - offsetY) * width;
98 lightBuffer[offset] = median3x3Filter(x - offsetX, y - offsetY, width, lightBuffer);
101 for (BadPixelSet::const_iterator onePixel = defectMap->coldPixels().cbegin();
102 onePixel != defectMap->coldThreshold(); ++onePixel)
104 const uint16_t x = (*onePixel).x;
105 const uint16_t y = (*onePixel).y;
107 if (x <= offsetX || y <= offsetY)
110 uint32_t offset = (x - offsetX) + (y - offsetY) * width;
112 lightBuffer[offset] = median3x3Filter(x - offsetX, y - offsetY, width, lightBuffer);
115 lightData->calculateStats(
true);
123T DarkProcessor::median3x3Filter(uint16_t x, uint16_t y, uint32_t width, T *buffer)
125 T *top = buffer + (y - 1) * width + (x - 1);
126 T *mid = buffer + (y - 0) * width + (x - 1);
127 T *bot = buffer + (y + 1) * width + (x - 1);
129 std::array<T, 8> elements;
132 elements[0] = *(top + 0);
133 elements[1] = *(top + 1);
134 elements[2] = *(top + 2);
136 elements[3] = *(mid + 0);
138 elements[4] = *(mid + 2);
140 elements[5] = *(bot + 0);
141 elements[6] = *(bot + 1);
142 elements[7] = *(bot + 2);
144 std::sort(elements.begin(), elements.end());
145 auto median = (elements[3] + elements[4]) / 2;
153 uint16_t offsetX, uint16_t offsetY)
155 switch (darkData->dataType())
158 subtractInternal<uint8_t>(darkData, lightData, offsetX, offsetY);
162 subtractInternal<int16_t>(darkData, lightData, offsetX, offsetY);
166 subtractInternal<uint16_t>(darkData, lightData, offsetX, offsetY);
170 subtractInternal<int32_t>(darkData, lightData, offsetX, offsetY);
174 subtractInternal<uint32_t>(darkData, lightData, offsetX, offsetY);
178 subtractInternal<float>(darkData, lightData, offsetX, offsetY);
182 subtractInternal<int64_t>(darkData, lightData, offsetX, offsetY);
186 subtractInternal<double>(darkData, lightData, offsetX, offsetY);
199 uint16_t offsetX, uint16_t offsetY)
201 const uint32_t width = lightData->width();
202 const uint32_t height = lightData->height();
203 T *lightBuffer =
reinterpret_cast<T *
>(lightData->getWritableImageBuffer());
205 const uint32_t darkStride = darkData->width();
206 const uint32_t darkoffset = offsetX + offsetY * darkStride;
207 T
const *darkBuffer =
reinterpret_cast<T const*
>(darkData->getImageBuffer()) + darkoffset;
209 for (uint32_t y = 0; y < height; y++)
211 for (uint32_t x = 0; x < width; x++)
212 lightBuffer[x] = (lightBuffer[x] > darkBuffer[x]) ? (lightBuffer[x] - darkBuffer[x]) : 0;
214 lightBuffer += width;
215 darkBuffer += darkStride;
218 lightData->calculateStats(
true);
225 double duration, uint16_t offsetX, uint16_t offsetY)
227 info = {trainID, m_TargetChip, targetData, duration, offsetX, offsetY};
229 auto useDefect =
false;
231 OpticalTrainSettings::Instance()->setOpticalTrainID(trainID);
232 auto settings = OpticalTrainSettings::Instance()->getOneSetting(OpticalTrainSettings::DarkLibrary);
233 if (settings.isValid())
234 useDefect = settings.toMap().contains(
"preferDefectsRadio");
235#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
240 m_Watcher.setFuture(result);
246bool DarkProcessor::denoiseInternal(
bool useDefect)
254 if (DarkLibrary::Instance()->findDefectMap(info.targetChip, info.duration, targetDefectMap))
256 normalizeDefects(targetDefectMap, info.targetData, info.offsetX, info.offsetY);
257 qCDebug(KSTARS_EKOS) <<
"Defect map denoising applied";
264 if (DarkLibrary::Instance()->findDarkFrame(info.targetChip, info.duration, darkData))
267 if (info.offsetX == 0 && info.offsetY == 0 &&
268 (info.targetData->width() != darkData->width() || info.targetData->height() != darkData->height()))
271 emit newLog(
i18n(
"No suitable dark frames or defect maps found. Please run the Dark Library wizard in Capture module."));
274 subtractDarkData(darkData, info.targetData, info.offsetX, info.offsetY);
275 qCDebug(KSTARS_EKOS) <<
"Dark frame subtraction applied";
279 emit newLog(
i18n(
"No suitable dark frames or defect maps found. Please run the Dark Library wizard in Capture module."));
CameraChip class controls a particular chip in camera.
QString i18n(const char *text, const TYPE &arg...)
Ekos is an advanced Astrophotography tool for Linux.
QFuture< T > run(Function function,...)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)