Skip to content

Commit 716400a

Browse files
committed
vtkImageHistogram for histogram computation (massive speedup)
1 parent 3c7f6fe commit 716400a

File tree

1 file changed

+64
-35
lines changed

1 file changed

+64
-35
lines changed

libs/charts/iAHistogramData.cpp

Lines changed: 64 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,18 @@
88
#include "iAToolsVTK.h"
99
#include "iATypedCallHelper.h"
1010

11-
#include <vtkImageAccumulate.h>
11+
//#define MODE_OWN 0 // use self-written code
12+
//#define MODE_VTK_ACC 1 // use vtkImageAccumulate
13+
//#define MODE_VTK_HIS 2 // use vtkImageHistogram
14+
15+
//#define HISTO_MODE MODE_VTK_HIS
16+
17+
//#if HISTO_MODE == MODE_VTK_ACC
18+
//#include <vtkImageAccumulate.h>
19+
//#elif HISTO_MODE == MODE_VTK_HIS
20+
#include <vtkIdTypeArray.h>
21+
#include <vtkImageHistogramStatistics.h>
22+
//#endif
1223
#include <vtkImageCast.h>
1324
#include <vtkImageData.h>
1425

@@ -243,10 +254,6 @@ void computeHistogram(std::shared_ptr<iAHistogramData> histData, vtkImageData* i
243254
}
244255
}
245256

246-
247-
#define MODE_VTK 0 // use self-written code above
248-
//#define MODE_VTK 1 // use vtkImageAccumulate
249-
250257
std::shared_ptr<iAHistogramData> iAHistogramData::create(QString const& name,
251258
vtkImageData* img, size_t desiredNumBin, iAImageStatistics* imgStatistics, int component)
252259
{
@@ -264,40 +271,62 @@ std::shared_ptr<iAHistogramData> iAHistogramData::create(QString const& name,
264271

265272
//QElapsedTimer timer;
266273
//timer.start();
267-
#if MODE_VTK
268-
if (img->GetNumberOfScalarComponents() != 1)
269-
{
270-
LOG(lvlDebug,
271-
QString("Image has %2 components, only computing histogram of first one!")
272-
.arg(img->GetNumberOfScalarComponents()));
273-
}
274-
auto accumulate = vtkSmartPointer<vtkImageAccumulate>::New();
275-
accumulate->ReleaseDataFlagOn();
276-
accumulate->SetInputData(img);
277-
accumulate->SetComponentOrigin(img->GetScalarRange()[0], 0.0, 0.0);
278-
// The check in finalNumBin guarantees that numBin is smaller than int max, so the cast to int below is safe!
279-
accumulate->SetComponentExtent(0, static_cast<int>(numBin - 1), 0, 0, 0, 0);
280-
accumulate->SetComponentSpacing(histRange / numBin, 0.0, 0.0);
281-
accumulate->Update();
274+
//#if HISTO_MODE == MODE_VTK_ACC
275+
// if (img->GetNumberOfScalarComponents() != 1)
276+
// {
277+
// LOG(lvlDebug,
278+
// QString("Image has %2 components, only computing histogram of first one!")
279+
// .arg(img->GetNumberOfScalarComponents()));
280+
// }
281+
// vtkNew<vtkImageAccumulate> accumulate;
282+
// accumulate->ReleaseDataFlagOn();
283+
// accumulate->SetInputData(img);
284+
// accumulate->SetComponentOrigin(img->GetScalarRange()[0], 0.0, 0.0);
285+
// // The check in finalNumBin guarantees that numBins is smaller than int max, so the cast to int below is safe!
286+
// accumulate->SetComponentExtent(0, static_cast<int>(numBins - 1), 0, 0, 0, 0);
287+
// accumulate->SetComponentSpacing(histRange / numBins, 0.0, 0.0);
288+
// accumulate->Update();
289+
// int extent[6];
290+
// accumulate->GetComponentExtent(extent);
291+
// vtkNew<vtkImageCast> caster;
292+
// caster->SetInputData(accumulate->GetOutput());
293+
// caster->SetOutputScalarType(iAVtkDataType<DataType>::value);
294+
// caster->Update();
295+
// auto rawImg = caster->GetOutput();
296+
//
297+
// auto vtkRawData = static_cast<DataType*>(rawImg->GetScalarPointer());
298+
// std::copy(vtkRawData, vtkRawData + result->m_numBin, result->m_histoData);
299+
// if (imgStatistics)
300+
// {
301+
// *imgStatistics = iAImageStatistics{ *accumulate->GetMin(), *accumulate->GetMax(), *accumulate->GetMean(), *accumulate->GetStandardDeviation() };
302+
// }
303+
// LOG(lvlDebug, QString("VTK (vtkImageAccumulate): %1 seconds").arg(timer.elapsed() / 1000.0, 5, 'f', 3));
304+
//#elif HISTO_MODE == MODE_VTK_HIS
305+
vtkNew<vtkImageHistogramStatistics> histo;
306+
histo->SetInputData(img);
307+
histo->GenerateHistogramImageOff();
308+
histo->AutomaticBinningOff();
309+
histo->SetNumberOfBins(numBins);
310+
histo->SetBinOrigin(scalarRange[0]);
311+
histo->SetBinSpacing(histRange / numBins);
312+
histo->SetActiveComponent(component);
313+
histo->Update();
282314
int extent[6];
283-
accumulate->GetComponentExtent(extent);
284-
auto caster = vtkSmartPointer<vtkImageCast>::New();
285-
caster->SetInputData(accumulate->GetOutput());
286-
caster->SetOutputScalarType(iAVtkDataType<DataType>::value);
287-
caster->Update();
288-
auto rawImg = caster->GetOutput();
289-
290-
auto vtkRawData = static_cast<DataType*>(rawImg->GetScalarPointer());
291-
std::copy(vtkRawData, vtkRawData + result->m_numBin, result->m_histoData);
315+
histo->GetOutput()->GetExtent(extent);
316+
auto vtkRawData = histo->GetHistogram();
317+
//#pragma omp parallel for // no difference in runtimes
318+
for (size_t b=0; b<result->m_numBin; ++b) {
319+
result->m_histoData[b] = vtkRawData->GetTuple1(b);
320+
}
292321
if (imgStatistics)
293322
{
294-
*imgStatistics = iAImageStatistics{ *accumulate->GetMin(), *accumulate->GetMax(), *accumulate->GetMean(), *accumulate->GetStandardDeviation() };
323+
*imgStatistics = iAImageStatistics{scalarRange[0], scalarRange[1], histo->GetMean(), histo->GetStandardDeviation() };
295324
}
296-
//LOG(lvlDebug, QString("VTK: %1 seconds").arg(timer.elapsed() / 1000.0, 5, 'f', 3));
297-
#else
298-
VTK_TYPED_CALL(computeHistogram, img->GetScalarType(), result, img, imgStatistics, component);
299-
//LOG(lvlDebug, QString("OpenMP: %1 seconds").arg(timer.elapsed() / 1000.0, 5, 'f', 3));
300-
#endif
325+
//LOG(lvlDebug, QString("VTK (vtkImageHistogram): %1 seconds").arg(timer.elapsed() / 1000.0, 5, 'f', 3));
326+
//#else // MODE_OWN
327+
// VTK_TYPED_CALL(computeHistogram, img->GetScalarType(), result, img, imgStatistics, component);
328+
// LOG(lvlDebug, QString("OpenMP: %1 seconds").arg(timer.elapsed() / 1000.0, 5, 'f', 3));
329+
//#endif
301330
result->m_spacing = histRange / result->m_numBin;
302331
result->updateYBounds();
303332

0 commit comments

Comments
 (0)