Files
scikit-image/skimage/io/_plugins/skivi.py
T
2012-03-03 11:18:16 -08:00

243 lines
7.9 KiB
Python

'''
Skivi is written/maintained/developed by:
S. Chris Colbert - sccolbert@gmail.com
Skivi is free software and is part of the scikits-image project.
Skivi is governed by the licenses of the scikits-image project.
Please report any bugs to the author.
The skivi module is not meant to be used directly.
Use skimage.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(QFrame):
def __init__(self):
QFrame.__init__(self)
self.setFrameStyle(QtGui.QFrame.Box|QtGui.QFrame.Sunken)
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 SkiviImageWindow(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.label_container = QFrame()
self.label_container.setFrameShape(QtGui.QFrame.StyledPanel|QtGui.QFrame.Sunken)
self.label_container.setLineWidth(1)
self.label_container.layout = QtGui.QGridLayout(self.label_container)
self.label_container.layout.setMargin(0)
self.label_container.layout.addWidget(self.label, 0, 0)
self.layout.addWidget(self.label_container, 0, 0)
self.mgr.add_window(self)
self.main_widget.show()
self.setWindowTitle('Skivi - The skimage 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 skimage 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 skimage import io
filename = str(QtGui.QFileDialog.getSaveFileName())
if len(filename) == 0:
return
io.imsave(filename, self.arr)