# -*- coding: utf-8 -*-
"""
.. module:: segment
:synopsis: helper module for image segmentation
"""
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
import tkFileDialog
import pickle
# inspired by: http://matplotlib.org/examples/widgets/buttons.html
[docs]class SegmentUI():
"""Class for performing manual point feature extraction.
"""
def __init__(self, I, data={}, Nclicks=1, block=True):
"""Constructor.
:param np.array I: Nf x Nr x Nc (frames number x image row size x image column size) array containing grey levels data.
:param int Nclicks: number of point features to be extracted.
:param dict data: dictionary when keys a frame values and values are list of tuples. Each tuple represents coordinates for a
single point in the image.
:param bool block: if to block the window or not.
In interactive Python shell mode, if True, it shows the main window and disables buttons usage. These have to be called
manually from command line. If False, program flow is interrupted until the main window is closed, and buttons usage is enabled.
In script mode, if True, it has the same behaviour as interactive shell. In this mondality, False value has no meaning since no
window is shown.
"""
# Set sttributes
self.I = I
self.J, self.M, self.N = I.shape
self.data = data
self.Nclicks = Nclicks
self.ind = 0
# Create plot area
fig, self.ax = plt.subplots()
# Crete current idx text
axidx = plt.axes([0.5, 0.15, 0.05, 0.065])
axidx.set_axis_off()
self.txt = plt.text(0, 0.5, '', axes=axidx)
# Show first image
self._showImage()
self._showPoints()
self._showCurrentIdx()
# Define buttons
axclick = plt.axes([0.09, 0.15, 0.1, 0.075])
axreset = plt.axes([0.20, 0.15, 0.1, 0.075])
axfileload = plt.axes([0.09, 0.05, 0.1, 0.075])
axfilesave = plt.axes([0.20, 0.05, 0.1, 0.075])
axprev = plt.axes([0.7, 0.15, 0.1, 0.075])
axnext = plt.axes([0.81, 0.15, 0.1, 0.075])
bclick = Button(axclick, 'Click')
bclick.on_clicked(self.click)
breset = Button(axreset, 'Reset')
breset.on_clicked(self.reset)
bfileload = Button(axfileload, 'Load...')
bfileload.on_clicked(self.fileLoad)
bfilesave = Button(axfilesave, 'Save...')
bfilesave.on_clicked(self.fileSave)
bnext = Button(axnext, 'Next')
bnext.on_clicked(self.next)
bprev = Button(axprev, 'Previous')
bprev.on_clicked(self.prev)
# Adjust borders
plt.subplots_adjust(bottom=0.3)
# Plot
plt.show(block=block)
def _showImage(self):
plt.sca(self.ax)
plt.cla()
plt.imshow(self.I[self.ind,:,:].squeeze(), cmap=plt.cm.binary)
plt.xlim(0, self.N)
plt.ylim(self.M, 0)
[docs] def next(self, event):
# Calculate index
self.ind += 1
self.ind = self.ind % self.J
self._showCurrentIdx()
# Replot image
self._showImage()
# Plot points
self._showPoints()
[docs] def prev(self, event):
# Calculate index
self.ind -= 1
self.ind = self.ind % self.J
self._showCurrentIdx()
# Replot image
self._showImage()
# Plot points
self._showPoints()
[docs] def click(self, event):
pts = plt.ginput(self.Nclicks)
self.data[self.ind] = pts
self._showPoints()
[docs] def reset(self, event):
del self.data[self.ind]
self._clearPoints()
def _showPoints(self):
if self.ind in self.data:
pts = self.data[self.ind]
for i in xrange(0, len(pts)):
plt.sca(self.ax)
plt.plot(pts[i][0], pts[i][1], 'ro')
plt.xlim(0, self.N)
plt.ylim(self.M, 0)
def _clearPoints(self):
plt.sca(self.ax)
self._showImage()
def _showCurrentIdx(self):
self.txt.set_text(str(self.ind+1) + '/' + str(self.J))
[docs] def getData(self):
return self.data
[docs] def fileLoad(self, event):
# Select path
filePath = tkFileDialog.askopenfilename()
if len(filePath) == 0:
return
# Load file
with open(filePath, "rb") as f:
self.data = pickle.load(f)
# Plot points
self._showPoints()
[docs] def fileSave(self, event):
# Select path
filePath = tkFileDialog.asksaveasfilename()
if len(filePath) == 0:
return
# Save file
with open(filePath, "wb") as f:
pickle.dump(self.data, f, protocol=pickle.HIGHEST_PROTOCOL)
if __name__ == '__main__':
from image_utils import *
print 'reading dicom...'
D, ds = readDICOM('C:/Users/Davide Monari/Desktop/KULeuvenJob/PythonSoftware/Ultrasound/test_cal_dyn_18mar/test12cal_50mm_Mevis.dcm', method='flattened')
I = pixelData2grey(D)
print 'running ui'
ui = SegmentUI(I, Nclicks=2, block=False)
print 'getting points'
print ui.getData()