# CellTracking.py
# By MW, Jun 2013
# GPLv3+
#
# Class managing the display of a cell instance
import logging, cv2, numpy, gtk
[docs]class GtkCell :
"""A generic class for handling cell creation (get polygon as successive clicks)"""
def __init__(self, cells, state) :
self.state = state
self.cells = cells
self.eps = 7 # A distance in pixels
self.points = []
self.closed = False
self.type = 'pol'
self.cell = None
self.panel = None
self.selected = False
self.r_panel = None
self.radiobutton = None # The button on the cell l_panel
self.radiobutton_none = None # The widget to select to uselect all
self.visible = True
self.selected_handle = None
[docs] def get_selected(self) :
return self.selected
[docs] def set_r_panel(self, panel) :
self.r_panel = panel
[docs] def set_selected(self, sel) :
logging.debug("cell %s %s", self.get_name(), ['unselected', 'selected'][sel])
self.selected = sel
self.radiobutton.set_active(sel)
self.radiobutton.set_sensitive(self.visible)
if not self.visible and sel:
self.radiobutton_none.set_active(True)
[docs] def get_name(self) :
"""Return the name of the cell"""
if self.closed :
return self.cell.get_name()
else :
logging.warning("Trying to get the name of a temporary cell")
return "TMP cell"
[docs] def rb_toggled(self, active) :
self.selected = active
if active :
if self.r_panel.get_child() != None :
self.r_panel.remove(self.r_panel.get_child())
l = gtk.Label('testbabou!'+self.get_name())
l.show()
self.r_panel.add_with_viewport(l)
[docs] def get_panel(self, rb, rb_none) :
"""Return the panel to manage a cell
rb is the radiobutton instance determining which
cell is selected"""
# Create expander and header
self.panel = gtk.Expander(label="Cell: "+self.get_name())
self.radiobutton = rb
self.radiobutton_none = rb
header_cb = gtk.CheckButton("Show")
header_cb.set_active(self.visible)
header_cb.connect('clicked', self.show_evt)
box = gtk.HBox()
box.pack_start(header_cb, fill=False, expand=False)
box.pack_start(gtk.VSeparator(), expand=False, fill=False)
box.pack_start(self.panel, fill=False, expand=False)
box.show_all()
# Fill panel
l = gtk.Label('Not implemented yer!')
l.show()
self.panel.add(l)
#self.panel.set_label_widget(header)
return box
[docs] def show_evt(self, evt) :
self.visible = evt.get_active()
self.set_selected(evt.get_active())
[docs] def unclick(self) :
"""Function called when the user click is released"""
self.selected_handle = None
[docs] def click(self, tup) :
"""Function that receive a click from the viewer.
This function returns True if the click lies inside the cell (core or reference polygon)
In theory, the coordinates already have been converted"""
if self.visible :
i = self.state.get_subclass('player').get_current_index()
in_c = self.cell.is_point_in_cell(tup, i)
in_r = self.cell.is_point_in_ref(tup, i)
if self.selected_handle == None :
self.selected_handle = self.cell.is_point_on_cell_handle(tup, i)
if self.selected_handle == None :
self.selected_handle = self.cell.is_point_on_ref_handle(tup, i)
if in_c or in_r or (self.selected_handle != None):
# Select cell
logging.debug("%s selected", str(self.get_name()))
# update clickable panel
##self.radiobutton.set_active(True)
##self.selected = True
self.set_selected(True)
return True
else :
#unselect cell
logging.debug("%s unselected", str(self.get_name()))
self.set_selected(False)
##self.selected = False
##self.radiobutton.set_active(False)
return False
return False
[docs] def move(self, tup) :
"""Function called when the cell is selected and the user tries to
drag'n'drop it"""
#print 'moving point %s' % self.selected_handle
# Get selected feature
# Update according to the selected feature
[docs] def get_type(self) :
"""Return the cell type ('pol' for instance)"""
return self.type
[docs] def add_point(self, tup) :
if not self.closed :
if (len(self.points)>=1) and (self.dist(self.points[0], tup)<self.eps) :
self.close() # Close the polygon
return False # erase tmp_cell
else :
self.points.append(tup)
print "point added: %s" % str(tup)
else :
logging.warning("Trying to add a point to a closed polygon")
[docs] def reset_polygon(self) :
self.points = []
self.state.get_subclass('player').set_current_frame(None) # updating display
[docs] def close(self) :
"""Function that close the polygon and create a new cell instance instead"""
n = self.cells.get_name() # Get an unused name
self.cell = self.cells.new_cell(str(n))
i = self.state.get_subclass('player').get_current_index()
self.cell.reset_polygon(self.points, i)
self.closed = True
[docs] def dist(self, p1, p2) :
s = 0
for i in range(len(p1)) :
s += (p1[i]-p2[i])**2
return s**0.5
[docs] def draw_polygon(self, im) :
"""Draw the polygon on the image
:param im: the image to draw on.
:param type: a numpy matrix (x*y*3)
:returns: numpy matrix -- the output image"""
if self.visible :
if self.closed :
i = self.state.get_subclass('player').get_current_index()
points = self.cell.cell_pol.get_polygon(i)
if self.selected :
color = (255,0,0)
else :
color = (0,0,255)
else :
points = self.points
color = (255,0,0)
tuplist = points
if len(tuplist)==1 : # Draw first point if necessary
p = tuplist[0]
cv2.circle(im, (int(p[0]), int(p[1])), 3, color=color)
# Draw polygon
#if self.points != [] : # Not sure whether this is required...
if points != [] :
cv2.polylines(im, [numpy.array(tuplist, dtype=numpy.int32)], self.closed, color=color)
if self.closed :
center = numpy.array(tuplist).mean(axis=0)
cv2.circle(im,tuple(numpy.int_(center)), 5, color=color)
for p in tuplist :
cv2.circle(im, (int(p[0]), int(p[1])), 3, color=color)
coord = (int(tuplist[0][0]), int(tuplist[0][1])-3)
cv2.putText(im, self.get_name(), coord, cv2.FONT_HERSHEY_PLAIN, fontScale=1,color=color)
return im
[docs]class GtkRect(GtkCell) :
"""A generic class to handle polygons as untilted rectangles"""
def __init__(self, cells, state) :
self.state = state
TmpCell.__init__(self, cells)
[docs]class GtkRect_ct(GtkRect) :
def __init__(self, cells, state) :
self.state = state
TmpCell.__init__(self, cells)
[docs]class GtkRect_tp(GtkRect) :
def __init__(self, cells, state) :
self.state = state
TmpCell.__init__(self, cells)