def __getattr__(self, attribute): """ Reimplements the :meth:`MutableSequence.__getattr__` method. Parameters ---------- attribute : unicode Attribute to retrieve the value. Returns ------- object Attribute value. """ try: return self.__dict__[attribute] except KeyError: if hasattr(Image, attribute): value = [getattr(image, attribute) for image in self] if attribute == 'data': return tstack(value) else: return tuple(value) elif hasattr(Metadata, attribute): value = [getattr(image.metadata, attribute) for image in self] return np.asarray(value) else: raise AttributeError( "'{0}' object has no attribute '{1}'".format( self.__class__.__name__, attribute))
def camera_response_functions_Debevec1997(image_stack, s=samples_Grossberg2003, samples=1000, l=30, w=weighting_function_Debevec1997, n=256, normalise=True): """ Returns the camera response functions for given image stack using Debevec (1997) method. Image channels are sampled with :math:`s` sampling function and the output samples are passed to :func:`g_solve`. Parameters ---------- image_stack : ImageStack Stack of single channel or multi-channel floating point images. s : callable, optional Sampling function :math:`s`. samples : int, optional Samples count per images. l : numeric, optional :math:`\lambda` smoothing term. w : callable, optional Weighting function :math:`w`. n : int, optional :math:`n` constant. normalise : bool, optional Enables the camera response functions normalisation. Uncertain camera response functions values resulting from :math:`w` function are set to zero. Returns ------- ndarray Camera response functions :math:`g(z)`. """ samples = s(image_stack.data, samples, n) L_l = np.log(average_luminance(image_stack.f_number, image_stack.exposure_time, image_stack.iso)) crfs = np.exp(tstack(np.array([g_solve(samples[..., x], L_l, l, w, n)[0] for x in range(samples.shape[-1])]))) if normalise: # TODO: Investigate if the normalisation value should account for the # percentage of uncertain camera response functions values or be # correlated to it and scaled accordingly. As an alternative of setting # the uncertain camera response functions values to zero, it would be # interesting to explore extrapolation as the camera response functions # are essentially smooth. It is important to note that camera sensors # are usually acting non linearly when reaching saturation level. crfs[w(np.linspace(0, 1, crfs.shape[0])) == 0] = 0 crfs /= np.max(crfs, axis=0) return crfs
def chromaticity_diagram_visual( samples=256, cmfs='CIE 1931 2 Degree Standard Observer', transformation='CIE 1931', parent=None): """ Creates a chromaticity diagram visual based on :class:`colour_analysis.visuals.Primitive` class. Parameters ---------- samples : int, optional Inner samples count used to construct the chromaticity diagram triangulation. cmfs : unicode, optional Standard observer colour matching functions used for the chromaticity diagram boundaries. transformation : unicode, optional {'CIE 1931', 'CIE 1960 UCS', 'CIE 1976 UCS'} Chromaticity diagram transformation. parent : Node, optional Parent of the chromaticity diagram in the `SceneGraph`. Returns ------- Primitive Chromaticity diagram visual. """ cmfs = get_cmfs(cmfs) illuminant = DEFAULT_PLOTTING_ILLUMINANT XYZ_to_ij = ( CHROMATICITY_DIAGRAM_TRANSFORMATIONS[transformation]['XYZ_to_ij']) ij_to_XYZ = ( CHROMATICITY_DIAGRAM_TRANSFORMATIONS[transformation]['ij_to_XYZ']) ij_c = XYZ_to_ij(cmfs.values, illuminant) triangulation = Delaunay(ij_c, qhull_options='QJ') samples = np.linspace(0, 1, samples) ii, jj = np.meshgrid(samples, samples) ij = tstack((ii, jj)) ij = np.vstack((ij_c, ij[triangulation.find_simplex(ij) > 0])) ij_p = np.hstack((ij, np.full((ij.shape[0], 1), 0))) triangulation = Delaunay(ij, qhull_options='QJ') RGB = normalise(XYZ_to_sRGB(ij_to_XYZ(ij, illuminant), illuminant), axis=-1) diagram = Primitive(vertices=ij_p, faces=triangulation.simplices, vertex_colours=RGB, parent=parent) return diagram
def test_multi_signal_copy_operations(): domain = np.arange(0, 1000, 100) range_1 = np.linspace(1, 10, domain.size) range_2 = np.linspace(1, 10, domain.size) + 1 range_3 = np.linspace(1, 10, domain.size) + 2 cms1 = MultiSignal(tstack((domain, range_1, range_2, range_3))) cms2 = cms1.copy() assert id(cms1) != id(cms2)
def chromaticity_diagram_visual(samples=256, cmfs='CIE 1931 2 Degree Standard Observer', transformation='CIE 1931', parent=None): """ Creates a chromaticity diagram visual based on :class:`colour_analysis.visuals.Primitive` class. Parameters ---------- samples : int, optional Inner samples count used to construct the chromaticity diagram triangulation. cmfs : unicode, optional Standard observer colour matching functions used for the chromaticity diagram boundaries. transformation : unicode, optional **{'CIE 1931', 'CIE 1960 UCS', 'CIE 1976 UCS'}**, Chromaticity diagram transformation. parent : Node, optional Parent of the chromaticity diagram in the `SceneGraph`. Returns ------- Primitive Chromaticity diagram visual. """ cmfs = get_cmfs(cmfs) illuminant = DEFAULT_PLOTTING_ILLUMINANT XYZ_to_ij = ( CHROMATICITY_DIAGRAM_TRANSFORMATIONS[transformation]['XYZ_to_ij']) ij_to_XYZ = ( CHROMATICITY_DIAGRAM_TRANSFORMATIONS[transformation]['ij_to_XYZ']) ij_c = XYZ_to_ij(cmfs.values, illuminant) triangulation = Delaunay(ij_c, qhull_options='QJ') samples = np.linspace(0, 1, samples) ii, jj = np.meshgrid(samples, samples) ij = tstack((ii, jj)) ij = np.vstack((ij_c, ij[triangulation.find_simplex(ij) > 0])) ij_p = np.hstack((ij, np.full((ij.shape[0], 1), 0, DEFAULT_FLOAT_DTYPE))) triangulation = Delaunay(ij, qhull_options='QJ') RGB = normalise_maximum( XYZ_to_sRGB(ij_to_XYZ(ij, illuminant), illuminant), axis=-1) diagram = Primitive( vertices=ij_p, faces=triangulation.simplices, vertex_colours=RGB, parent=parent) return diagram
def __repr__(self): try: representation = repr(tstack((self.domain, self.range))) representation = representation.replace('array', self.__class__.__name__) representation = representation.replace(' [', '{0}['.format( ' ' * (len(self.__class__.__name__) + 2))) return representation except TypeError: return super(Signal, self).__repr__()
def __repr__(self): try: representation = repr(tstack((self.domain, self.range))) representation = representation.replace('array', self.__class__.__name__) representation = representation.replace( ' [', '{0}['.format(' ' * (len(self.__class__.__name__) + 2))) return representation except TypeError: return super(Signal, self).__repr__()
def __create_image(self): """ Creates the image used by the *Image View* according to :attr:`GamutView.__display_input_colourspace_out_of_gamut`, :attr:`GamutView.__display_correlate_colourspace_out_of_gamut`, :attr:`GamutView.__display_out_of_pointer_gamut` and :attr:`GamutView.__display_hdr_colours` attributes values. Returns ------- ndarray Image """ image = np.copy(self.__image) has_overlay = False if (self.__display_input_colourspace_out_of_gamut or self.__display_correlate_colourspace_out_of_gamut): image[image >= 0] = 0 image[image < 0] = 1 has_overlay = True if self.__display_correlate_colourspace_out_of_gamut: image = RGB_to_RGB(image, RGB_COLOURSPACES[self.__input_colourspace], RGB_COLOURSPACES[self.__correlate_colourspace]) has_overlay = True if self.__display_out_of_pointer_gamut: colourspace = RGB_COLOURSPACES[self.__input_colourspace] image = is_within_pointer_gamut( RGB_to_XYZ(image, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix)).astype(int) # TODO: Investigate why stacking implies that image needs to be # inverted. image = 1 - tstack((image, image, image)) has_overlay = True if self.__display_hdr_colours: image[image <= 1] = 0 # has_overlay = True if self.__image_overlay and has_overlay: image = self.__image + image oecf = RGB_COLOURSPACES[DEFAULT_OECF].transfer_function return oecf(image)
def test_masks_CFA_Bayer(self): """ Tests :func:`colour_demosaicing.bayer.masks.masks_CFA_Bayer` definition. """ for pattern in ('RGGB', 'BGGR', 'GRBG', 'GBRG'): np.testing.assert_almost_equal( colour.tstack(masks_CFA_Bayer((8, 8), pattern)), colour.read_image( str(os.path.join(BAYER_DIRECTORY, '{0}_Masks.exr'.format(pattern)))), decimal=7)
def _create_image(self): """ Creates the image used by the *Image View* according to :attr:`GamutView._display_input_colourspace_out_of_gamut`, :attr:`GamutView._display_correlate_colourspace_out_of_gamut`, :attr:`GamutView._display_out_of_pointer_gamut` and :attr:`GamutView._display_hdr_colours` attributes values. Returns ------- ndarray Image """ image = np.copy(self._image) has_overlay = False if (self._display_input_colourspace_out_of_gamut or self._display_correlate_colourspace_out_of_gamut): image[image >= 0] = 0 image[image < 0] = 1 has_overlay = True if self._display_correlate_colourspace_out_of_gamut: image = RGB_to_RGB(image, RGB_COLOURSPACES[self._input_colourspace], RGB_COLOURSPACES[self._correlate_colourspace]) has_overlay = True if self._display_out_of_pointer_gamut: colourspace = RGB_COLOURSPACES[self._input_colourspace] image = is_within_pointer_gamut( RGB_to_XYZ(image, colourspace.whitepoint, colourspace.whitepoint, colourspace.RGB_to_XYZ_matrix)).astype(int) # TODO: Investigate why stacking implies that image needs to be # inverted. image = 1 - tstack((image, image, image)) has_overlay = True if self._display_hdr_colours: image[image <= 1] = 0 # has_overlay = True if self._image_overlay and has_overlay: image = self._image + image oecf = RGB_COLOURSPACES[DEFAULT_ENCODING_CCTF].encoding_cctf return oecf(image)
def test_multi_signal_oject_initialisation(): domain = np.arange(0, 1000, 100) range_1 = np.linspace(1, 10, domain.size) range_2 = np.linspace(1, 10, domain.size) + 1 range_3 = np.linspace(1, 10, domain.size) + 2 cms1 = MultiSignal(tstack((domain, range_1, range_2, range_3))) np.testing.assert_array_equal(cms1.range, tstack((range_1, range_2, range_3))) np.testing.assert_array_equal(cms1.domain, domain) cms2 = MultiSignal(range_1) np.testing.assert_array_equal(cms2.range, range_1[:, np.newaxis]) np.testing.assert_array_equal(cms2.domain, np.linspace(0, 1, domain.size)) cms3 = MultiSignal(range_1, labels=['My Label']) assert list(cms3.signals.keys()) == ['My Label'] cms4 = MultiSignal( tstack((range_1, range_2, range_3)), domain / 1000, ('a', 'b', 'c')) np.testing.assert_array_equal(cms4.range, tstack((range_1, range_2, range_3))) np.testing.assert_array_equal(cms4.domain, domain / 1000) assert cms4.labels == ['a', 'b', 'c'] cms5 = MultiSignal(Series(range_1, domain)) np.testing.assert_array_equal(cms5.range, range_1[:, np.newaxis]) np.testing.assert_array_equal(cms5.domain, domain) dataframe = DataFrame( OrderedDict([('aa', range_1), ('bb', range_2), ('cc', range_3)])) cms6 = MultiSignal(dataframe) np.testing.assert_array_equal(cms6.range, tstack((range_1, range_2, range_3))) assert cms6.labels == ['aa', 'bb', 'cc'] np.testing.assert_array_equal(cms6.domain, np.arange(0, np.size(domain)))
def test_multi_signal_oject_initialisation(): domain = np.arange(0, 1000, 100) range_1 = np.linspace(1, 10, domain.size) range_2 = np.linspace(1, 10, domain.size) + 1 range_3 = np.linspace(1, 10, domain.size) + 2 cms1 = MultiSignal(tstack((domain, range_1, range_2, range_3))) np.testing.assert_array_equal(cms1.range, tstack((range_1, range_2, range_3))) np.testing.assert_array_equal(cms1.domain, domain) cms2 = MultiSignal(range_1) np.testing.assert_array_equal(cms2.range, range_1[:, np.newaxis]) np.testing.assert_array_equal(cms2.domain, np.linspace(0, 1, domain.size)) cms3 = MultiSignal(range_1, labels=['My Label']) assert list(cms3.signals.keys()) == ['My Label'] cms4 = MultiSignal(tstack((range_1, range_2, range_3)), domain / 1000, ('a', 'b', 'c')) np.testing.assert_array_equal(cms4.range, tstack((range_1, range_2, range_3))) np.testing.assert_array_equal(cms4.domain, domain / 1000) assert cms4.labels == ['a', 'b', 'c'] cms5 = MultiSignal(Series(range_1, domain)) np.testing.assert_array_equal(cms5.range, range_1[:, np.newaxis]) np.testing.assert_array_equal(cms5.domain, domain) dataframe = DataFrame( OrderedDict([('aa', range_1), ('bb', range_2), ('cc', range_3)])) cms6 = MultiSignal(dataframe) np.testing.assert_array_equal(cms6.range, tstack((range_1, range_2, range_3))) assert cms6.labels == ['aa', 'bb', 'cc'] np.testing.assert_array_equal(cms6.domain, np.arange(0, np.size(domain)))
def samples_Grossberg2003(image_stack, samples=1000, n=256): """ Returns the samples for given image stack intensity histograms using Grossberg (2003) method. Parameters ---------- image_stack : array_like Stack of single channel or multi-channel floating point images. samples : int, optional Samples count. n : int, optional Histograms bins count. Returns ------- ndarray Intensity histograms samples. """ image_stack = np.asarray(image_stack) if image_stack.ndim == 3: channels_c = 1 else: channels_c = image_stack.shape[-2] cdf_i = [] for image in tsplit(image_stack): histograms = tstack( [np.histogram(image[..., c], n, range=(0, 1))[0] for c in np.arange(channels_c)]) cdf = np.cumsum(histograms, axis=0) cdf_i.append(cdf.astype(np.float_) / np.max(cdf, axis=0)) samples_cdf_i = np.zeros((samples, len(cdf_i), channels_c)) samples_u = np.linspace(0, 1, samples) for i in np.arange(samples): for j in np.arange(channels_c): for k, cdf in enumerate(cdf_i): samples_cdf_i[i, k, j] = np.argmin(np.abs(cdf[:, j] - samples_u[i])) return samples_cdf_i
def test_multi_signal_getter(): domain = np.arange(0, 1000, 100) range_1 = np.linspace(1, 10, domain.size) range_2 = np.linspace(1, 10, domain.size) + 1 range_3 = np.linspace(1, 10, domain.size) + 2 cms1 = MultiSignal(tstack((domain, range_1, range_2, range_3))) np.testing.assert_array_almost_equal(cms1[150.25], [2.5025, 3.5025, 4.5025]) np.testing.assert_array_almost_equal( cms1[np.linspace(100, 400, 10)], np.array([[2.00000000, 3.00000000, 4.00000000], [2.33333333, 3.33333333, 4.33333333], [ 2.66666667, 3.66666667, 4.66666667 ], [3.00000000, 4.00000000, 5.00000000], [3.33333333, 4.33333333, 5.33333333], [3.66666667, 4.66666667, 5.66666667], [4.00000000, 5.00000000, 6.00000000], [ 4.33333333, 5.33333333, 6.33333333 ], [4.66666667, 5.66666667, 6.66666667], [5.00000000, 6.00000000, 7.00000000]]))
def test_multi_signal_getter(): domain = np.arange(0, 1000, 100) range_1 = np.linspace(1, 10, domain.size) range_2 = np.linspace(1, 10, domain.size) + 1 range_3 = np.linspace(1, 10, domain.size) + 2 cms1 = MultiSignal(tstack((domain, range_1, range_2, range_3))) np.testing.assert_array_almost_equal(cms1[150.25], [2.5025, 3.5025, 4.5025]) np.testing.assert_array_almost_equal( cms1[np.linspace(100, 400, 10)], np.array([[2.00000000, 3.00000000, 4.00000000], [2.33333333, 3.33333333, 4.33333333], [2.66666667, 3.66666667, 4.66666667], [3.00000000, 4.00000000, 5.00000000], [3.33333333, 4.33333333, 5.33333333], [3.66666667, 4.66666667, 5.66666667], [4.00000000, 5.00000000, 6.00000000], [4.33333333, 5.33333333, 6.33333333], [4.66666667, 5.66666667, 6.66666667], [5.00000000, 6.00000000, 7.00000000]]))
def __str__(self): try: return str(tstack((self.domain, self.range))) except TypeError: return super(Signal, self).__str__()
def demosaicing_CFA_Bayer_Menon2007(CFA, pattern='RGGB', refining_step=True): """ Returns the demosaiced *RGB* colourspace array from given *Bayer* CFA using DDFAPD - Menon (2007) demosaicing algorithm. Parameters ---------- CFA : array_like *Bayer* CFA. pattern : unicode, optional **{'RGGB', 'BGGR', 'GRBG', 'GBRG'}**, Arrangement of the colour filters on the pixel array. refining_step : bool Perform refining step. Returns ------- ndarray *RGB* colourspace array. Examples -------- >>> CFA = np.array([[ 0.30980393, 0.36078432, 0.30588236, 0.3764706 ], ... [ 0.35686275, 0.39607844, 0.36078432, 0.40000001]]) >>> demosaicing_CFA_Bayer_Menon2007(CFA) array([[[ 0.30980393, 0.35686275, 0.39215687], [ 0.30980393, 0.36078432, 0.39607844], [ 0.30588236, 0.36078432, 0.39019608], [ 0.32156864, 0.3764706 , 0.40000001]], <BLANKLINE> [[ 0.30980393, 0.35686275, 0.39215687], [ 0.30980393, 0.36078432, 0.39607844], [ 0.30588236, 0.36078432, 0.39019609], [ 0.32156864, 0.3764706 , 0.40000001]]]) >>> CFA = np.array([[ 0.3764706 , 0.36078432, 0.40784314, 0.3764706 ], ... [ 0.35686275, 0.30980393, 0.36078432, 0.29803923]]) >>> demosaicing_CFA_Bayer_Menon2007(CFA, 'BGGR') array([[[ 0.30588236, 0.35686275, 0.3764706 ], [ 0.30980393, 0.36078432, 0.39411766], [ 0.29607844, 0.36078432, 0.40784314], [ 0.29803923, 0.3764706 , 0.42352942]], <BLANKLINE> [[ 0.30588236, 0.35686275, 0.3764706 ], [ 0.30980393, 0.36078432, 0.39411766], [ 0.29607844, 0.36078432, 0.40784314], [ 0.29803923, 0.3764706 , 0.42352942]]]) """ CFA = np.asarray(CFA) R_m, G_m, B_m = masks_CFA_Bayer(CFA.shape, pattern) h_0 = np.array([0, 0.5, 0, 0.5, 0]) h_1 = np.array([-0.25, 0, 0.5, 0, -0.25]) R = CFA * R_m G = CFA * G_m B = CFA * B_m G_H = np.where(G_m == 0, _cnv_h(CFA, h_0) + _cnv_h(CFA, h_1), G) G_V = np.where(G_m == 0, _cnv_v(CFA, h_0) + _cnv_v(CFA, h_1), G) C_H = np.where(R_m == 1, R - G_H, 0) C_H = np.where(B_m == 1, B - G_H, C_H) C_V = np.where(R_m == 1, R - G_V, 0) C_V = np.where(B_m == 1, B - G_V, C_V) D_H = np.abs(C_H - np.pad(C_H, ((0, 0), (0, 2)), mode=str('reflect'))[:, 2:]) D_V = np.abs(C_V - np.pad(C_V, ((0, 2), (0, 0)), mode=str('reflect'))[2:, :]) k = np.array([[0, 0, 1, 0, 1], [0, 0, 0, 1, 0], [0, 0, 3, 0, 3], [0, 0, 0, 1, 0], [0, 0, 1, 0, 1]]) d_H = convolve(D_H, k, mode='constant') d_V = convolve(D_V, np.transpose(k), mode='constant') mask = d_V >= d_H G = np.where(mask, G_H, G_V) M = np.where(mask, 1, 0) # Red rows. R_r = np.transpose(np.any(R_m == 1, axis=1)[np.newaxis]) * np.ones(R.shape) # Blue rows. B_r = np.transpose(np.any(B_m == 1, axis=1)[np.newaxis]) * np.ones(B.shape) k_b = np.array([0.5, 0, 0.5]) R = np.where(np.logical_and(G_m == 1, R_r == 1), G + _cnv_h(R, k_b) - _cnv_h(G, k_b), R) R = np.where( np.logical_and(G_m == 1, B_r == 1) == 1, G + _cnv_v(R, k_b) - _cnv_v(G, k_b), R) B = np.where(np.logical_and(G_m == 1, B_r == 1), G + _cnv_h(B, k_b) - _cnv_h(G, k_b), B) B = np.where( np.logical_and(G_m == 1, R_r == 1) == 1, G + _cnv_v(B, k_b) - _cnv_v(G, k_b), B) R = np.where( np.logical_and(B_r == 1, B_m == 1), np.where(M == 1, B + _cnv_h(R, k_b) - _cnv_h(B, k_b), B + _cnv_v(R, k_b) - _cnv_v(B, k_b)), R) B = np.where( np.logical_and(R_r == 1, R_m == 1), np.where(M == 1, R + _cnv_h(B, k_b) - _cnv_h(R, k_b), R + _cnv_v(B, k_b) - _cnv_v(R, k_b)), B) RGB = tstack((R, G, B)) if refining_step: RGB = refining_step_Menon2007(RGB, tstack((R_m, G_m, B_m)), M) return RGB
def refining_step_Menon2007(RGB, RGB_m, M): """ Performs the refining step on given *RGB* colourspace array. Parameters ---------- RGB : array_like *RGB* colourspace array. RGB_m : array_like *Bayer* CFA red, green and blue masks. M : array_like Estimation for the best directional reconstruction. Returns ------- ndarray Refined *RGB* colourspace array. Examples -------- >>> RGB = np.array([[[0.30588236, 0.35686275, 0.3764706], ... [0.30980393, 0.36078432, 0.39411766], ... [0.29607844, 0.36078432, 0.40784314], ... [0.29803923, 0.37647060, 0.42352942]], ... [[0.30588236, 0.35686275, 0.3764706], ... [0.30980393, 0.36078432, 0.39411766], ... [0.29607844, 0.36078432, 0.40784314], ... [0.29803923, 0.37647060, 0.42352942]]]) >>> RGB_m = np.array([[[0, 0, 1], ... [0, 1, 0], ... [0, 0, 1], ... [0, 1, 0]], ... [[0, 1, 0], ... [1, 0, 0], ... [0, 1, 0], ... [1, 0, 0]]]) >>> M = np.array([[0, 1, 0, 1], ... [1, 0, 1, 0]]) >>> refining_step_Menon2007(RGB, RGB_m, M) array([[[ 0.30588236, 0.35686275, 0.3764706 ], [ 0.30980393, 0.36078432, 0.39411765], [ 0.29607844, 0.36078432, 0.40784314], [ 0.29803923, 0.3764706 , 0.42352942]], <BLANKLINE> [[ 0.30588236, 0.35686275, 0.3764706 ], [ 0.30980393, 0.36078432, 0.39411766], [ 0.29607844, 0.36078432, 0.40784314], [ 0.29803923, 0.3764706 , 0.42352942]]]) """ R, G, B = tsplit(RGB) R_m, G_m, B_m = tsplit(RGB_m) M = np.asarray(M) # Updating of the green component. R_G = R - G B_G = B - G FIR = np.ones(3) / 3 B_G_m = np.where(B_m == 1, np.where(M == 1, _cnv_h(B_G, FIR), _cnv_v(B_G, FIR)), 0) R_G_m = np.where(R_m == 1, np.where(M == 1, _cnv_h(R_G, FIR), _cnv_v(R_G, FIR)), 0) G = np.where(R_m == 1, R - R_G_m, G) G = np.where(B_m == 1, B - B_G_m, G) # Updating of the red and blue components in the green locations. # Red rows. R_r = np.transpose(np.any(R_m == 1, axis=1)[np.newaxis]) * np.ones(R.shape) # Red columns. R_c = np.any(R_m == 1, axis=0)[np.newaxis] * np.ones(R.shape) # Blue rows. B_r = np.transpose(np.any(B_m == 1, axis=1)[np.newaxis]) * np.ones(B.shape) # Blue columns B_c = np.any(B_m == 1, axis=0)[np.newaxis] * np.ones(B.shape) R_G = R - G B_G = B - G k_b = np.array([0.5, 0, 0.5]) R_G_m = np.where(np.logical_and(G_m == 1, B_r == 1), _cnv_v(R_G, k_b), R_G_m) R = np.where(np.logical_and(G_m == 1, B_r == 1), G + R_G_m, R) R_G_m = np.where(np.logical_and(G_m == 1, B_c == 1), _cnv_h(R_G, k_b), R_G_m) R = np.where(np.logical_and(G_m == 1, B_c == 1), G + R_G_m, R) B_G_m = np.where(np.logical_and(G_m == 1, R_r == 1), _cnv_v(B_G, k_b), B_G_m) B = np.where(np.logical_and(G_m == 1, R_r == 1), G + B_G_m, B) B_G_m = np.where(np.logical_and(G_m == 1, R_c == 1), _cnv_h(B_G, k_b), B_G_m) B = np.where(np.logical_and(G_m == 1, R_c == 1), G + B_G_m, B) # Updating of the red (blue) component in the blue (red) locations. R_B = R - B R_B_m = np.where(B_m == 1, np.where(M == 1, _cnv_h(R_B, FIR), _cnv_v(R_B, FIR)), 0) R = np.where(B_m == 1, B + R_B_m, R) R_B_m = np.where(R_m == 1, np.where(M == 1, _cnv_h(R_B, FIR), _cnv_v(R_B, FIR)), 0) B = np.where(R_m == 1, R - R_B_m, B) return tstack((R, G, B))
def __getitem__(self, x): return tstack([signal[x] for signal in self._signals.values()])
def range(self): if len(self._signals) != 0: return tstack([signal.range for signal in self._signals.values()])
def demosaicing_CFA_Bayer_Menon2007(CFA, pattern='RGGB', refining_step=True): """ Returns the demosaiced *RGB* colourspace array from given *Bayer* CFA using DDFAPD - Menon (2007) demosaicing algorithm. Parameters ---------- CFA : array_like *Bayer* CFA. pattern : unicode, optional **{'RGGB', 'BGGR', 'GRBG', 'GBRG'}**, Arrangement of the colour filters on the pixel array. refining_step : bool Perform refining step. Returns ------- ndarray *RGB* colourspace array. Examples -------- >>> CFA = np.array([[ 0.30980393, 0.36078432, 0.30588236, 0.3764706 ], ... [ 0.35686275, 0.39607844, 0.36078432, 0.40000001]]) >>> demosaicing_CFA_Bayer_Menon2007(CFA) array([[[ 0.30980393, 0.35686275, 0.39215687], [ 0.30980393, 0.36078432, 0.39607844], [ 0.30588236, 0.36078432, 0.39019608], [ 0.32156864, 0.3764706 , 0.40000001]], <BLANKLINE> [[ 0.30980393, 0.35686275, 0.39215687], [ 0.30980393, 0.36078432, 0.39607844], [ 0.30588236, 0.36078432, 0.39019609], [ 0.32156864, 0.3764706 , 0.40000001]]]) >>> CFA = np.array([[ 0.3764706 , 0.36078432, 0.40784314, 0.3764706 ], ... [ 0.35686275, 0.30980393, 0.36078432, 0.29803923]]) >>> demosaicing_CFA_Bayer_Menon2007(CFA, 'BGGR') array([[[ 0.30588236, 0.35686275, 0.3764706 ], [ 0.30980393, 0.36078432, 0.39411766], [ 0.29607844, 0.36078432, 0.40784314], [ 0.29803923, 0.3764706 , 0.42352942]], <BLANKLINE> [[ 0.30588236, 0.35686275, 0.3764706 ], [ 0.30980393, 0.36078432, 0.39411766], [ 0.29607844, 0.36078432, 0.40784314], [ 0.29803923, 0.3764706 , 0.42352942]]]) """ CFA = np.asarray(CFA) R_m, G_m, B_m = masks_CFA_Bayer(CFA.shape, pattern) h_0 = np.array([0, 0.5, 0, 0.5, 0]) h_1 = np.array([-0.25, 0, 0.5, 0, -0.25]) R = CFA * R_m G = CFA * G_m B = CFA * B_m G_H = np.where(G_m == 0, _cnv_h(CFA, h_0) + _cnv_h(CFA, h_1), G) G_V = np.where(G_m == 0, _cnv_v(CFA, h_0) + _cnv_v(CFA, h_1), G) C_H = np.where(R_m == 1, R - G_H, 0) C_H = np.where(B_m == 1, B - G_H, C_H) C_V = np.where(R_m == 1, R - G_V, 0) C_V = np.where(B_m == 1, B - G_V, C_V) D_H = np.abs(C_H - np.pad(C_H, ((0, 0), (0, 2)), mode=str('reflect'))[:, 2:]) D_V = np.abs(C_V - np.pad(C_V, ((0, 2), (0, 0)), mode=str('reflect'))[2:, :]) k = np.array( [[0, 0, 1, 0, 1], [0, 0, 0, 1, 0], [0, 0, 3, 0, 3], [0, 0, 0, 1, 0], [0, 0, 1, 0, 1]]) d_H = convolve(D_H, k, mode='constant') d_V = convolve(D_V, np.transpose(k), mode='constant') mask = d_V >= d_H G = np.where(mask, G_H, G_V) M = np.where(mask, 1, 0) # Red rows. R_r = np.transpose(np.any(R_m == 1, axis=1)[np.newaxis]) * np.ones(R.shape) # Blue rows. B_r = np.transpose(np.any(B_m == 1, axis=1)[np.newaxis]) * np.ones(B.shape) k_b = np.array([0.5, 0, 0.5]) R = np.where(np.logical_and(G_m == 1, R_r == 1), G + _cnv_h(R, k_b) - _cnv_h(G, k_b), R) R = np.where(np.logical_and(G_m == 1, B_r == 1) == 1, G + _cnv_v(R, k_b) - _cnv_v(G, k_b), R) B = np.where(np.logical_and(G_m == 1, B_r == 1), G + _cnv_h(B, k_b) - _cnv_h(G, k_b), B) B = np.where(np.logical_and(G_m == 1, R_r == 1) == 1, G + _cnv_v(B, k_b) - _cnv_v(G, k_b), B) R = np.where(np.logical_and(B_r == 1, B_m == 1), np.where(M == 1, B + _cnv_h(R, k_b) - _cnv_h(B, k_b), B + _cnv_v(R, k_b) - _cnv_v(B, k_b)), R) B = np.where(np.logical_and(R_r == 1, R_m == 1), np.where(M == 1, R + _cnv_h(B, k_b) - _cnv_h(R, k_b), R + _cnv_v(B, k_b) - _cnv_v(R, k_b)), B) RGB = tstack((R, G, B)) if refining_step: RGB = refining_step_Menon2007(RGB, tstack((R_m, G_m, B_m)), M) return RGB
def image_stack_to_radiance_image( image_stack, weighting_function=weighting_function_Debevec1997, weighting_average=False, camera_response_functions=None): """ Generates a HDRI / radiance image from given image stack. Parameters ---------- image_stack : ImageStack Stack of single channel or multi-channel floating point images. The stack is assumed to be representing linear values except if ``camera_response_functions`` argument is provided. weighting_function : callable, optional Weighting function :math:`w`. weighting_average : bool, optional Enables weighting function :math:`w` computation on channels average instead of on a per channel basis. camera_response_functions : array_like, optional Camera response functions :math:`g(z)` of the imaging system / camera if the stack is representing non linear values. Returns ------- ndarray Radiance image. """ image_c = None weight_c = None for image in image_stack: if image_c is None: image_c = np.zeros(image.data.shape) weight_c = np.zeros(image.data.shape) L = average_luminance( image.metadata.f_number, image.metadata.exposure_time, image.metadata.iso) if weighting_average and image.data.ndim == 3: weight = weighting_function(np.average(image.data, axis=-1)) weight = np.rollaxis(weight[np.newaxis], 0, 3) else: weight = weighting_function(image.data) image_data = image.data if camera_response_functions is not None: samples = np.linspace(0, 1, camera_response_functions.shape[0]) R, G, B = tsplit(image.data) R = np.interp(R, samples, camera_response_functions[..., 0]) G = np.interp(G, samples, camera_response_functions[..., 1]) B = np.interp(B, samples, camera_response_functions[..., 2]) image_data = tstack((R, G, B)) image_c += weight * image_data / L weight_c += weight if image_c is not None: image_c /= weight_c image_c[np.isnan(image_c)] = 0 return image_c
def demosaicing_CFA_Bayer_Malvar2004(CFA, pattern='RGGB'): """ Returns the demosaiced *RGB* colourspace array from given *Bayer* CFA using Malvar (2004) demosaicing algorithm. Parameters ---------- CFA : array_like *Bayer* CFA. pattern : unicode, optional **{'RGGB', 'BGGR', 'GRBG', 'GBRG'}**, Arrangement of the colour filters on the pixel array. Returns ------- ndarray *RGB* colourspace array. Examples -------- >>> CFA = np.array([[0.30980393, 0.36078432, 0.30588236, 0.3764706], ... [0.35686275, 0.39607844, 0.36078432, 0.40000001]]) >>> demosaicing_CFA_Bayer_Malvar2004(CFA) array([[[ 0.30980393, 0.31666668, 0.32941177], [ 0.33039216, 0.36078432, 0.38112746], [ 0.30588236, 0.32794118, 0.34877452], [ 0.36274511, 0.3764706 , 0.38480393]], <BLANKLINE> [[ 0.34828432, 0.35686275, 0.36568628], [ 0.35318628, 0.38186275, 0.39607844], [ 0.3379902 , 0.36078432, 0.3754902 ], [ 0.37769609, 0.39558825, 0.40000001]]]) >>> CFA = np.array([[0.3764706, 0.360784320, 0.40784314, 0.3764706], ... [0.35686275, 0.30980393, 0.36078432, 0.29803923]]) >>> demosaicing_CFA_Bayer_Malvar2004(CFA, 'BGGR') array([[[ 0.35539217, 0.37058825, 0.3764706 ], [ 0.34264707, 0.36078432, 0.37450981], [ 0.36568628, 0.39607844, 0.40784314], [ 0.36568629, 0.3764706 , 0.3882353 ]], <BLANKLINE> [[ 0.34411765, 0.35686275, 0.36200981], [ 0.30980393, 0.32990197, 0.34975491], [ 0.33039216, 0.36078432, 0.38063726], [ 0.29803923, 0.30441178, 0.31740197]]]) """ CFA = np.asarray(CFA) R_m, G_m, B_m = masks_CFA_Bayer(CFA.shape, pattern) GR_GB = np.asarray( [[0, 0, -1, 0, 0], [0, 0, 2, 0, 0], [-1, 2, 4, 2, -1], [0, 0, 2, 0, 0], [0, 0, -1, 0, 0]]) / 8 Rg_RB_Bg_BR = np.asarray( [[0, 0, 0.5, 0, 0], [0, -1, 0, -1, 0], [-1, 4, 5, 4, - 1], [0, -1, 0, -1, 0], [0, 0, 0.5, 0, 0]]) / 8 Rg_BR_Bg_RB = np.transpose(Rg_RB_Bg_BR) Rb_BB_Br_RR = np.asarray( [[0, 0, -1.5, 0, 0], [0, 2, 0, 2, 0], [-1.5, 0, 6, 0, -1.5], [0, 2, 0, 2, 0], [0, 0, -1.5, 0, 0]]) / 8 R = CFA * R_m G = CFA * G_m B = CFA * B_m G = np.where(np.logical_or(R_m == 1, B_m == 1), convolve(CFA, GR_GB), G) RBg_RBBR = convolve(CFA, Rg_RB_Bg_BR) RBg_BRRB = convolve(CFA, Rg_BR_Bg_RB) RBgr_BBRR = convolve(CFA, Rb_BB_Br_RR) # Red rows. R_r = np.transpose(np.any(R_m == 1, axis=1)[np.newaxis]) * np.ones(R.shape) # Red columns. R_c = np.any(R_m == 1, axis=0)[np.newaxis] * np.ones(R.shape) # Blue rows. B_r = np.transpose(np.any(B_m == 1, axis=1)[np.newaxis]) * np.ones(B.shape) # Blue columns B_c = np.any(B_m == 1, axis=0)[np.newaxis] * np.ones(B.shape) R = np.where(np.logical_and(R_r == 1, B_c == 1), RBg_RBBR, R) R = np.where(np.logical_and(B_r == 1, R_c == 1), RBg_BRRB, R) B = np.where(np.logical_and(B_r == 1, R_c == 1), RBg_RBBR, B) B = np.where(np.logical_and(R_r == 1, B_c == 1), RBg_BRRB, B) R = np.where(np.logical_and(B_r == 1, B_c == 1), RBgr_BBRR, R) B = np.where(np.logical_and(R_r == 1, R_c == 1), RBgr_BBRR, B) return tstack((R, G, B))
def demosaicing_CFA_Bayer_Malvar2004(CFA, pattern='RGGB'): """ Returns the demosaiced *RGB* colourspace array from given *Bayer* CFA using Malvar (2004) demosaicing algorithm. Parameters ---------- CFA : array_like *Bayer* CFA. pattern : unicode, optional **{'RGGB', 'BGGR', 'GRBG', 'GBRG'}**, Arrangement of the colour filters on the pixel array. Returns ------- ndarray *RGB* colourspace array. Examples -------- >>> CFA = np.array([[0.30980393, 0.36078432, 0.30588236, 0.3764706], ... [0.35686275, 0.39607844, 0.36078432, 0.40000001]]) >>> demosaicing_CFA_Bayer_Malvar2004(CFA) array([[[ 0.30980393, 0.31666668, 0.32941177], [ 0.33039216, 0.36078432, 0.38112746], [ 0.30588236, 0.32794118, 0.34877452], [ 0.36274511, 0.3764706 , 0.38480393]], <BLANKLINE> [[ 0.34828432, 0.35686275, 0.36568628], [ 0.35318628, 0.38186275, 0.39607844], [ 0.3379902 , 0.36078432, 0.3754902 ], [ 0.37769609, 0.39558825, 0.40000001]]]) >>> CFA = np.array([[0.3764706, 0.360784320, 0.40784314, 0.3764706], ... [0.35686275, 0.30980393, 0.36078432, 0.29803923]]) >>> demosaicing_CFA_Bayer_Malvar2004(CFA, 'BGGR') array([[[ 0.35539217, 0.37058825, 0.3764706 ], [ 0.34264707, 0.36078432, 0.37450981], [ 0.36568628, 0.39607844, 0.40784314], [ 0.36568629, 0.3764706 , 0.3882353 ]], <BLANKLINE> [[ 0.34411765, 0.35686275, 0.36200981], [ 0.30980393, 0.32990197, 0.34975491], [ 0.33039216, 0.36078432, 0.38063726], [ 0.29803923, 0.30441178, 0.31740197]]]) """ CFA = np.asarray(CFA) R_m, G_m, B_m = masks_CFA_Bayer(CFA.shape, pattern) GR_GB = np.asarray([[0, 0, -1, 0, 0], [0, 0, 2, 0, 0], [-1, 2, 4, 2, -1], [0, 0, 2, 0, 0], [0, 0, -1, 0, 0]]) / 8 Rg_RB_Bg_BR = np.asarray([[0, 0, 0.5, 0, 0], [0, -1, 0, -1, 0], [-1, 4, 5, 4, -1], [0, -1, 0, -1, 0], [0, 0, 0.5, 0, 0]]) / 8 Rg_BR_Bg_RB = np.transpose(Rg_RB_Bg_BR) Rb_BB_Br_RR = np.asarray([[0, 0, -1.5, 0, 0], [0, 2, 0, 2, 0], [-1.5, 0, 6, 0, -1.5], [0, 2, 0, 2, 0], [0, 0, -1.5, 0, 0]]) / 8 R = CFA * R_m G = CFA * G_m B = CFA * B_m G = np.where(np.logical_or(R_m == 1, B_m == 1), convolve(CFA, GR_GB), G) RBg_RBBR = convolve(CFA, Rg_RB_Bg_BR) RBg_BRRB = convolve(CFA, Rg_BR_Bg_RB) RBgr_BBRR = convolve(CFA, Rb_BB_Br_RR) # Red rows. R_r = np.transpose(np.any(R_m == 1, axis=1)[np.newaxis]) * np.ones(R.shape) # Red columns. R_c = np.any(R_m == 1, axis=0)[np.newaxis] * np.ones(R.shape) # Blue rows. B_r = np.transpose(np.any(B_m == 1, axis=1)[np.newaxis]) * np.ones(B.shape) # Blue columns B_c = np.any(B_m == 1, axis=0)[np.newaxis] * np.ones(B.shape) R = np.where(np.logical_and(R_r == 1, B_c == 1), RBg_RBBR, R) R = np.where(np.logical_and(B_r == 1, R_c == 1), RBg_BRRB, R) B = np.where(np.logical_and(B_r == 1, R_c == 1), RBg_RBBR, B) B = np.where(np.logical_and(R_r == 1, B_c == 1), RBg_BRRB, B) R = np.where(np.logical_and(B_r == 1, B_c == 1), RBgr_BBRR, R) B = np.where(np.logical_and(R_r == 1, R_c == 1), RBgr_BBRR, B) return tstack((R, G, B))
def demosaicing_CFA_Bayer_bilinear(CFA, pattern='RGGB'): """ Returns the demosaiced *RGB* colourspace array from given *Bayer* CFA using bilinear interpolation. Parameters ---------- CFA : array_like *Bayer* CFA. pattern : unicode, optional **{'RGGB', 'BGGR', 'GRBG', 'GBRG'}**, Arrangement of the colour filters on the pixel array. Returns ------- ndarray *RGB* colourspace array. Examples -------- >>> CFA = np.array([[0.30980393, 0.36078432, 0.30588236, 0.3764706], ... [0.35686275, 0.39607844, 0.36078432, 0.40000001]]) >>> demosaicing_CFA_Bayer_bilinear(CFA) array([[[ 0.69705884, 0.17941177, 0.09901961], [ 0.46176472, 0.4509804 , 0.19803922], [ 0.45882354, 0.27450981, 0.19901961], [ 0.22941177, 0.5647059 , 0.30000001]], <BLANKLINE> [[ 0.23235295, 0.53529412, 0.29705883], [ 0.15392157, 0.26960785, 0.59411766], [ 0.15294118, 0.4509804 , 0.59705884], [ 0.07647059, 0.18431373, 0.90000002]]]) >>> CFA = np.array([[0.3764706, 0.360784320, 0.40784314, 0.3764706], ... [0.35686275, 0.30980393, 0.36078432, 0.29803923]]) >>> demosaicing_CFA_Bayer_bilinear(CFA, 'BGGR') array([[[ 0.07745098, 0.17941177, 0.84705885], [ 0.15490197, 0.4509804 , 0.5882353 ], [ 0.15196079, 0.27450981, 0.61176471], [ 0.22352942, 0.5647059 , 0.30588235]], <BLANKLINE> [[ 0.23235295, 0.53529412, 0.28235295], [ 0.4647059 , 0.26960785, 0.19607843], [ 0.45588237, 0.4509804 , 0.20392157], [ 0.67058827, 0.18431373, 0.10196078]]]) """ CFA = np.asarray(CFA) R_m, G_m, B_m = masks_CFA_Bayer(CFA.shape, pattern) H_G = np.asarray( [[0, 1, 0], [1, 4, 1], [0, 1, 0]]) / 4 H_RB = np.asarray( [[1, 2, 1], [2, 4, 2], [1, 2, 1]]) / 4 R = convolve(CFA * R_m, H_RB) G = convolve(CFA * G_m, H_G) B = convolve(CFA * B_m, H_RB) return tstack((R, G, B))