mirror of
https://github.com/wassname/scikit-image.git
synced 2026-06-30 11:09:29 +08:00
Added tests for colormixer and histograms. Moved tests up a directory level because
nosetests doesnt see tests in a directory beginning with an _ (_plugins/). Moved fancy imshow to its own module scivi.py
This commit is contained in:
+2
-2
@@ -10,8 +10,8 @@
|
||||
- Mahipal Raythattha
|
||||
Documentation infrastructure
|
||||
|
||||
- Chris Colbert
|
||||
OpenCV wrappers
|
||||
- S. Chris Colbert
|
||||
OpenCV wrappers, Scivi, Qt and Gtk gui bits.
|
||||
|
||||
- Holger Rapp
|
||||
OpenCV functions and better OSX library loader
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[qt]
|
||||
description = Fast image display using the Qt library
|
||||
provides = imshow, _app_show
|
||||
provides = imshow, _app_show, imsave
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from util import prepare_for_display, window_manager, GuiLockError
|
||||
|
||||
from textwrap import dedent
|
||||
import numpy as np
|
||||
import sys
|
||||
|
||||
@@ -14,12 +14,8 @@ except GuiLockError, gle:
|
||||
else:
|
||||
try:
|
||||
from PyQt4.QtGui import (QApplication, QMainWindow, QImage, QPixmap,
|
||||
QLabel, QWidget, QVBoxLayout, QSlider,
|
||||
QPainter, QColor, QFrame, QLayoutItem)
|
||||
QLabel, QWidget)
|
||||
from PyQt4 import QtCore, QtGui
|
||||
from PyQt4.QtCore import Qt
|
||||
from q_color_mixer import MixerPanel
|
||||
from q_histogram import QuadHistogram
|
||||
|
||||
except ImportError:
|
||||
print 'PyQT4 libraries not installed. Plugin not loaded.'
|
||||
@@ -29,10 +25,10 @@ else:
|
||||
|
||||
app = None
|
||||
|
||||
class LabelImage(QLabel):
|
||||
class ImageLabel(QLabel):
|
||||
def __init__(self, parent, arr):
|
||||
QLabel.__init__(self)
|
||||
self.parent = parent
|
||||
|
||||
# we need to hold a reference to
|
||||
# arr because QImage doesn't copy the data
|
||||
# and the buffer must be alive as long
|
||||
@@ -47,14 +43,10 @@ else:
|
||||
self.img = QImage(arr.data, arr.shape[1], arr.shape[0],
|
||||
arr.strides[0], QImage.Format_RGB888)
|
||||
self.pm = QPixmap.fromImage(self.img)
|
||||
self.setAlignment(Qt.AlignTop)
|
||||
self.setPixmap(self.pm)
|
||||
self.setAlignment(QtCore.Qt.AlignTop)
|
||||
self.setMinimumSize(100, 100)
|
||||
|
||||
def mouseMoveEvent(self, evt):
|
||||
self.parent.label_mouseMoveEvent(evt)
|
||||
|
||||
def resizeEvent(self, evt):
|
||||
width = self.width()
|
||||
pm = QPixmap.fromImage(self.img)
|
||||
@@ -62,22 +54,16 @@ else:
|
||||
self.setPixmap(self.pm)
|
||||
|
||||
|
||||
def update_image(self):
|
||||
width = self.width()
|
||||
pm = QPixmap.fromImage(self.img)
|
||||
pm = pm.scaledToWidth(width)
|
||||
self.setPixmap(pm)
|
||||
|
||||
|
||||
class ImageWindow(QMainWindow):
|
||||
def __init__(self, arr, mgr):
|
||||
QMainWindow.__init__(self)
|
||||
self.setWindowTitle('scikits.image')
|
||||
self.mgr = mgr
|
||||
self.main_widget = QWidget()
|
||||
self.layout = QtGui.QGridLayout(self.main_widget)
|
||||
self.setCentralWidget(self.main_widget)
|
||||
|
||||
self.label = LabelImage(self, arr)
|
||||
self.label = ImageLabel(self, arr)
|
||||
self.layout.addWidget(self.label, 0, 0)
|
||||
self.layout.addLayout
|
||||
self.mgr.add_window(self)
|
||||
@@ -88,156 +74,6 @@ else:
|
||||
# references to it
|
||||
self.mgr.remove_window(self)
|
||||
|
||||
def label_mouseMoveEvent(self, evt):
|
||||
pass
|
||||
|
||||
|
||||
class RGBHSVDisplay(QWidget):
|
||||
def __init__(self):
|
||||
QWidget.__init__(self)
|
||||
self.posx_label = QLabel('X-pos:')
|
||||
self.posx_value = QLabel()
|
||||
self.posy_label = QLabel('Y-pos:')
|
||||
self.posy_value = QLabel()
|
||||
self.r_label = QLabel('R:')
|
||||
self.r_value = QLabel()
|
||||
self.g_label = QLabel('G:')
|
||||
self.g_value = QLabel()
|
||||
self.b_label = QLabel('B:')
|
||||
self.b_value = QLabel()
|
||||
self.h_label = QLabel('H:')
|
||||
self.h_value = QLabel()
|
||||
self.s_label = QLabel('S:')
|
||||
self.s_value = QLabel()
|
||||
self.v_label = QLabel('V:')
|
||||
self.v_value = QLabel()
|
||||
|
||||
self.layout = QtGui.QGridLayout(self)
|
||||
self.layout.addWidget(self.posx_label, 0, 0)
|
||||
self.layout.addWidget(self.posx_value, 0, 1)
|
||||
self.layout.addWidget(self.posy_label, 1, 0)
|
||||
self.layout.addWidget(self.posy_value, 1, 1)
|
||||
self.layout.addWidget(self.r_label, 0, 2)
|
||||
self.layout.addWidget(self.r_value, 0, 3)
|
||||
self.layout.addWidget(self.g_label, 1, 2)
|
||||
self.layout.addWidget(self.g_value, 1, 3)
|
||||
self.layout.addWidget(self.b_label, 2, 2)
|
||||
self.layout.addWidget(self.b_value, 2, 3)
|
||||
self.layout.addWidget(self.h_label, 0, 4)
|
||||
self.layout.addWidget(self.h_value, 0, 5)
|
||||
self.layout.addWidget(self.s_label, 1, 4)
|
||||
self.layout.addWidget(self.s_value, 1, 5)
|
||||
self.layout.addWidget(self.v_label, 2, 4)
|
||||
self.layout.addWidget(self.v_value, 2, 5)
|
||||
|
||||
def update_vals(self, data):
|
||||
xpos, ypos, r, g, b, h, s, v = data
|
||||
self.posx_value.setText(str(xpos)[:5])
|
||||
self.posy_value.setText(str(ypos)[:5])
|
||||
self.r_value.setText(str(r)[:5])
|
||||
self.g_value.setText(str(g)[:5])
|
||||
self.b_value.setText(str(b)[:5])
|
||||
self.h_value.setText(str(h)[:5])
|
||||
self.s_value.setText(str(s)[:5])
|
||||
self.v_value.setText(str(v)[:5])
|
||||
|
||||
|
||||
class FancyImageWindow(ImageWindow):
|
||||
def __init__(self, arr, mgr):
|
||||
ImageWindow.__init__(self, arr, mgr)
|
||||
self.arr = arr
|
||||
|
||||
self.label.setMouseTracking(True)
|
||||
|
||||
self.mixer_panel = MixerPanel(self.arr)
|
||||
self.layout.addWidget(self.mixer_panel, 0, 2)
|
||||
self.mixer_panel.show()
|
||||
self.mixer_panel.set_callback(self.refresh_image)
|
||||
|
||||
self.rgbv_hist = QuadHistogram(self.arr)
|
||||
self.layout.addWidget(self.rgbv_hist, 0, 1)
|
||||
self.rgbv_hist.show()
|
||||
|
||||
self.rgb_hsv_disp = RGBHSVDisplay()
|
||||
self.layout.addWidget(self.rgb_hsv_disp, 1, 0)
|
||||
self.rgb_hsv_disp.show()
|
||||
|
||||
self.layout.setColumnStretch(0, 1)
|
||||
self.layout.setRowStretch(0, 1)
|
||||
|
||||
self.save_file = QtGui.QPushButton('Save to File')
|
||||
self.save_file.clicked.connect(self.save_to_file)
|
||||
self.save_variable = QtGui.QPushButton('Save to Variable')
|
||||
self.save_variable.clicked.connect(self.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)
|
||||
|
||||
|
||||
def update_histograms(self):
|
||||
self.rgbv_hist.update_hists(self.arr)
|
||||
|
||||
def save_to_variable(self):
|
||||
from scikits.image import io
|
||||
from textwrap import dedent
|
||||
img = self.arr.copy()
|
||||
io.push(img)
|
||||
msg = dedent('''
|
||||
The image has been pushed to the io stack.
|
||||
Use io.pop() to retrieve the most recently pushed image.''')
|
||||
msglabel = QLabel(msg)
|
||||
dialog = QtGui.QDialog()
|
||||
ok = QtGui.QPushButton('OK', dialog)
|
||||
ok.clicked.connect(dialog.accept)
|
||||
ok.setDefault(True)
|
||||
dialog.layout = QtGui.QGridLayout(dialog)
|
||||
dialog.layout.addWidget(msglabel, 0, 0, 1, 3)
|
||||
dialog.layout.addWidget(ok, 1, 1)
|
||||
dialog.exec_()
|
||||
|
||||
|
||||
def save_to_file(self):
|
||||
from scikits.image import io
|
||||
filename = str(QtGui.QFileDialog.getSaveFileName())
|
||||
if len(filename) == 0:
|
||||
return
|
||||
io.imsave(filename, self.arr)
|
||||
|
||||
def refresh_image(self):
|
||||
self.label.update_image()
|
||||
self.update_histograms()
|
||||
|
||||
def scale_mouse_pos(self, x, y):
|
||||
width = self.label.pm.width()
|
||||
height = self.label.pm.height()
|
||||
x_frac = 1. * x / width
|
||||
y_frac = 1. * y / height
|
||||
width = self.arr.shape[1]
|
||||
height = self.arr.shape[0]
|
||||
new_x = int(width * x_frac)
|
||||
new_y = int(height * y_frac)
|
||||
return(new_x, new_y)
|
||||
|
||||
def label_mouseMoveEvent(self, evt):
|
||||
x = evt.x()
|
||||
y = evt.y()
|
||||
x, y = self.scale_mouse_pos(x, y)
|
||||
|
||||
# handle tracking out of array bounds
|
||||
maxw = self.arr.shape[1]
|
||||
maxh = self.arr.shape[0]
|
||||
if x >= maxw or y >= maxh or x < 0 or y < 0:
|
||||
r = g = b = h = s = v = ''
|
||||
else:
|
||||
r = self.arr[y,x,0]
|
||||
g = self.arr[y,x,1]
|
||||
b = self.arr[y,x,2]
|
||||
h, s, v = self.mixer_panel.mixer.rgb_2_hsv_pixel(r, g, b)
|
||||
|
||||
self.rgb_hsv_disp.update_vals((x, y, r, g, b, h, s, v))
|
||||
|
||||
|
||||
def imshow(arr, fancy=False):
|
||||
global app
|
||||
@@ -249,7 +85,8 @@ else:
|
||||
if not fancy:
|
||||
iw = ImageWindow(arr, window_manager)
|
||||
else:
|
||||
iw = FancyImageWindow(arr, window_manager)
|
||||
from scivi import SciviImageWindow
|
||||
iw = SciviImageWindow(arr, window_manager)
|
||||
|
||||
iw.show()
|
||||
|
||||
@@ -260,3 +97,17 @@ else:
|
||||
app.exec_()
|
||||
else:
|
||||
print 'No images to show. See `imshow`.'
|
||||
|
||||
|
||||
def imsave(filename, img):
|
||||
# we can support for other than 3D uint8 here...
|
||||
img = prepare_for_display(img)
|
||||
qimg = QImage(img.data, img.shape[1], img.shape[0],
|
||||
img.strides[0], QImage.Format_RGB888)
|
||||
saved = qimg.save(filename)
|
||||
if not saved:
|
||||
msg = dedent(
|
||||
'''The image was not saved. Allowable file formats
|
||||
for the QT imsave plugin are:
|
||||
BMP, JPG, JPEG, PNG, PPM, TIFF, XBM, XPM''')
|
||||
raise RuntimeError(msg)
|
||||
|
||||
@@ -0,0 +1,233 @@
|
||||
'''
|
||||
Scivi is written/maintained/developed by:
|
||||
|
||||
S. Chris Colbert - sccolbert@gmail.com
|
||||
|
||||
Scivi is free software and is part of the scikits.image project.
|
||||
|
||||
Scivi is governed by the licenses of the scikits.image project.
|
||||
|
||||
Please report any bugs to the author.
|
||||
|
||||
The scivi module is not meant to be used directly.
|
||||
|
||||
Use scikits.image.io.imshow(img, fancy=True)'''
|
||||
|
||||
from textwrap import dedent
|
||||
import numpy as np
|
||||
import sys
|
||||
|
||||
from PyQt4 import QtCore, QtGui
|
||||
from PyQt4.QtGui import (QApplication, QMainWindow, QImage, QPixmap,
|
||||
QLabel, QWidget, QVBoxLayout, QSlider,
|
||||
QPainter, QColor, QFrame, QLayoutItem)
|
||||
|
||||
from q_color_mixer import MixerPanel
|
||||
from q_histogram import QuadHistogram
|
||||
|
||||
|
||||
class ImageLabel(QLabel):
|
||||
def __init__(self, parent, arr):
|
||||
QLabel.__init__(self)
|
||||
self.parent = parent
|
||||
|
||||
# we need to hold a reference to
|
||||
# arr because QImage doesn't copy the data
|
||||
# and the buffer must be alive as long
|
||||
# as the image is alive.
|
||||
self.arr = arr
|
||||
|
||||
# we also need to pass in the row-stride to
|
||||
# the constructor, because we can't guarantee
|
||||
# that every row of the numpy data is
|
||||
# 4-byte aligned. Which Qt would require
|
||||
# if we didnt pass the stride.
|
||||
self.img = QImage(arr.data, arr.shape[1], arr.shape[0],
|
||||
arr.strides[0], QImage.Format_RGB888)
|
||||
self.pm = QPixmap.fromImage(self.img)
|
||||
self.setPixmap(self.pm)
|
||||
self.setAlignment(QtCore.Qt.AlignTop)
|
||||
self.setMinimumSize(100, 100)
|
||||
self.setMouseTracking(True)
|
||||
|
||||
def mouseMoveEvent(self, evt):
|
||||
self.parent.label_mouseMoveEvent(evt)
|
||||
|
||||
def resizeEvent(self, evt):
|
||||
width = self.width()
|
||||
pm = QPixmap.fromImage(self.img)
|
||||
self.pm = pm.scaledToWidth(width)
|
||||
self.setPixmap(self.pm)
|
||||
|
||||
def update_image(self):
|
||||
width = self.width()
|
||||
pm = QPixmap.fromImage(self.img)
|
||||
pm = pm.scaledToWidth(width)
|
||||
self.setPixmap(pm)
|
||||
|
||||
|
||||
class RGBHSVDisplay(QWidget):
|
||||
def __init__(self):
|
||||
QWidget.__init__(self)
|
||||
self.posx_label = QLabel('X-pos:')
|
||||
self.posx_value = QLabel()
|
||||
self.posy_label = QLabel('Y-pos:')
|
||||
self.posy_value = QLabel()
|
||||
self.r_label = QLabel('R:')
|
||||
self.r_value = QLabel()
|
||||
self.g_label = QLabel('G:')
|
||||
self.g_value = QLabel()
|
||||
self.b_label = QLabel('B:')
|
||||
self.b_value = QLabel()
|
||||
self.h_label = QLabel('H:')
|
||||
self.h_value = QLabel()
|
||||
self.s_label = QLabel('S:')
|
||||
self.s_value = QLabel()
|
||||
self.v_label = QLabel('V:')
|
||||
self.v_value = QLabel()
|
||||
|
||||
self.layout = QtGui.QGridLayout(self)
|
||||
self.layout.addWidget(self.posx_label, 0, 0)
|
||||
self.layout.addWidget(self.posx_value, 0, 1)
|
||||
self.layout.addWidget(self.posy_label, 1, 0)
|
||||
self.layout.addWidget(self.posy_value, 1, 1)
|
||||
self.layout.addWidget(self.r_label, 0, 2)
|
||||
self.layout.addWidget(self.r_value, 0, 3)
|
||||
self.layout.addWidget(self.g_label, 1, 2)
|
||||
self.layout.addWidget(self.g_value, 1, 3)
|
||||
self.layout.addWidget(self.b_label, 2, 2)
|
||||
self.layout.addWidget(self.b_value, 2, 3)
|
||||
self.layout.addWidget(self.h_label, 0, 4)
|
||||
self.layout.addWidget(self.h_value, 0, 5)
|
||||
self.layout.addWidget(self.s_label, 1, 4)
|
||||
self.layout.addWidget(self.s_value, 1, 5)
|
||||
self.layout.addWidget(self.v_label, 2, 4)
|
||||
self.layout.addWidget(self.v_value, 2, 5)
|
||||
|
||||
def update_vals(self, data):
|
||||
xpos, ypos, r, g, b, h, s, v = data
|
||||
self.posx_value.setText(str(xpos)[:5])
|
||||
self.posy_value.setText(str(ypos)[:5])
|
||||
self.r_value.setText(str(r)[:5])
|
||||
self.g_value.setText(str(g)[:5])
|
||||
self.b_value.setText(str(b)[:5])
|
||||
self.h_value.setText(str(h)[:5])
|
||||
self.s_value.setText(str(s)[:5])
|
||||
self.v_value.setText(str(v)[:5])
|
||||
|
||||
|
||||
|
||||
class SciviImageWindow(QMainWindow):
|
||||
def __init__(self, arr, mgr):
|
||||
QMainWindow.__init__(self)
|
||||
|
||||
self.arr = arr
|
||||
|
||||
self.mgr = mgr
|
||||
self.main_widget = QWidget()
|
||||
self.layout = QtGui.QGridLayout(self.main_widget)
|
||||
self.setCentralWidget(self.main_widget)
|
||||
|
||||
self.label = ImageLabel(self, arr)
|
||||
self.layout.addWidget(self.label, 0, 0)
|
||||
self.layout.addLayout
|
||||
self.mgr.add_window(self)
|
||||
self.main_widget.show()
|
||||
|
||||
self.setWindowTitle('Scivi - The scikits.image viewer.')
|
||||
|
||||
self.mixer_panel = MixerPanel(self.arr)
|
||||
self.layout.addWidget(self.mixer_panel, 0, 2)
|
||||
self.mixer_panel.show()
|
||||
self.mixer_panel.set_callback(self.refresh_image)
|
||||
|
||||
self.rgbv_hist = QuadHistogram(self.arr)
|
||||
self.layout.addWidget(self.rgbv_hist, 0, 1)
|
||||
self.rgbv_hist.show()
|
||||
|
||||
self.rgb_hsv_disp = RGBHSVDisplay()
|
||||
self.layout.addWidget(self.rgb_hsv_disp, 1, 0)
|
||||
self.rgb_hsv_disp.show()
|
||||
|
||||
self.layout.setColumnStretch(0, 1)
|
||||
self.layout.setRowStretch(0, 1)
|
||||
|
||||
self.save_file = QtGui.QPushButton('Save to File')
|
||||
self.save_file.clicked.connect(self.save_to_file)
|
||||
self.save_stack = QtGui.QPushButton('Save to Stack')
|
||||
self.save_stack.clicked.connect(self.save_to_stack)
|
||||
self.save_file.show()
|
||||
self.save_stack.show()
|
||||
|
||||
self.layout.addWidget(self.save_stack, 1, 1)
|
||||
self.layout.addWidget(self.save_file, 1, 2)
|
||||
|
||||
|
||||
def closeEvent(self, event):
|
||||
# Allow window to be destroyed by removing any
|
||||
# references to it
|
||||
self.mgr.remove_window(self)
|
||||
|
||||
def update_histograms(self):
|
||||
self.rgbv_hist.update_hists(self.arr)
|
||||
|
||||
def refresh_image(self):
|
||||
self.label.update_image()
|
||||
self.update_histograms()
|
||||
|
||||
def scale_mouse_pos(self, x, y):
|
||||
width = self.label.pm.width()
|
||||
height = self.label.pm.height()
|
||||
x_frac = 1. * x / width
|
||||
y_frac = 1. * y / height
|
||||
width = self.arr.shape[1]
|
||||
height = self.arr.shape[0]
|
||||
new_x = int(width * x_frac)
|
||||
new_y = int(height * y_frac)
|
||||
return(new_x, new_y)
|
||||
|
||||
def label_mouseMoveEvent(self, evt):
|
||||
x = evt.x()
|
||||
y = evt.y()
|
||||
x, y = self.scale_mouse_pos(x, y)
|
||||
|
||||
# handle tracking out of array bounds
|
||||
maxw = self.arr.shape[1]
|
||||
maxh = self.arr.shape[0]
|
||||
if x >= maxw or y >= maxh or x < 0 or y < 0:
|
||||
r = g = b = h = s = v = ''
|
||||
else:
|
||||
r = self.arr[y,x,0]
|
||||
g = self.arr[y,x,1]
|
||||
b = self.arr[y,x,2]
|
||||
h, s, v = self.mixer_panel.mixer.rgb_2_hsv_pixel(r, g, b)
|
||||
|
||||
self.rgb_hsv_disp.update_vals((x, y, r, g, b, h, s, v))
|
||||
|
||||
|
||||
def save_to_stack(self):
|
||||
from scikits.image import io
|
||||
img = self.arr.copy()
|
||||
io.push(img)
|
||||
msg = dedent('''
|
||||
The image has been pushed to the io stack.
|
||||
Use io.pop() to retrieve the most recently
|
||||
pushed image.''')
|
||||
msglabel = QLabel(msg)
|
||||
dialog = QtGui.QDialog()
|
||||
ok = QtGui.QPushButton('OK', dialog)
|
||||
ok.clicked.connect(dialog.accept)
|
||||
ok.setDefault(True)
|
||||
dialog.layout = QtGui.QGridLayout(dialog)
|
||||
dialog.layout.addWidget(msglabel, 0, 0, 1, 3)
|
||||
dialog.layout.addWidget(ok, 1, 1)
|
||||
dialog.exec_()
|
||||
|
||||
def save_to_file(self):
|
||||
from scikits.image import io
|
||||
filename = str(QtGui.QFileDialog.getSaveFileName())
|
||||
if len(filename) == 0:
|
||||
return
|
||||
io.imsave(filename, self.arr)
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
from numpy.testing import *
|
||||
import numpy as np
|
||||
|
||||
import scikits.image.io._plugins._colormixer as cm
|
||||
|
||||
class ColorMixerTest(object):
|
||||
def setup(self):
|
||||
self.state = np.ones((18, 33, 3), dtype=np.uint8) * 200
|
||||
self.img = np.zeros_like(self.state)
|
||||
|
||||
def test_basic(self):
|
||||
self.op(self.img, self.state, 0, self.positive)
|
||||
assert_array_equal(self.img[..., 0],
|
||||
self.py_op(self.state[..., 0], self.positive))
|
||||
|
||||
def test_clip(self):
|
||||
self.op(self.img, self.state, 0, self.positive_clip)
|
||||
assert_array_equal(self.img[..., 0],
|
||||
np.ones_like(self.img[..., 0]) * 255)
|
||||
|
||||
def test_negative(self):
|
||||
self.op(self.img, self.state, 0, self.negative)
|
||||
assert_array_equal(self.img[..., 0],
|
||||
self.py_op(self.state[..., 0], self.negative))
|
||||
|
||||
def test_negative_clip(self):
|
||||
self.op(self.img, self.state, 0, self.negative_clip)
|
||||
assert_array_equal(self.img[..., 0],
|
||||
np.zeros_like(self.img[..., 0]))
|
||||
|
||||
class TestColorMixerAdd(ColorMixerTest):
|
||||
op = cm.add
|
||||
py_op = np.add
|
||||
positive = 50
|
||||
positive_clip = 56
|
||||
negative = -50
|
||||
negative_clip = -220
|
||||
|
||||
class TestColorMixerMul(ColorMixerTest):
|
||||
op = cm.multiply
|
||||
py_op = np.multiply
|
||||
positive = 1.2
|
||||
positive_clip = 2
|
||||
negative = 0.5
|
||||
negative_clip = -0.5
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_module_suite()
|
||||
@@ -11,6 +11,7 @@ def configuration(parent_package='', top_path=None):
|
||||
|
||||
config = Configuration('io', parent_package, top_path)
|
||||
config.add_data_dir('tests')
|
||||
config.add_data_dir('_plugins/tests')
|
||||
config.add_data_files('_plugins/*.ini')
|
||||
|
||||
# This function tries to create C files from the given .pyx files. If
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
from numpy.testing import *
|
||||
import numpy as np
|
||||
|
||||
import scikits.image.io._plugins._colormixer as cm
|
||||
|
||||
class ColorMixerTest(object):
|
||||
def setup(self):
|
||||
self.state = np.ones((18, 33, 3), dtype=np.uint8) * 200
|
||||
self.img = np.zeros_like(self.state)
|
||||
|
||||
def test_basic(self):
|
||||
self.op(self.img, self.state, 0, self.positive)
|
||||
assert_array_equal(self.img[..., 0],
|
||||
self.py_op(self.state[..., 0], self.positive))
|
||||
|
||||
def test_clip(self):
|
||||
self.op(self.img, self.state, 0, self.positive_clip)
|
||||
assert_array_equal(self.img[..., 0],
|
||||
np.ones_like(self.img[..., 0]) * 255)
|
||||
|
||||
def test_negative(self):
|
||||
self.op(self.img, self.state, 0, self.negative)
|
||||
assert_array_equal(self.img[..., 0],
|
||||
self.py_op(self.state[..., 0], self.negative))
|
||||
|
||||
def test_negative_clip(self):
|
||||
self.op(self.img, self.state, 0, self.negative_clip)
|
||||
assert_array_equal(self.img[..., 0],
|
||||
np.zeros_like(self.img[..., 0]))
|
||||
|
||||
|
||||
class TestColorMixerAdd(ColorMixerTest):
|
||||
op = cm.add
|
||||
py_op = np.add
|
||||
positive = 50
|
||||
positive_clip = 56
|
||||
negative = -50
|
||||
negative_clip = -220
|
||||
|
||||
|
||||
class TestColorMixerMul(ColorMixerTest):
|
||||
op = cm.multiply
|
||||
py_op = np.multiply
|
||||
positive = 1.2
|
||||
positive_clip = 2
|
||||
negative = 0.5
|
||||
negative_clip = -0.5
|
||||
|
||||
|
||||
class TestColorMixerBright(object):
|
||||
|
||||
def setup(self):
|
||||
self.state = np.ones((18, 33, 3), dtype=np.uint8) * 200
|
||||
self.img = np.zeros_like(self.state)
|
||||
|
||||
def test_brightness_pos(self):
|
||||
cm.brightness(self.img, self.state, 1.25, 1)
|
||||
assert_array_equal(self.img, np.ones_like(self.img) * 251)
|
||||
|
||||
def test_brightness_neg(self):
|
||||
cm.brightness(self.img, self.state, 0.5, -50)
|
||||
assert_array_equal(self.img, np.ones_like(self.img) * 50)
|
||||
|
||||
def test_brightness_pos_clip(self):
|
||||
cm.brightness(self.img, self.state, 2, 0)
|
||||
assert_array_equal(self.img, np.ones_like(self.img) * 255)
|
||||
|
||||
def test_brightness_neg_clip(self):
|
||||
cm.brightness(self.img, self.state, 0, 0)
|
||||
assert_array_equal(self.img, np.zeros_like(self.img))
|
||||
|
||||
|
||||
class TestColorMixer(object):
|
||||
|
||||
def setup(self):
|
||||
self.state = np.ones((18, 33, 3), dtype=np.uint8) * 50
|
||||
self.img = np.zeros_like(self.state)
|
||||
|
||||
def test_sigmoid(self):
|
||||
import math
|
||||
alpha = 1.5
|
||||
beta = 1.5
|
||||
c1 = 1 / (1 + math.exp(beta))
|
||||
c2 = 1 / (1 + math.exp(beta - alpha)) - c1
|
||||
state = self.state / 255.
|
||||
cm.sigmoid_gamma(self.img, self.state, alpha, beta)
|
||||
img = 1 / (1 + np.exp(beta - state * alpha))
|
||||
img = np.asarray((img - c1) / c2 * 255, dtype='uint8')
|
||||
assert_almost_equal(img, self.img)
|
||||
|
||||
def test_gamma(self):
|
||||
gamma = 1.5
|
||||
cm.gamma(self.img, self.state, gamma)
|
||||
img = np.asarray(((self.state/255.)**(1/gamma))*255, dtype='uint8')
|
||||
assert_array_almost_equal(img, self.img)
|
||||
|
||||
def test_rgb_2_hsv(self):
|
||||
r = 255
|
||||
g = 0
|
||||
b = 0
|
||||
h, s, v = cm.py_rgb_2_hsv(r, g, b)
|
||||
assert_almost_equal(np.array([h]), np.array([0]))
|
||||
assert_almost_equal(np.array([s]), np.array([1]))
|
||||
assert_almost_equal(np.array([v]), np.array([1]))
|
||||
|
||||
def test_hsv_2_rgb(self):
|
||||
h = 0
|
||||
s = 1
|
||||
v = 1
|
||||
r, g, b = cm.py_hsv_2_rgb(h, s, v)
|
||||
assert_almost_equal(np.array([r]), np.array([255]))
|
||||
assert_almost_equal(np.array([g]), np.array([0]))
|
||||
assert_almost_equal(np.array([b]), np.array([0]))
|
||||
|
||||
|
||||
def test_hsv_add(self):
|
||||
cm.hsv_add(self.img, self.state, 360, 0, 0)
|
||||
assert_almost_equal(self.img, self.state)
|
||||
|
||||
def test_hsv_add_clip_neg(self):
|
||||
cm.hsv_add(self.img, self.state, 0, 0, -1)
|
||||
assert_equal(self.img, np.zeros_like(self.state))
|
||||
|
||||
def test_hsv_add_clip_pos(self):
|
||||
cm.hsv_add(self.img, self.state, 0, 0, 1)
|
||||
assert_equal(self.img, np.ones_like(self.state)*255)
|
||||
|
||||
def test_hsv_mul(self):
|
||||
cm.hsv_multiply(self.img, self.state, 360, 1, 1)
|
||||
assert_almost_equal(self.img, self.state)
|
||||
|
||||
def test_hsv_mul_clip_neg(self):
|
||||
cm.hsv_multiply(self.img, self.state, 0, 0, 0)
|
||||
assert_equal(self.img, np.zeros_like(self.state))
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_module_suite()
|
||||
+12
@@ -12,5 +12,17 @@ class TestHistogram:
|
||||
for band in (r, g, b, v):
|
||||
yield assert_equal, band.sum(), 50*50
|
||||
|
||||
def test_counts(self):
|
||||
channel = np.arange(255).reshape(51, 5)
|
||||
img = np.empty((51, 5, 3), dtype='uint8')
|
||||
img[:,:,0] = channel
|
||||
img[:,:,1] = channel
|
||||
img[:,:,2] = channel
|
||||
r, g, b, v = histograms(img, 255)
|
||||
assert_array_equal(r, g)
|
||||
assert_array_equal(r, b)
|
||||
assert_array_equal(r, v)
|
||||
assert_array_equal(r, np.ones(255))
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_module_suite()
|
||||
Reference in New Issue
Block a user