def _doMorph(self):
        """Apply a gaussian blur and then a tophat."""
        tophatKernel = im.makeCircularKernel(self._featureRadius)

        morphed = []
        for image in self._images:
            scaled = im.forceRange(image, 0.0, 1.0) # scale pixel values to 0-1
            blurred = cv2.GaussianBlur(scaled, (0, 0), self._blurSigma)
            tophat = cv2.morphologyEx(blurred, cv2.MORPH_TOPHAT, tophatKernel)
            # maximize contrast by forcing the range to be 0-1 again
            morphed.append(im.forceRange(tophat, 0.0, 1.0))

        self._morphed = morphed
    def _findLocalMax(self):
        """Find the centers of particles by thresholding and dilating."""
        dilationKernel = im.makeCircularKernel(self._dilationRadius)

        maxed = []
        for image in self._morphed:
            # set pixels below morph thresh to 0
            threshed = stats.threshold(image, self._morphThreshold, newval=0.0)
            dilated = cv2.dilate(threshed, dilationKernel)
            # expThreshold is so named because the original algorithm 
            # originally exponentiated and then thresholded, which is the same
            # as flipping the sign and exponentiating the threshold.
            binary = (dilated - threshed) >= self._expThreshold
            maxed.append(binary)
        self._maxed = maxed
    def _findLocalMax(self):
        """Find the centers of particles by thresholding and dilating."""
        dilationKernel = im.makeCircularKernel(self._dilationRadius)

        self._maxed = im.createImageArray(self, "morphMax",
                                          dtype=np.bool,
                                          shape = self._morphed[0].shape,
                                          expectedrows=len(self._morphed))
        for image in self._morphed:
            # set pixels below morph thresh to 0
            threshed = stats.threshold(image, self._morphThreshold, newval=0.0)
            dilated = cv2.dilate(threshed, dilationKernel)
            # expThreshold is so named because the original algorithm 
            # originally exponentiated and then thresholded, which is the same
            # as flipping the sign and exponentiating the threshold.
            binary = (dilated - threshed) >= self._expThreshold
            self._maxed.append([binary])
        self._maxed.flush()