gaussSmooth()

in src/engine/loaders/voltools.js [49:162]


  gaussSmooth(volBuffer, xDim, yDim, zDim, gaussRadius, gaussSigma) {
    // eslint-disable-next-line
    const side = Math.floor(gaussRadius * 2 + 1);
    // check valid arguments
    const ERR_SIDE = -1;
    const ERR_BAD_SIGMA = -2;
    const ERR_DIM_NEGATIVE = -3;
    const ERR_DIM_LARGE = -4;
    const ERR_VOL_BUF_NULL = -5;
    const ERR_WRONG_BUF_SIZE = -6;
    if (side > GAUSS_SMOOTH_MAX_SIDE) {
      return ERR_SIDE;
    }
    const SIGMA_MIN = 0.0;
    const SIGMA_MAX = 8.0;
    if (gaussSigma < SIGMA_MIN || gaussSigma > SIGMA_MAX) {
      return ERR_BAD_SIGMA;
    }
    if (xDim <= 0 || yDim <= 0 || zDim <= 0) {
      return ERR_DIM_NEGATIVE;
    }
    if (xDim > MAX_VOLUME_SIDE_INPUT || yDim > MAX_VOLUME_SIDE_INPUT || zDim > MAX_VOLUME_SIDE_INPUT) {
      return ERR_DIM_LARGE;
    }
    // check valid buffer size
    if (volBuffer === null) {
      return ERR_VOL_BUF_NULL;
    }
    const bufSize = volBuffer.length;
    if (bufSize < xDim * yDim * zDim) {
      return ERR_WRONG_BUF_SIZE;
    }

    const side2 = side * side;
    const side3 = side2 * side;
    // eslint-disable-next-line
    const koefSpatial = 1.0 / (2.0 * gaussSigma * gaussSigma);

    // console.log(`Start Gauss smoothing`);

    const xyzDim = xDim * yDim * zDim;
    const volDst = new Uint8Array(xyzDim);
    // if (volDst === null) {
    //   return -10;
    // }

    // Fill gauss convolution matrix
    let weightSum = 0.0;
    let off = 0;
    for (let z = 0; z < side; z++) {
      const dz = z - gaussRadius;
      for (let y = 0; y < side; y++) {
        const dy = y - gaussRadius;
        for (let x = 0; x < side; x++) {
          const dx = x - gaussRadius;
          const dist2 = dx * dx + dy * dy + dz * dz;
          const w = 1.0 / Math.exp(dist2 * koefSpatial);
          this.m_gaussWeights[off] = w;
          weightSum += this.m_gaussWeights[off];
          off += 1;
        } // for (x)
      } // for (y)
    } // for (z)

    // Normalize gauss matrix
    const scale = 1.0 / weightSum;
    for (let x = 0; x < side3; x++) {
      this.m_gaussWeights[x] *= scale;
    }

    const xyDim = xDim * yDim;
    // process whole image using gauss matrix
    for (let z = 0; z < zDim; z++) {
      for (let y = 0; y < yDim; y++) {
        for (let x = 0; x < xDim; x++) {
          let sum = 0.0;
          let offConv = 0;
          for (let dz = -gaussRadius; dz <= +gaussRadius; dz++) {
            let zz = z + dz;
            zz = zz < 0 ? 0 : zz;
            zz = zz >= zDim ? zDim - 1 : zz;
            for (let dy = -gaussRadius; dy <= +gaussRadius; dy++) {
              let yy = y + dy;
              yy = yy < 0 ? 0 : yy;
              yy = yy >= yDim ? yDim - 1 : yy;
              for (let dx = -gaussRadius; dx <= +gaussRadius; dx++) {
                let xx = x + dx;
                xx = xx < 0 ? 0 : xx;
                xx = xx >= xDim ? xDim - 1 : xx;
                const w = this.m_gaussWeights[offConv];
                offConv += 1;
                const offImage = zz * xyDim + yy * xDim + xx;
                const val = volBuffer[offImage];
                sum += val * w;
              } // for (dx)
            } // for (dy)
          } // for (dz)
          let iSum = Math.floor(sum);
          const MAX_BYTE = 255;
          iSum = iSum <= MAX_BYTE ? iSum : MAX_BYTE;
          const offImage = z * xyDim + y * xDim + x;
          volDst[offImage] = iSum;
        } // for (x)
      } // for (y)
    } // for (z)

    // copy filtered volume back to source
    // volBuffer.set(volDst, 0);
    for (let i = 0; i < xyzDim; i++) {
      volBuffer[i] = volDst[i];
    }
    // console.log(`End Gauss smoothing`);
    return 1;
  }