Skip to content

STYLE: STAPLEImageFilter counts pixels in a double accumulator instead of GetNumberOfPixels() #6763

Description

@hjmjohnson

STAPLEImageFilter::GenerateData() counts pixels in a double accumulator rather than reading the region's pixel count directly:

https://github.com/InsightSoftwareConsortium/ITK/blob/main/Modules/Filtering/ImageCompare/include/itkSTAPLEImageFilter.hxx#L110-L125

double N = 0.0;
double g_t = 0.0;
{
  ImageScanlineIterator out(W, W->GetRequestedRegion());
  while (!out.IsAtEnd())
  {
    while (!out.IsAtEndOfLine())
    {
      out.Set(out.Get() / static_cast<double>(number_of_input_files));
      g_t += out.Get();
      N = N + 1.0;          // <-- pixel counter held in double
      ++out;
    }
    out.NextLine();
  }
  g_t = (g_t / N) * m_ConfidenceWeight;
}

This is not a live defect. double has a 53-bit mantissa, so the increment stays exact up to 2^53 pixels — unreachable. Filing it as cleanup only, because it is the same idiom as the float counter fixed in #6759, and someone auditing for that pattern will land here and have to re-derive that it's benign.

Suggested change: drop N and use the region's pixel count, which is exact by construction and removes a per-pixel add from the inner scanline loop.

const SizeValueType N = W->GetRequestedRegion().GetNumberOfPixels();

g_t itself must stay floating-point — it accumulates fractional per-pixel values, not counts.

Scope check — what else in this file was examined
  • The initial averaging loop out.Set(out.Get() + 1.0) accumulates in the output pixel type, but is bounded by number_of_input_files, so it carries no precision risk.
  • p_num / p_denom / q_num / q_denom accumulate fractional weights W_i and 1 - W_i over all pixels. These are genuinely fractional and already double; they are not counters and should not be converted.
  • alpha1 / beta1 are per-pixel products, not accumulations.

itkLabelVotingImageFilter was also checked and already counts votes in unsigned int.

Related: #6759 (the float variant of this pattern in MultiLabelSTAPLEImageFilter, where it was a real defect — float saturates at 2^24 = 16,777,216, which a 3D image reaches easily).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions