For each block in the image, calculate the average black point using a 5x5 grid
of the blocks around it. Also handles the corner cases (fractional blocks are computed based
on the last pixels in the row/column which are also used in the previous block).
18220
private static void calculateThresholdForBlock(byte[] luminances,
                                                 int subWidth,
                                                 int subHeight,
                                                 int width,
                                                 int height,
                                                 int[][] blackPoints,
                                                 BitMatrix matrix) {
    int maxYOffset = height - BLOCK_SIZE;
    int maxXOffset = width - BLOCK_SIZE;
    for (int y = 0; y < subHeight; y++) {
      int yoffset = y << BLOCK_SIZE_POWER;
      if (yoffset > maxYOffset) {
        yoffset = maxYOffset;
      }
      int top = cap(y, 2, subHeight - 3);
      for (int x = 0; x < subWidth; x++) {
        int xoffset = x << BLOCK_SIZE_POWER;
        if (xoffset > maxXOffset) {
          xoffset = maxXOffset;
        }
        int left = cap(x, 2, subWidth - 3);
        int sum = 0;
        for (int z = -2; z <= 2; z++) {
          int[] blackRow = blackPoints[top + z];
          sum += blackRow[left - 2] + blackRow[left - 1] + blackRow[left] + blackRow[left + 1] + blackRow[left + 2];
        }
        int average = sum / 25;
        thresholdBlock(luminances, xoffset, yoffset, average, width, matrix);
      }
    }
  }
759638
@Override
  public BitMatrix getBlackMatrix() throws NotFoundException {
    LuminanceSource source = getLuminanceSource();
    int width = source.getWidth();
    int height = source.getHeight();
    BitMatrix matrix = new BitMatrix(width, height);

    // Quickly calculates the histogram by sampling four rows from the image. This proved to be
    // more robust on the blackbox tests than sampling a diagonal as we used to do.
    initArrays(width);
    int[] localBuckets = buckets;
    for (int y = 1; y < 5; y++) {
      int row = height * y / 5;
      byte[] localLuminances = source.getRow(row, luminances);
      int right = (width * 4) / 5;
      for (int x = width / 5; x < right; x++) {
        int pixel = localLuminances[x] & 0xff;
        localBuckets[pixel >> LUMINANCE_SHIFT]++;
      }
    }
    int blackPoint = estimateBlackPoint(localBuckets);

    // We delay reading the entire image luminance until the black point estimation succeeds.
    // Although we end up reading four rows twice, it is consistent with our motto of
    // "fail quickly" which is necessary for continuous scanning.
    byte[] localLuminances = source.getMatrix();
    for (int y = 0; y < height; y++) {
      int offset = y * width;
      for (int x = 0; x < width; x++) {
        int pixel = localLuminances[offset + x] & 0xff;
        if (pixel < blackPoint) {
          matrix.set(x, y);
        }
      }
    }

    return matrix;
  }
1115165
def find_local_maxima(self, input_grid):
        
        pixels, q_data = self.quantize(input_grid)
        centers = OrderedDict()
        for p in pixels.keys():
            centers[p] = []
        marked = np.ones(q_data.shape, dtype=int) * self.UNMARKED
        MIN_INFL = int(np.round(1 + 0.5 * np.sqrt(self.max_size)))
        MAX_INFL = 2 * MIN_INFL
        marked_so_far = []
        # Find the maxima. These are high-values with enough clearance
        # around them.
        # Work from high to low bins. The pixels in the highest bin mark their
        # neighborhoods first. If you did it from low to high the lowest maxima
        # would mark their neighborhoods first and interfere with the identification of higher maxima.
        for b in sorted(pixels.keys(),reverse=True):
            # Square starts large with high intensity bins and gets smaller with low intensity bins.
            infl_dist = MIN_INFL + int(np.round(float(b) / self.max_bin * (MAX_INFL - MIN_INFL)))
            for p in pixels[b]:
                if marked[p] == self.UNMARKED:
                    ok = False
                    del marked_so_far[:]
                    # Temporarily mark unmarked points in square around point (keep track of them in list marked_so_far).
                    # If none of the points in square were marked already from a higher intensity center, 
                    # this counts as a new center and ok=True and points will remain marked.
                    # Otherwise ok=False and marked points that were previously unmarked will be unmarked.
                    for (i, j), v in np.ndenumerate(marked[p[0] - infl_dist:p[0] + infl_dist + 1,
                                                    p[1] - infl_dist:p[1]+ infl_dist + 1]):
                        if v == self.UNMARKED:
                            ok = True
                            marked[i - infl_dist + p[0],j - infl_dist + p[1]] = b
                           
                            marked_so_far.append((i - infl_dist + p[0],j - infl_dist + p[1]))
                        else:
                            # neighborhood already taken
                            ok = False
                            break
                    # ok if point and surrounding square were not marked already.
                    if ok:
                        # highest point in its neighborhood
                        centers[b].append(p)
                    else:
                        for m in marked_so_far:
                            marked[m] = self.UNMARKED
        # Erase marks and start over. You have a list of centers now.
        marked[:, :] = self.UNMARKED
        deferred_from_last = []
        deferred_to_next = []
        # delta (int): maximum number of increments the cluster is allowed to range over. Larger d results in clusters over larger scales.
        for delta in range(0, self.delta + 1):
            # Work from high to low bins.
            for b in sorted(centers.keys(), reverse=True):
                bin_lower = b - delta
                deferred_from_last[:] = deferred_to_next[:]
                del deferred_to_next[:]
                foothills = []
                n_centers = len(centers[b])
                tot_centers = n_centers + len(deferred_from_last)
                for i in range(tot_centers):
                    # done this way to minimize memory overhead of maintaining two lists
                    if i < n_centers:
                        center = centers[b][i]
                    else:
                        center = deferred_from_last[i - n_centers]
                    if bin_lower < 0:
                        bin_lower = 0
                    if marked[center] == self.UNMARKED:
                        captured = self.set_maximum(q_data, marked, center, bin_lower, foothills)
                        if not captured:
                            # decrement to lower value to see if it'll get big enough
                            deferred_to_next.append(center)
                        else:
                            pass
                # this is the last one for this bin
                self.remove_foothills(q_data, marked, b, bin_lower, centers, foothills)
            del deferred_from_last[:]
            del deferred_to_next[:]
        return marked
411340
private void calc() {
        int hMin = (int) ((this.cImage.getHeight()) / 4.0);
        int hMax = (int) ((this.cImage.getHeight()) * 3.0 / 4.0);
        init();

        for (int y = hMin; y < hMax; y++) {
            for (int x = 1; x < (this.cImage.getWidth() - 2); x++) {
                // only lower edges are considered
                if (ImageUtil.isBlack(this.cImage, x, y)) {
                    if (!ImageUtil.isBlack(this.cImage, x, y + 1)) {
                        calc(x, y);
                    }
                }
            }
        }

    }
113325
@Override
	public void process() {
		locations.reset();
		descriptions.reset();

		int stepBlockPixelsX = pixelsPerCell *stepBlock;
		int stepBlockPixelsY = pixelsPerCell *stepBlock;

		int maxY = derivX.height - pixelsPerCell * cellsPerBlockY + 1;
		int maxX = derivX.width - pixelsPerCell * cellsPerBlockX + 1;

		for (int y = 0; y < maxY; y += stepBlockPixelsY ) {
			for (int x = 0; x < maxX; x += stepBlockPixelsX ) {
				TupleDesc_F64 d = descriptions.grow();
				Arrays.fill(d.value,0);
				histogram = d.value;

				for (int cellRow = 0; cellRow < cellsPerBlockY; cellRow++) {
					int blockPixelRow = cellRow* pixelsPerCell;
					for (int cellCol = 0; cellCol < cellsPerBlockX; cellCol++) {
						int blockPixelCol = cellCol* pixelsPerCell;

						computeCellHistogram(x+blockPixelCol, y+blockPixelRow, cellCol, cellRow);
					}
				}

				DescribeSiftCommon.normalizeDescriptor(d,0.2);
				locations.grow().set(x,y);
			}
		}
	}
98485
function dither(cb) {
  const rgb565Matrix = [1, 9, 3, 11, 13, 5, 15, 7, 4, 12, 2, 10, 16, 8, 14, 6];
  this.scanQuiet(0, 0, this.bitmap.width, this.bitmap.height, function(
    x,
    y,
    idx
  ) {
    const thresholdId = ((y & 3) << 2) + (x % 4);
    const dither = rgb565Matrix[thresholdId];
    this.bitmap.data[idx] = Math.min(this.bitmap.data[idx] + dither, 0xff);
    this.bitmap.data[idx + 1] = Math.min(
      this.bitmap.data[idx + 1] + dither,
      0xff
    );
    this.bitmap.data[idx + 2] = Math.min(
      this.bitmap.data[idx + 2] + dither,
      0xff
    );
  });

  if (isNodePattern(cb)) {
    cb.call(this, null, this);
  }

  return this;
}
150133
protected void computeWeightBlockPixels() {

		int rows = cellsPerBlockY*pixelsPerCell;
		int cols = cellsPerBlockX*pixelsPerCell;

		weights = new double[ rows*cols ];

		double offsetRow=0,offsetCol=0;
		int radiusRow=rows/2,radiusCol=cols/2;
		if( rows%2 == 0 ) {
			offsetRow = 0.5;
		}
		if( cols%2 == 0 ) {
			offsetCol = 0.5;
		}

		// use linear seperability of a Gaussian to make computation easier
		// sigma is 1/2 the width along each axis
		int index = 0;
		for (int row = 0; row < rows; row++) {
			double drow = row-radiusRow+offsetRow;
			double pdfRow = UtilGaussian.computePDF(0, radiusRow, drow);

			for (int col = 0; col < cols; col++) {
				double dcol = col-radiusCol+offsetCol;
				double pdfCol = UtilGaussian.computePDF(0, radiusCol, dcol);

				weights[index++] = pdfCol*pdfRow;
			}
		}
		// normalize so that the largest value is 1.0
		double max = 0;
		for (int i = 0; i < weights.length; i++) {
			if( weights[i] > max ) {
				max = weights[i];
			}
		}
		for (int i = 0; i < weights.length; i++) {
			weights[i] /= max;
		}
	}
466692
def calibrate(self, board_size=(8, 6), method='Chessboard', images=[],
                  max_images=100, sensorSize_mm=None,
                  detect_sensible=True):
        '''
        
        '''
        self._coeffs = {}
        self.opts = {'foundPattern': [],  # whether pattern could be found for image
                     'size': board_size,
                     'imgs': [],  # list of either npArrsays or img paths
                     # list or 2d coords. of found pattern features (e.g.
                     # chessboard corners)
                     'imgPoints': []
                     }

        self._detect_sensible = detect_sensible

        self.method = {'Chessboard': self._findChessboard,
                       'Symmetric circles': self._findSymmetricCircles,
                       'Asymmetric circles': self._findAsymmetricCircles,
                       'Manual': None
                       # TODO: 'Image grid':FindGridInImage
                       }[method]

        self.max_images = max_images
        self.findCount = 0
        self.apertureSize = sensorSize_mm

        self.objp = self._mkObjPoints(board_size)

        if method == 'Asymmetric circles':
            # this pattern have its points (every 2. row) displaced, so:
            i = self.objp[:, 1] % 2 == 1
            self.objp[:, 0] *= 2
            self.objp[i, 0] += 1

        # Arrays to store object points and image points from all the images.
        self.objpoints = []  # 3d point in real world space
        # self.imgpoints = [] # 2d points in image plane.
        self.mapx, self.mapy = None, None

        # from matplotlib import pyplot as plt
        for n, i in enumerate(images):
            print('working on image %s' % n)
            if self.addImg(i):
                print('OK')
577270
def display_bounding_boxes(img, blocks, alternatecolors=False, color=Color("blue")):
    
    draw = Drawing()
    draw.fill_color = Color("rgba(0, 0, 0, 0)")
    draw.stroke_color = color
    for block in blocks:
        top, left, bottom, right = block[-4:]
        if alternatecolors:
            draw.stroke_color = Color(
                "rgba({},{},{}, 1)".format(
                    str(np.random.randint(255)),
                    str(np.random.randint(255)),
                    str(np.random.randint(255)),
                )
            )
        draw.rectangle(
            left=float(left), top=float(top), right=float(right), bottom=float(bottom)
        )
        draw(img)
    display(img)
724656
protected void computeHistogramBorder(T image, RectangleRotate_F32 region) {
		for( int i = 0; i < samplePts.size(); i++ ) {
			Point2D_F32 p = samplePts.get(i);

			squareToImageSample(p.x, p.y, region);

			// make sure its inside the image
			if( !BoofMiscOps.checkInside(image, imageX, imageY)) {
				sampleHistIndex[ i ] = -1;
			} else {
				// use the slower interpolation which can handle the border
				interpolate.get(imageX, imageY, value);

				int indexHistogram = computeHistogramBin(value);

				sampleHistIndex[ i ] = indexHistogram;
				histogram[indexHistogram] += weights[i];
			}
		}
	}
560221
def calculate_bbox_area(bbox, rows, cols):
    """"""
    bbox = denormalize_bbox(bbox, rows, cols)
    x_min, y_min, x_max, y_max = bbox[:4]
    area = (x_max - x_min) * (y_max - y_min)
    return area
121610
@Override
	public void compute(float x, float y, Point2D_F32 out) {
		float sum = 0;

		float radial[] = params.radial;
		float t1 = params.t1, t2 = params.t2;

		// out is undistorted normalized image coordinate
		out.x = a11*x + a12*y + a13;
		out.y = a22*y + a23;

		float r2 = out.x * out.x + out.y * out.y;
		float ri2 = r2;

		for (int i = 0; i < radial.length; i++) {
			sum += radial[i] * ri2;
			ri2 *= r2;
		}

		float tx = 2 * t1 * out.x * out.y + t2 * (r2 + 2 * out.x * out.x);
		float ty = t1 * (r2 + 2 * out.y * out.y) + 2 * t2 * out.x * out.y;

		// now compute the distorted normalized image coordinate
		out.x = out.x*(1 + sum) + tx;
		out.y = out.y*(1 + sum) + ty;
	}
191889
@Override
  public BitMatrix getBlackMatrix() throws NotFoundException {
    if (matrix != null) {
      return matrix;
    }
    LuminanceSource source = getLuminanceSource();
    int width = source.getWidth();
    int height = source.getHeight();
    if (width >= MINIMUM_DIMENSION && height >= MINIMUM_DIMENSION) {
      byte[] luminances = source.getMatrix();
      int subWidth = width >> BLOCK_SIZE_POWER;
      if ((width & BLOCK_SIZE_MASK) != 0) {
        subWidth++;
      }
      int subHeight = height >> BLOCK_SIZE_POWER;
      if ((height & BLOCK_SIZE_MASK) != 0) {
        subHeight++;
      }
      int[][] blackPoints = calculateBlackPoints(luminances, subWidth, subHeight, width, height);

      BitMatrix newMatrix = new BitMatrix(width, height);
      calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, newMatrix);
      matrix = newMatrix;
    } else {
      // If the image is too small, fall back to the global histogram approach.
      matrix = super.getBlackMatrix();
    }
    return matrix;
  }
932704
def calc_fwhm(img, region, fexpand=3, axis=0):
    """"""

    # We compute know the FWHM of the slit
    # Given the computed position of the slit
    # Expand 'fexpand' pixels around
    # and cut an slice in the median filtered image

    xpregion = expand_region(region, fexpand, fexpand)
    cslit = img[xpregion]

    # Collapse it
    pslit = cslit.mean(axis=axis)

    # Estimate the background as a flat line
    # starting in pslit[0] and ending in pslit[-1]
    x2 = len(pslit)
    y1, y2 = pslit[0], pslit[-1]
    mslope = (y2-y1) / x2
    # background estimation
    backstim = mslope*numpy.arange(x2) + y1

    # We subtract background
    qslit = pslit-backstim
    # and find the pixel of the maximum
    pidx = numpy.argmax(qslit)
    peak, fwhm = fmod.compute_fwhm_1d_simple(qslit, pidx)
    return fwhm
1202010
protected void computeClusterDistance() {
		for( int i = 0; i < pixels.size; i++ ) {
			pixels.data[i].reset();
		}

		for( int i = 0; i < clusters.size && !stopRequested; i++ ) {
			Cluster c = clusters.data[i];

			// compute search bounds
			int centerX = (int)(c.x + 0.5f);
			int centerY = (int)(c.y + 0.5f);

			int x0 = centerX - gridInterval; int x1 = centerX + gridInterval + 1;
			int y0 = centerY - gridInterval; int y1 = centerY + gridInterval + 1;

			if( x0 < 0 ) x0 = 0;
			if( y0 < 0 ) y0 = 0;
			if( x1 > input.width ) x1 = input.width;
			if( y1 > input.height ) y1 = input.height;

			for( int y = y0; y < y1; y++ ) {
				int indexPixel = y*input.width + x0;
				int indexInput = input.startIndex + y*input.stride + x0;

				int dy = y-centerY;

				for( int x = x0; x < x1; x++ ) {
					int dx = x-centerX;

					float distanceColor = colorDistance(c.color,indexInput++);
					float distanceSpacial = dx*dx + dy*dy;
					pixels.data[indexPixel++].add(c,distanceColor + adjustSpacial*distanceSpacial);
				}
			}
		}
	}
306395
def matrix_to_blockmatrix(self, blocksize):
        
        if self.get_width() % blocksize or self.get_height() % blocksize:
            raise ValueError("Number of rows and columns have to be evenly dividable by blocksize")
        selfBlocks = []
        for columnIndex in range(0, self.get_width() - 1, blocksize):
            for rowIndex in range(0, self.get_height() - 1, blocksize):
                currentBlock = []
                for blockRows in self.get_array(False)[columnIndex:columnIndex + blocksize]:
                    currentBlock += blockRows[rowIndex:rowIndex + blocksize]
                selfBlocks.append(Matrix(blocksize, blocksize, currentBlock, rowBased=False))
        return Matrix(self.get_width() / blocksize, self.get_height() / blocksize, selfBlocks, rowBased=False)
137716
@Override
  public BitArray getBlackRow(int y, BitArray row) throws NotFoundException {
    LuminanceSource source = getLuminanceSource();
    int width = source.getWidth();
    if (row == null || row.getSize() < width) {
      row = new BitArray(width);
    } else {
      row.clear();
    }

    initArrays(width);
    byte[] localLuminances = source.getRow(y, luminances);
    int[] localBuckets = buckets;
    for (int x = 0; x < width; x++) {
      localBuckets[(localLuminances[x] & 0xff) >> LUMINANCE_SHIFT]++;
    }
    int blackPoint = estimateBlackPoint(localBuckets);

    if (width < 3) {
      // Special case for very small images
      for (int x = 0; x < width; x++) {
        if ((localLuminances[x] & 0xff) < blackPoint) {
          row.set(x);
        }
      }
    } else {
      int left = localLuminances[0] & 0xff;
      int center = localLuminances[1] & 0xff;
      for (int x = 1; x < width - 1; x++) {
        int right = localLuminances[x + 1] & 0xff;
        // A simple -1 4 -1 box filter with a weight of 2.
        if (((center * 4) - left - right) / 2 < blackPoint) {
          row.set(x);
        }
        left = center;
        center = right;
      }
    }
    return row;
  }