Esempio n. 1
0
    def _count_du(self, x, y, size=5, bg=None):
        wmrg = size // 4
        mmrg = 1 if bg is None else 0
        mask = ImageProc.bsphkern(size + 2 * mmrg)
        if bg is None:
            mask[0, :] = 0
            mask[-1, :] = 0
            mask[:, 0] = 0
            mask[:, -1] = 0
        mask = mask.astype(np.bool)
        mr = size // 2 + mmrg
        mn = size + 2 * mmrg

        h, w, _ = self.image.shape
        x, y = int(round(x)), int(round(y))
        if h - y + wmrg <= mr or w - x + wmrg <= mr or x + wmrg < mr or y + wmrg < mr:
            return zip([None] * 3, [None] * 3)

        win = self.image[max(0, y - mr):min(h, y + mr + 1),
                         max(0, x - mr):min(w, x + mr + 1), :].reshape((-1, 3))
        mx0, mx1 = -min(0, x - mr), mn - (max(w, x + mr + 1) - w)
        my0, my1 = -min(0, y - mr), mn - (max(h, y + mr + 1) - h)

        mask = mask[my0:my1, mx0:mx1].flatten()
        bg = np.mean(win[np.logical_not(mask), :],
                     axis=0) if bg is None else bg

        if False:
            tot = np.sum(win[mask, :], axis=0)
            tot_bg = bg * np.sum(mask)
            tot = np.max(np.array((tot, tot_bg)), axis=0)

            # tried to take into account thumbnail mean resizing after gamma correction,
            # also assuming no saturation of original pixels because of motion blur
            # => better results if tune Camera->emp_coef instead
            resizing_gain = (1 / self.resize_scale)**2
            g = self.applied_gamma

            # ([sum over i in n: (bg+s_i)**g] / n) ** (1/g)
            #    => cannot compensate for gamma correction as signal components not summable anymore,
            #       only possible if assume that only a single pixel has signal (or some known distribution of signal?)
            # signal in a single, non-saturating pixel (conflicting assumptions):
            adj_tot = (((tot - tot_bg + bg)**g * resizing_gain) -
                       (resizing_gain - 1) * bg**g)**(1 / g) - bg
            signal = adj_tot
        else:
            #signal = tot - tot_bg
            signal = np.clip(np.sum(win[mask, :] - bg, axis=0), 0, np.inf)

        return zip(signal, bg)
Esempio n. 2
0
    def _feature_detection_mask(self, image):
        _, mask = cv2.threshold(image, self.min_feature_intensity, 255,
                                cv2.THRESH_BINARY)
        kernel = ImageProc.bsphkern(round(6 * image.shape[0] / 512) * 2 + 1)

        # exclude asteroid limb from feature detection
        mask = cv2.erode(mask, ImageProc.bsphkern(7),
                         iterations=1)  # remove stars
        mask = cv2.dilate(mask, kernel,
                          iterations=1)  # remove small shadows inside asteroid
        mask = cv2.erode(mask, kernel, iterations=2)  # remove asteroid limb

        # exclude overexposed parts
        _, mask_oe = cv2.threshold(image, self.max_feature_intensity, 255,
                                   cv2.THRESH_BINARY)
        mask_oe = cv2.dilate(mask_oe, kernel, iterations=1)
        mask_oe = cv2.erode(mask_oe, kernel, iterations=1)
        mask[mask_oe > 0] = 0

        if 0:
            cv2.imshow('mask', ImageProc.overlay_mask(image, mask))
            cv2.waitKey()

        return mask
Esempio n. 3
0
    def calc_source_kernel(cams, spectrum_fn, patch_size, points=None):
        # detect source
        kernel = ImageProc.bsphkern(
            tuple(map(int, patch_size)) if '__iter__' in
            dir(patch_size) else int(patch_size))

        expected_bgr = np.zeros(3)
        for i, cam in enumerate(cams):
            ef, _ = Camera.electron_flux_in_sensed_spectrum_fn(cam.qeff_coefs,
                                                               spectrum_fn,
                                                               cam.lambda_min,
                                                               cam.lambda_max,
                                                               fast=False,
                                                               points=points)
            expected_bgr[i] = cam.gain * cam.aperture_area * cam.emp_coef * ef

        kernel = np.repeat(np.expand_dims(kernel, axis=2), 3,
                           axis=2) * expected_bgr
        return kernel
Esempio n. 4
0
    def detect_moon(self):
        x, y = tuple(int(v) for v in self.moon_loc)
        win = self.image[y - 24:y + 25, x - 29:x + 30, :]

        if 0:
            # TODO: what transformation would make this work?
            win = ImageProc.adjust_gamma(win / 662 * 1023,
                                         2.2,
                                         inverse=1,
                                         max_val=1023)

        h, w, s, c = *win.shape[0:2], 19, 18
        mask = np.zeros((h, w), dtype='uint8')
        mask[(h // 2 - s):(h // 2 + s + 1),
             (w // 2 - s):(w // 2 + s +
                           1)] = ImageProc.bsphkern(s * 2 + 1).astype('uint8')
        mask[0:c, :] = 0

        if SHOW_MEASURES:
            mask_img = (mask.reshape(
                (h, w, 1)) * np.array([255, 0, 0]).reshape(
                    (1, 1, 3))).astype('uint8')
            win_img = np.clip(win, 0, 255).astype('uint8')
            plt.imshow(np.flip(ImageProc.merge((mask_img, win_img)), axis=2))
            plt.show()

        mask = mask.flatten().astype('bool')
        n = np.sum(mask)
        measures = []
        for i, cam in enumerate(self.cam):
            raw_du = np.sum(win[:, :, i].flatten()[mask])
            bg_du = np.mean(win[:, :, i].flatten()[np.logical_not(mask)])
            du_count = raw_du - bg_du * n
            measures.append(MoonMeasure(self, i, du_count))
        self.measures = measures
        return measures
Esempio n. 5
0
    def detect_source(self, kernel, total_radiation=False):
        assert kernel.shape[0] % 2 and kernel.shape[
            1] % 2, 'kernel width and height must be odd numbers'
        kernel = self.gain * self.exposure * kernel
        fkernel = ImageProc.fuzzy_kernel(kernel, self.impulse_spread)
        method = [cv2.TM_CCORR_NORMED, cv2.TM_SQDIFF][0]
        corr = cv2.matchTemplate(self.image.astype(np.float32),
                                 fkernel.astype(np.float32), method)
        _, _, minloc, maxloc = cv2.minMaxLoc(
            corr)  # minval, maxval, minloc, maxloc
        loc = minloc if method in (cv2.TM_SQDIFF,
                                   cv2.TM_SQDIFF_NORMED) else maxloc
        loc_i = tuple(np.round(np.array(loc)).astype(np.int))

        if SHOW_LAB_MEASURES:
            sc = 1024 / self.image.shape[1]
            img = cv2.resize(self.image.astype(np.float), None, fx=sc,
                             fy=sc) / np.max(self.image)
            center = np.array(loc) + np.flip(fkernel.shape[:2]) / 2
            img = cv2.circle(
                img, tuple(np.round(center * sc).astype(np.int)),
                round((kernel.shape[0] - self.impulse_spread) / 2 * sc),
                [0, 0, 1.0])
            cv2.imshow('te', img)
            print('waiting...', end='', flush=True)
            cv2.waitKey()
            print('done')

        if True:
            # use result as a mask to calculate mean and variance
            kh, kw = np.array(fkernel.shape[:2]) // 2
            win = self.image[loc_i[1]:loc_i[1] + kh * 2 + 1,
                             loc_i[0]:loc_i[0] + kw * 2 + 1, :].reshape(
                                 (-1, 3))
            kernel_max = np.max(np.sum(kernel, axis=2))
            mask = np.sum(fkernel, axis=2) / kernel_max > 0.95
            mean = np.median(win[mask.flatten(), :], axis=0)
            std = np.std(win[mask.flatten(), :], axis=0)
            n = np.sum(mask)

            tmp = np.zeros(self.image.shape[:2])
            tmp[loc_i[1]:loc_i[1] + kh * 2 + 1,
                loc_i[0]:loc_i[0] + kw * 2 + 1] = mask
            img_m = tmp

        else:
            # calculate a correlation channel (over whole image)
            k = kernel.shape[0] // 2
            corr = cv2.matchTemplate(
                self.image.astype(np.float32),
                kernel[k:k + 1, k:k + 1, :].astype(np.float32), method)

            # calculate mean & variance of kernel area using corr channel
            win = corr[loc_i[1] - k:loc_i[1] + k + 1,
                       loc_i[0] - k:loc_i[0] + k + 1]
            corr_mean = np.mean(win)
            corr_std = np.std(win)

            # threshold using mean - sd
            _, mask = cv2.threshold(corr, corr_mean - corr_std, 1,
                                    cv2.THRESH_BINARY)

            # dilate & erode to remove inner spots
            krn1 = ImageProc.bsphkern(round(1.5 * corr.shape[0] / 512) * 2 + 1)
            krn2 = ImageProc.bsphkern(round(2 * corr.shape[0] / 512) * 2 + 1)
            mask = cv2.dilate(mask, krn1, iterations=1)  # remove holes
            mask = cv2.erode(mask, krn2, iterations=1)  # same size
            mask = mask.astype(np.bool)

            # use result as a mask to calculate mean and variance
            mean = np.mean(self.image.reshape((-1, 3))[mask.flatten()], axis=0)
            var = np.var(self.image.reshape((-1, 3))[mask.flatten()], axis=0)
            n = np.sum(mask)

        if self.debug:
            sc = 1024 / self.image.shape[1]
            img_m = np.repeat(np.atleast_3d(img_m.astype(np.uint8) * 127),
                              3,
                              axis=2)
            merged = ImageProc.merge(
                (self.image.astype(np.float32) / np.max(self.image),
                 img_m.astype(np.float32) / 255))
            img = cv2.resize(merged, None, fx=sc, fy=sc)
            cv2.imshow('te', img)
            arr_n, lims, _ = plt.hist(self.image[:, :, 1].flatten(),
                                      bins=np.max(self.image) + 1,
                                      log=True,
                                      histtype='step')
            plt.hist(win[mask.flatten(), 1].flatten(),
                     bins=np.max(self.image) + 1,
                     log=True,
                     histtype='step')
            x = np.linspace(0, np.max(win), np.max(win) + 1)
            i = list(np.logical_and(lims[1:] > mean[1], arr_n > 0)).index(True)
            plt.plot(x, arr_n[i] * np.exp(-((x - mean[1]) / std[1])**2))
            plt.ylim(1e-1, 1e6)
            plt.figure()
            plt.imshow(self.image[loc_i[1]:loc_i[1] + kh * 2 + 1,
                                  loc_i[0]:loc_i[0] + kw * 2 + 1, :] /
                       np.max(self.image))
            print('waiting (%.1f, %.1f)...' % (mean[1], std[1]),
                  end='',
                  flush=True)
            cv2.waitKey(1)
            plt.show()
            print('done')

        return LabMeasure(self, mean, std, n)