class DarkCurrentMap(Iteratives): ''' Averages given background images removing single time effects ''' def __init__(self, twoImages, noise_level_function=None, calcVariance=False, **kwargs): Iteratives.__init__(self, **kwargs) assert len(twoImages) > 1, 'need at least 2 images' self.det = SingleTimeEffectDetection(twoImages, noise_level_function, nStd=3, calcVariance=calcVariance) def addImg(self, img, raiseIfConvergence=False): self.det.addImage(img) if raiseIfConvergence: return self.checkConvergence(self.det.mma.var**0.5) def map(self): return self.det.mma.avg def uncertaintyMap(self): return self.det.mma.var**0.5 def uncertainty(self): return np.mean(self.det.mma.var)**0.5
def __init__(self, twoImages, noise_level_function=None, calcVariance=False, **kwargs): Iteratives.__init__(self, **kwargs) assert len(twoImages) > 1, 'need at least 2 images' self.det = SingleTimeEffectDetection(twoImages, noise_level_function, nStd=3, calcVariance=calcVariance)
def flatFieldFromCloseDistance2(images, bgImages=None, calcStd=False, nlf=None, nstd=6): ''' Same as [flatFieldFromCloseDistance]. Differences are: ... single-time-effect removal included ... returns the standard deviation of the image average [calcStd=True] Optional: ----------- calcStd -> set to True to also return the standard deviation nlf -> noise level function (callable) nstd -> artefact needs to deviate more than [nstd] to be removed ''' if len(images) > 1: # start with brightest images def fn(img): img = imread(img) s0, s1 = img.shape[:2] # rough approx. of image brightness: return -img[::s0 // 10, ::s1 // 10].min() images = sorted(images, key=lambda i: fn(i)) avgBg = getBackground2(bgImages, images[1]) i0 = imread(images[0], dtype=float) - avgBg i1 = imread(images[1], dtype=float) - avgBg if nlf is None: nlf = oneImageNLF(i0, i1)[0] det = SingleTimeEffectDetection( (i0, i1), nlf, nStd=nstd, calcVariance=calcStd) for i in images[1:]: i = imread(i) # exclude erroneously darker areas: thresh = det.noSTE - nlf(det.noSTE) * nstd mask = i > thresh # filter STE: det.addImage(i, mask) ma = det.noSTE else: ma = imread(images[0], dtype=float) - avgBg # fast artifact free maximum: mx = median_filter(ma[::10, ::10], 3).max() if calcStd: return ma / mx, det.mma.var**0.5 / mx return ma / mx
def __init__(self, twoImages, noise_level_function=None, calcVariance=False, **kwargs): Iteratives.__init__(self, **kwargs) assert len(twoImages) > 1, 'need at least 2 images' self.det = SingleTimeEffectDetection(twoImages, noise_level_function, nStd=3) self._map = MaskedMovingAverage(shape=twoImages[0].shape, calcVariance=calcVariance) self._map.update(self.det.noSTE)
def _correctDarkCurrent(self, image, exposuretime, bgImages, date): ''' open OR calculate a background image: f(t)=m*t+n ''' # either exposureTime or bgImages has to be given # if exposuretime is not None or bgImages is not None: print('... remove dark current') if bgImages is not None: if (type(bgImages) in (list, tuple) or (isinstance(bgImages, np.ndarray) and bgImages.ndim == 3)): if len(bgImages) > 1: # if multiple images are given: do STE removal: nlf = self.noise_level_function bg = SingleTimeEffectDetection( bgImages, nStd=4, noise_level_function=nlf).noSTE else: bg = imread(bgImages[0]) else: bg = imread(bgImages) else: bg = self.calcDarkCurrent(exposuretime, date) self.temp['bg'] = bg image -= bg
def fn(img, i0, i1): if remove_ste: ste = SingleTimeEffectDetection(img[i0:i1], save_ste_indices=show_changes, nStd=self.pNStd.value()) out.append(ste.noSTE) indices.append(ste.mask_STE) else: out.append(imgAverage(img[i0:i1])) names.append('img[%s:%s]' % (i0, i1))
def _correctDarkCurrent(self, image, exposuretime, bgImages, date): ''' open OR calculate a background image: f(t)=m*t+n ''' if bgImages is not None: if (type(bgImages) in (list, tuple) or (isinstance(bgImages, np.ndarray) and bgImages.ndim == 3)): #if multiple images are given: do STE removal: bg = SingleTimeEffectDetection( (imread(bgImages[0]), imread(bgImages[1])), nStd=4).noSTE else: bg = imread(bgImages) else: d = self.coeffs['dark current'] d = _getFromDate(d, date) #calculate bg image: offs, ascent = d[2] bg = offs + ascent * exposuretime mx = self.coeffs['max value'] with np.errstate(invalid='ignore'): bg[bg > mx] = mx image -= bg
def correct(self, images, bgImages=None, exposure_time=None, light_spectrum=None, threshold=0.1, keep_size=True, date=None, deblur=False, denoise=False): ''' exposure_time [s] date -> string e.g. '30. Nov 15' to get a calibration on from date -> {'dark current':'30. Nov 15', 'flat field':'15. Nov 15', 'lens':'14. Nov 15', 'noise':'01. Nov 15'} ''' print('CORRECT CAMERA ...') if isinstance(date, string_types) or date is None: date = { 'dark current': date, 'flat field': date, 'lens': date, 'noise': date, 'psf': date } if light_spectrum is None: try: light_spectrum = self.coeffs['light spectra'][0] except IndexError: pass # do we have multiple images? if (type(images) in (list, tuple) or (isinstance(images, np.ndarray) and images.ndim == 3 and images.shape[-1] not in (3, 4) # is color )): if len(images) > 1: # 0.NOISE n = self.coeffs['noise'] if self.noise_level_function is None and len(n): n = _getFromDate(n, date['noise'])[2] self.noise_level_function = lambda x: NoiseLevelFunction.boundedFunction( x, *n) print('... remove single-time-effects from images ') # 1. STE REMOVAL ONLY IF >=2 IMAGES ARE GIVEN: ste = SingleTimeEffectDetection( images, nStd=4, noise_level_function=self.noise_level_function) image = ste.noSTE if self.noise_level_function is None: self.noise_level_function = ste.noise_level_function else: image = np.asfarray(imread(images[0], dtype=np.float)) else: image = np.asfarray(imread(images, dtype=np.float)) self._checkShape(image) self.last_light_spectrum = light_spectrum self.last_img = image # 2. BACKGROUND REMOVAL try: self._correctDarkCurrent(image, exposure_time, bgImages, date['dark current']) except Exception as errm: print('Error: %s' % errm) # 3. VIGNETTING/SENSITIVITY CORRECTION: try: self._correctVignetting(image, light_spectrum, date['flat field']) except Exception as errm: print('Error: %s' % errm) # 4. REPLACE DECECTIVE PX WITH MEDIAN FILTERED FALUE if threshold > 0: print('... remove artefacts') try: image = self._correctArtefacts(image, threshold) except Exception as errm: print('Error: %s' % errm) # 5. DEBLUR if deblur: print('... remove blur') try: image = self._correctBlur(image, light_spectrum, date['psf']) except Exception as errm: print('Error: %s' % errm) # 5. LENS CORRECTION: try: image = self._correctLens(image, light_spectrum, date['lens'], keep_size) except TypeError: 'Error: no lens calibration found' except Exception as errm: print('Error: %s' % errm) # 6. Denoise if denoise: print('... denoise ... this might take some time') image = self._correctNoise(image) print('DONE') return image
def correct(self, image1, image2=None, bgImages=None, exposure_time=None, light_spectrum=None, threshold=0.2, keep_size=True, date=None, deblur=True): ''' exposure_time [s] date -> string e.g. '30. Nov 15' to get a calibration on from date -> {'dark current':'30. Nov 15', 'flat field':'15. Nov 15', 'lens':'14. Nov 15', 'noise':'01. Nov 15'} ''' if isinstance(date, basestring) or date is None: date = { 'dark current': date, 'flat field': date, 'lens': date, 'noise': date, 'psf': date } if light_spectrum is None: light_spectrum = self.coeffs['light spectra'][0] assert exposure_time is not None or bgImages is not None, 'either exposureTime or bgImages has to be given' #0.NOISE n = self.coeffs['noise'] if self.noise_level_function is None and len(n): n = _getFromDate(n, date['noise'])[2] self.noise_level_function = lambda x: NoiseLevelFunction.boundedFunction( x, *n) #1. STE REMOVAL ONLY IF 2 IMAGES ARE GIVEN: image1orig = image1 image1 = np.asfarray(imread(image1)) self._checkShape(image1) if image2 is None: image = image1 if id(image1orig) == id(image): image = image.copy() else: image2 = np.asfarray(imread(image2)) self._checkShape(image2) print('... remove single-time-effects') ste = SingleTimeEffectDetection( (image1, image2), nStd=4, noise_level_function=self.noise_level_function) image = ste.noSTE if self.noise_level_function is None: self.noise_level_function = ste.noise_level_function self.last_light_spectrum = light_spectrum self.last_img = image #2. BACKGROUND REMOVAL print('... remove background') self._correctDarkCurrent(image, exposure_time, bgImages, date['dark current']) #3. VIGNETTING/SENSITIVITY CORRECTION: print('... remove vignetting and sensitivity') self._correctVignetting(image, light_spectrum, date['flat field']) #4. REPLACE DECECTIVE PX WITH MEDIAN FILTERED FALUE print('... remove artefacts') self._correctArtefacts(image, threshold) #5. DEBLUR if deblur: print('... remove blur') image = self._correctBlur(image, light_spectrum, date['psf']) #5. LENS CORRECTION: print('... correct lens distortion') image = self._correctLens(image, light_spectrum, date['lens'], keep_size) print('DONE') return image