diff --git a/scikits/image/io/_plugins/_colormixer.pyx b/scikits/image/io/_plugins/_colormixer.pyx index 73127d52..c1291e78 100644 --- a/scikits/image/io/_plugins/_colormixer.pyx +++ b/scikits/image/io/_plugins/_colormixer.pyx @@ -14,6 +14,10 @@ cimport numpy as np import cython +cdef extern from "math.h": + float exp(float) + + @cython.boundscheck(False) def add(np.ndarray[np.uint8_t, ndim=3] img, np.ndarray[np.uint8_t, ndim=3] stateimg, @@ -51,6 +55,7 @@ def add(np.ndarray[np.uint8_t, ndim=3] img, else: img[i, j, k] = op_result + @cython.boundscheck(False) def multiply(np.ndarray[np.uint8_t, ndim=3] img, np.ndarray[np.uint8_t, ndim=3] stateimg, @@ -88,13 +93,14 @@ def multiply(np.ndarray[np.uint8_t, ndim=3] img, else: img[i, j, k] = op_result + @cython.boundscheck(False) def brightness(np.ndarray[np.uint8_t, ndim=3] img, np.ndarray[np.uint8_t, ndim=3] stateimg, int offset, float factor): """Modify the brightness of an image. - 'offset' is added to all channels, which are - then multiplied by 'factor'. Overflow is clipped. + 'factor' is multiplied to all channels, which are + then added by 'amount'. Overflow is clipped. Parameters ---------- @@ -118,7 +124,8 @@ def brightness(np.ndarray[np.uint8_t, ndim=3] img, for i in range(height): for j in range(width): for k in range(3): - op_result = ((stateimg[i,j,k] + offset)*factor) + op_result = ((stateimg[i,j,k] * factor + offset)) + if op_result > 255: img[i, j, k] = 255 elif op_result < 0: @@ -127,6 +134,42 @@ def brightness(np.ndarray[np.uint8_t, ndim=3] img, img[i, j, k] = op_result +@cython.boundscheck(False) +def sigmoid_gamma(np.ndarray[np.uint8_t, ndim=3] img, + np.ndarray[np.uint8_t, ndim=3] stateimg, + float alpha, float beta): + + cdef int height = img.shape[0] + cdef int width = img.shape[1] + + cdef float c1, c2, r, g, b + + cdef int i, j, k + for i in range(height): + for j in range(width): + r = stateimg[i,j,0] / 255. + g = stateimg[i,j,1] / 255. + b = stateimg[i,j,2] / 255. + + c1 = 1 / (1 + exp(beta)) + c2 = 1 / (1 + exp(beta - alpha)) - c1 + + r = 1 / (1 + exp(beta - r * alpha)) + r = (r - c1) / c2 + + g = 1 / (1 + exp(beta - g * alpha)) + g = (g - c1) / c2 + + b = 1 / (1 + exp(beta - b * alpha)) + b = (b - c1) / c2 + + img[i,j,0] = (r * 255) + img[i,j,1] = (g * 255) + img[i,j,2] = (b * 255) + + + + cdef void rgb_2_hsv(float* RGB, float* HSV): cdef float R, G, B, H, S, V, MAX, MIN R = RGB[0] diff --git a/scikits/image/io/_plugins/qt_plugin.py b/scikits/image/io/_plugins/qt_plugin.py index 0531a114..a7d95a98 100644 --- a/scikits/image/io/_plugins/qt_plugin.py +++ b/scikits/image/io/_plugins/qt_plugin.py @@ -181,7 +181,8 @@ else: #--------------------------------------------------------------- self.combo_box_entries = ['RGB Color', 'HSV Color', - 'Brightness', 'Contrast'] + 'Brightness/Contrast', + 'Gamma (Sigmoidal)'] self.combo_box = QtGui.QComboBox() for entry in self.combo_box_entries: self.combo_box.addItem(entry) @@ -252,8 +253,9 @@ else: #--------------------------------------------------------------- # sliders - self.bright_sliders = NSliderBlock(2, [(-255, 255, 0, '+', 1), - (0, 1000, 500, 'x', 0.002)], + self.bright_sliders = NSliderBlock(2, + [(0, 1000, 500, 'x', 0.002), + (-255, 255, 0, '+', 1)], self.bright_changed) # layout @@ -261,6 +263,20 @@ else: self.bright_widget.layout = QtGui.QGridLayout(self.bright_widget) self.bright_widget.layout.addWidget(self.bright_sliders, 0, 0) + #--------------------------------------------------------------- + # Gamma sliders + #--------------------------------------------------------------- + # sliders + self.gamma_sliders = NSliderBlock(2, + [(100, 1200, 100, 'alpha', 0.01), + (0, 1200, 0, 'beta', 0.01)], + self.gamma_changed) + + # layout + self.gamma_widget = QWidget() + self.gamma_widget.layout = QtGui.QGridLayout(self.gamma_widget) + self.gamma_widget.layout.addWidget(self.gamma_sliders, 0, 0) + #--------------------------------------------------------------- # Buttons #--------------------------------------------------------------- @@ -276,7 +292,9 @@ else: self.layout.addWidget(self.combo_box, 0, 0) self.layout.addWidget(self.rgb_widget, 1, 0) self.layout.addWidget(self.hsv_widget, 1, 0) + self.layout.addWidget(self.gamma_widget, 1, 0) self.layout.addWidget(self.bright_widget, 1, 0) + self.layout.addWidget(self.commit_button, 2, 0) self.layout.addWidget(self.revert_button, 3, 0) @@ -342,6 +360,16 @@ else: self.mixer.brightness(offset, factor) self.update() + def gamma_changed(self, name, val): + # doesnt matter which slider changed we need both + # values + alpha = self.gamma_sliders.sliders['alpha'].conv_val() + beta = self.gamma_sliders.sliders['beta'].conv_val() + self.mixer.sigmoid_gamma(alpha, beta) + self.update() + + def iter_all_sliders(self): + pass def reset_sliders(self): self.rgb_add_sliders.set_sliders({'R': 0, 'G': 0, 'B': 0}) @@ -349,19 +377,21 @@ else: self.hsv_add_sliders.set_sliders({'H': 0, 'S': 0, 'V': 0}) self.hsv_mul_sliders.set_sliders({'H': 0, 'S': 500, 'V': 500}) self.bright_sliders.set_sliders({'+': 0, 'x': 500}) + self.gamma_sliders.set_sliders({'alpha': 100, 'beta': 0}) def combo_box_changed(self, index): self.reset_sliders() self.mixer.set_to_stateimg() self.update() combo_box_map={0: self.show_rgb, 1: self.show_hsv, - 2: self.show_bright, 3: self.show_contrast} + 2: self.show_bright, 3: self.show_gamma} combo_box_map[index]() def hide_sliders(self): self.rgb_widget.hide() self.hsv_widget.hide() self.bright_widget.hide() + self.gamma_sliders.hide() def rgb_radio_changed(self): if self.rgb_add.isChecked(): @@ -403,8 +433,9 @@ else: self.hide_sliders() self.bright_widget.show() - def show_contrast(self): + def show_gamma(self): self.hide_sliders() + self.gamma_sliders.show() def commit_changes(self): self.mixer.commit_changes() @@ -605,6 +636,14 @@ else: self.layout.setColumnStretch(0, 1) self.layout.setRowStretch(0, 1) + self.save_file = QtGui.QPushButton('Save to File') + self.save_variable = QtGui.QPushButton('Save to Variable') + self.save_file.show() + self.save_variable.show() + + self.layout.addWidget(self.save_variable, 1, 1) + self.layout.addWidget(self.save_file, 1, 2) + # hook up the mixer sliders move events to trigger a # histogram redraw. self.mixer_panel.rgb_add_sliders.sliders['R'].\ diff --git a/scikits/image/io/_plugins/util.py b/scikits/image/io/_plugins/util.py index c6f0dbe7..7caff221 100644 --- a/scikits/image/io/_plugins/util.py +++ b/scikits/image/io/_plugins/util.py @@ -258,6 +258,9 @@ class ColorMixer(object): ''' _colormixer.brightness(self.img, self.stateimg, offset, factor) + def sigmoid_gamma(self, alpha, beta): + _colormixer.sigmoid_gamma(self.img, self.stateimg, alpha, beta) + def hsv_add(self, h_amt, s_amt, v_amt): '''Adjust the H, S, V channels of an image by a constant ammount. This is similar to the add() mixer function, but operates over the