8#include <QJsonDocument>
27DefectMap::DefectMap() :
QObject()
35bool DefectMap::load(
const QString &filename)
37 QFile input(filename);
46 m_Filename = filename;
48 auto root = doc.object();
50 m_Camera = root[
"camera"].toString();
51 m_Median = root[
"median"].toDouble();
52 m_StandardDeviation = root[
"standardDeviation"].toDouble();
53 m_HotPixelsAggressiveness = root[
"hotAggressiveness"].toInt();
54 m_ColdPixelsAggressiveness = root[
"coldAggressiveness"].toInt();
62 for (
const auto &onePixel : qAsConst(hot))
65 m_HotPixels.insert(BadPixel(oneObject[
"x"].toInt(), oneObject[
"y"].toInt(), oneObject[
"value"].toDouble()));
68 m_HotPixelsCount = m_HotPixels.size();
70 for (
const auto &onePixel : qAsConst(cold))
73 m_ColdPixels.insert(BadPixel(oneObject[
"x"].toInt(), oneObject[
"y"].toInt(), oneObject[
"value"].toDouble()));
76 m_ColdPixelsCount = m_ColdPixels.size();
83bool DefectMap::save(
const QString &filename,
const QString &camera)
87 root.
insert(
"camera", camera);
88 root.
insert(
"median", m_Median);
89 root.
insert(
"standardDeviation", m_StandardDeviation);
90 root.
insert(
"hotAggressiveness", m_HotPixelsAggressiveness);
91 root.
insert(
"coldAggressiveness", m_ColdPixelsAggressiveness);
96 for (
const auto &onePixel : m_HotPixels)
97 hotArray.
append(onePixel.json());
102 for (
const auto &onePixel : m_ColdPixels)
103 coldArray.
append(onePixel.json());
106 root.
insert(
"hot", hotArray);
107 root.
insert(
"cold", coldArray);
109 QFile output(filename);
114 m_Filename = filename;
124double DefectMap::calculateSigma(uint8_t aggressiveness)
127 return 18.61742934980 * exp(-0.00052422221 * (aggressiveness - 9.89915467884) * (aggressiveness - 9.89915467884));
136 m_Median = data->getMedian(0);
137 m_StandardDeviation = data->getStdDev(0);
138 if (m_HotPixels.empty() && m_ColdPixels.empty())
147double DefectMap::getHotThreshold(uint8_t aggressiveness)
149 return (m_Median + m_StandardDeviation * calculateSigma(aggressiveness));
155double DefectMap::getColdThreshold(uint8_t aggressiveness)
157 return (m_Median - m_StandardDeviation * calculateSigma(aggressiveness));
163void DefectMap::initBadPixels()
165 double hotPixelThreshold = getHotThreshold(100);
166 double coldPixelThreshold = getColdThreshold(100);
168 m_ColdPixels.clear();
171 switch (m_DarkData->dataType())
174 initBadPixelsInternal<uint8_t>(hotPixelThreshold, coldPixelThreshold);
178 initBadPixelsInternal<int16_t>(hotPixelThreshold, coldPixelThreshold);
182 initBadPixelsInternal<uint16_t>(hotPixelThreshold, coldPixelThreshold);
186 initBadPixelsInternal<int32_t>(hotPixelThreshold, coldPixelThreshold);
190 initBadPixelsInternal<uint32_t>(hotPixelThreshold, coldPixelThreshold);
194 initBadPixelsInternal<float>(hotPixelThreshold, coldPixelThreshold);
198 initBadPixelsInternal<int64_t>(hotPixelThreshold, coldPixelThreshold);
202 initBadPixelsInternal<double>(hotPixelThreshold, coldPixelThreshold);
214void DefectMap::initBadPixelsInternal(
double hotPixelThreshold,
215 double coldPixelThreshold)
217 T
const *buffer =
reinterpret_cast<T const*
>(m_DarkData->getImageBuffer());
218 const uint32_t width = m_DarkData->width();
219 const uint32_t height = m_DarkData->height();
221 const uint32_t maxSize = 500000;
222 uint32_t samples = m_DarkData->samplesPerChannel();
223 uint8_t downsample = 1;
224 if (samples > maxSize)
226 downsample = (
static_cast<double>(samples) / maxSize) + 0.999;
227 samples /= downsample;
231 for (uint32_t y = 4; y < height - 4; y += downsample)
233 for (uint32_t x = 4; x < width - 4; x += downsample)
235 uint32_t offset = x + y * width;
236 if (buffer[offset] > hotPixelThreshold)
237 m_HotPixels.insert(BadPixel(x, y, buffer[offset]));
238 else if (buffer[offset] < coldPixelThreshold)
239 m_ColdPixels.insert(BadPixel(x, y, buffer[offset]));
249void DefectMap::filterPixels()
251 double hotPixelThreshold = getHotThreshold(m_HotPixelsAggressiveness);
252 double coldPixelThreshold = getColdThreshold(m_ColdPixelsAggressiveness);
254 m_HotPixelsThreshold = m_HotPixels.lower_bound(BadPixel(0, 0, hotPixelThreshold));
255 m_ColdPixelsThreshold = m_ColdPixels.lower_bound(BadPixel(0, 0, coldPixelThreshold));
257 if (m_HotPixelsThreshold == m_HotPixels.cend())
258 m_HotPixelsCount = 0;
260 m_HotPixelsCount = std::distance(m_HotPixelsThreshold, m_HotPixels.cend());
262 if (m_ColdPixelsThreshold == m_ColdPixels.cbegin())
263 m_ColdPixelsCount = 0;
265 m_ColdPixelsCount = std::distance(m_ColdPixels.cbegin(), m_ColdPixelsThreshold);
267 emit pixelsUpdated(m_HotPixelsCount, m_ColdPixelsCount);
273void DefectMap::setHotEnabled(
bool enabled)
275 m_HotEnabled = enabled;
276 emit pixelsUpdated(m_HotEnabled ? m_HotPixelsCount : 0, m_ColdPixelsCount);
282void DefectMap::setColdEnabled(
bool enabled)
284 m_ColdEnabled = enabled;
285 emit pixelsUpdated(m_HotPixelsCount, m_ColdEnabled ? m_ColdPixelsCount : 0);
void append(const QJsonValue &value)
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
iterator insert(QLatin1StringView key, const QJsonValue &value)