Skip to content

Commit

Permalink
Merge branch 'main' of github.com:ivapylibs/trackpointer into main
Browse files Browse the repository at this point in the history
  • Loading branch information
pv33 committed Jul 1, 2022
2 parents ad47b41 + 9458f86 commit a31dfb7
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 105 deletions.
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
# trackpointers
Implementations of trackpointer methods. Track object by giving track point or track coordinate frame.

## installation instruction
## Install

Install the following repositories from the source:

- [improcessor](https://github.com/ivapylibs/improcessor)
- [detector](https://github.com/ivapylibs/detector.git)
- [Lie](https://github.com/ivapylibs/Lie)

```
git clone [email protected]:ivapylibs/trackpointer.git
Expand All @@ -11,5 +17,5 @@ pip3 install -e trackpointer/
The test files are shell command line executable and should work when
invoked, presuming that pip installation has been performed. If no
modifications to the source code will be performed then the ``-e`` flag
is not neessary (e.g., use the flag if the underlying code will be
is not necessary (e.g., use the flag if the underlying code will be
modified).
5 changes: 3 additions & 2 deletions testing/fakeTri02.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@
import numpy as np
import matplotlib.pyplot as plt

from fakeTriangle import fakeTriangle
from trackpointer.utils.fakeTriangle import fakeTriangle
import Lie.group.SE2.Homog

#==[1] Specify the marker geometry on the rigid body, and other related
# parameters. Instantiate the simulated image generator.
#
Expand Down Expand Up @@ -83,4 +84,4 @@
plt.draw()

#
#=============================== fakeTri02 ===============================
#=============================== fakeTri02 ===============================
8 changes: 4 additions & 4 deletions testing/trackTri01.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import numpy as np
import matplotlib.pyplot as plt

from fakeTriangle import fakeTriangle
from trackpointer.utils.fakeTriangle import fakeTriangle
import Lie.group.SE2.Homog
import improcessor.basic as improcessor
import detector.inImage as detector
Expand Down Expand Up @@ -106,18 +106,18 @@
dI = binDet.Ip

trackptr.process(dI)
tstate = trackptr.getstate()
tstate = trackptr.getState()

# @todo
# There is no setting in the trackTri01.m to enable the display of the tracker as it uses
# triangleSE2 instead of centroid, which are slightly different in their displayState functions.
# For now, we manully set the state.
if ii==0:
# Start tracking
trackptr.setstate(tstate.tpt)
trackptr.setState(tstate)

plt.cla()
trackptr.displayState(tstate)
trackptr.displayState()

plt.imshow(I, cmap='Greys')
plt.pause(0.001)
Expand Down
8 changes: 4 additions & 4 deletions testing/trackTri02.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
import numpy as np
import matplotlib.pyplot as plt

from fakeTriangle import fakeTriangle
from trackpointer.utils.fakeTriangle import fakeTriangle
import Lie.group.SE2.Homog
import improcessor.basic as improcessor
import detector.inImage as detector
Expand Down Expand Up @@ -123,18 +123,18 @@
dI = binDet.Ip

trackptr.process(dI)
tstate = trackptr.getstate()
tstate = trackptr.getState()

# @todo
# There is no setting in the trackTri01.m to enable the display of the tracker as it uses
# triangleSE2 instead of centroid, which are slightly different in their displayState functions.
# For now, we manully set the state.
if ii==0:
# Start tracking
trackptr.setstate(tstate.tpt)
trackptr.setState(tstate)

plt.cla()
trackptr.displayState(tstate)
trackptr.displayState()

plt.imshow(I, cmap='Greys')
plt.pause(0.001)
Expand Down
90 changes: 50 additions & 40 deletions trackpointer/centroid.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,22 @@

import numpy as np
import matplotlib.pyplot as plt
from dataclasses import dataclass

class State(object):

def __init__(self, tpt=None, haveMeas=None):
self.tpt = tpt
self.haveMeas = haveMeas
@dataclass
class State:
tpt: np.ndarray = np.array([])
haveMeas: bool = False

@dataclass
class Params(object):
"""The parameters for the centroid tracker
def __init__(self):
pass
Args:
plotStyle (str): The plot style from the matplotlib for the centroid. Defaults to "rx". \
Detailed choices see: https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.plot.html
"""
plotStyle:str = "rx"

class centroid(object):

Expand All @@ -56,17 +61,20 @@ class centroid(object):
# @param[in] iPt The initial track point coordinates.
# params The parameter structure.
#
def __init__(self, iPt=None, params=None):

if iPt:
self.tpt = iPt
def __init__(self, iPt=None, params=Params()):

if params is None:
if not isinstance(params, Params):
params = self.setIfMissing(params,'plotStyle','rx')

self.tparams = params
self.haveMeas = False

if iPt:
self.tpt = iPt
self.haveMeas = True
else:
self.tpt = None

#=============================== set ===============================
#
# @brief Set parameters for the tracker.
Expand Down Expand Up @@ -94,37 +102,37 @@ def get(self, fname):

pass

#============================= emptystate ============================
#============================= emptyState ============================
#
# @brief Return an empty state structure.
#
#
def emptystate(self):
def emptyState(self):

estate= State(tpt=[], haveMeas=False)
estate= State(tpt=np.array([]), haveMeas=False)

return estate

#============================== setstate =============================
#============================== setState =============================
#
# @brief Set the state vector.
#
# @param[in] g The desired state.
# @param[in] dPt The desired state.
#
def setstate(self, g):
def setState(self, dPt):

self.tpt = g
self.haveMeas = True
self.tpt = dPt.tpt
self.haveMeas = dPt.haveMeas



#============================== getstate =============================
#============================== getState =============================
#
# @brief Return the track-pointer state.
#
# @param[out] tstate The track point state structure.
#
def getstate(self):
def getState(self):

tstate = State(tpt=self.tpt, haveMeas=self.haveMeas)

Expand Down Expand Up @@ -177,22 +185,18 @@ def measure(self, I):
else:
Ip = I


# y,x in OpenCV
ibin, jbin = np.nonzero(Ip)

self.tpt = np.array([np.mean(jbin), np.mean(ibin)]).reshape(-1,1)

self.haveMeas = self.tpt.shape[1] > 0

# center = transpose(size(image)*[0 1;1 0]+1)/2;
# trackpoint = trackpoint - center;
if ibin.size == 0:
self.tpt = None
self.haveMeas = False
else:
# x,y in OpenCV
self.tpt = np.array([np.mean(jbin), np.mean(ibin)]).reshape(-1,1)
self.haveMeas = True

# @todo
# Not sure if the translation is correct
# if (nargout == 1):
# mstate = this.getstate();
# end
mstate = self.getstate()
mstate = self.getState()

return mstate

Expand All @@ -215,14 +219,20 @@ def process(self, I):
# existing elements that should remain, then hold should be enabled prior to
# invoking this function.
#
def displayState(self, dstate = None):
def displayState(self, dstate = None, ax=None):

if dstate:
if ax is None:
ax = plt.gca()

if isinstance(dstate, State):
if dstate.haveMeas:
plt.plot(dstate.tpt[0,:], dstate.tpt[1,:], self.tparams.plotStyle)
# Change to OpenCV style
ax.plot(dstate.tpt[0,:], dstate.tpt[1,:], self.tparams.plotStyle)
else:
if self.haveMeas:
plt.plot(self.tpt[0,:], self.tpt[1,:], self.tparams.plotStyle)
# Change to OpenCV style
ax.plot(self.tpt[0,:], self.tpt[1,:], self.tparams.plotStyle)



#========================= displayDebugState =========================
Expand All @@ -249,7 +259,7 @@ def setIfMissing(self, params, pname, pval):

# @todo
# Need double check on this translation
if params is None or not isinstance(params):
if not isinstance(params, Params):
params = Params()
setattr(params, pname, pval)
return params
Expand Down
67 changes: 14 additions & 53 deletions trackpointer/centroidMulti.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,10 @@
#================================ centroid ===============================

import numpy as np
import matplotlib.pyplot as plt
import cv2

from skimage.measure import regionprops
from trackpointer.centroid import centroid

class State(object):

def __init__(self, tpt=None, haveMeas=None):
self.tpt = tpt
self.haveMeas = haveMeas

class Params(object):

def __init__(self):
pass
from trackpointer.centroid import centroid, State, Params

class centroidMulti(centroid):

Expand All @@ -59,9 +47,9 @@ class centroidMulti(centroid):
# @param[in] iPt The initial track point coordinates.
# params The parameter structure.
#
def __init__(self, iPt=None, params=None):
def __init__(self, iPt=None, params=Params()):

super(centroidMulti,self).__init__(iPt,params)
super(centroidMulti,self).__init__(iPt, params)


#=============================== set ===============================
Expand Down Expand Up @@ -106,16 +94,14 @@ def measure(self, I):
Ip = I

binReg = centroidMulti.regionProposal(Ip)
self.tpt = np.array(binReg).T # from N x 2 to 2 x N
self.tpt = np.array(binReg).T # from N x 2 to 2 x N

self.haveMeas = self.tpt.shape[1] > 0
if len(self.tpt) == 0:
self.haveMeas = False
else:
self.haveMeas = self.tpt.shape[1] > 0

# @todo
# Not sure if the translation is correct
# if (nargout == 1):
# mstate = this.getstate();
# end
mstate = self.getstate()
mstate = self.getState()

return mstate

Expand All @@ -129,34 +115,6 @@ def process(self, I):

self.measure(I)

#============================ displayState ===========================
#
# @brief Displays the current track pointer measurement.
#
# Assumes that the current figure to plot to is activate. If the plot has
# existing elements that should remain, then hold should be enabled prior to
# invoking this function.
#
def displayState(self, dstate = None):

if dstate:
if dstate.haveMeas:
plt.plot(dstate.tpt[0,:], dstate.tpt[1,:], self.tparams.plotStyle)
else:
if self.haveMeas:
plt.plot(self.tpt[0,:], self.tpt[1,:], self.tparams.plotStyle)


#========================= displayDebugState =========================
#
# @brief Displays internally stored intermediate process output.
#
# Currently, there is no intermediate output, though that might change
# in the future.
#
def displayDebugState(self, dbstate=None):
pass

#========================= regionProposal =========================
#
# @brief Find out the centroid for multiple objects
Expand All @@ -165,8 +123,9 @@ def displayDebugState(self, dbstate=None):
#
@ staticmethod
def regionProposal(I):
mask = np.zeros_like(I)
cnts = cv2.findContours(I, cv2.RETR_EXTERNAL,
Ip = I.astype(np.uint8)
mask = np.zeros_like(Ip)
cnts = cv2.findContours(Ip, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
# For OpenCV 4+
cnts = cnts[0]
Expand All @@ -176,6 +135,8 @@ def regionProposal(I):

# Note that regionprops assumes different areas are with different labels
# See https://stackoverflow.com/a/61591279/5269146

# Have been transferred to the OpenCV style as regionprops is from skimage
binReg = [[i.centroid[1], i.centroid[0]] for i in regionprops(mask)]

return binReg
Expand Down
Empty file added trackpointer/utils/__init__.py
Empty file.
File renamed without changes.

0 comments on commit a31dfb7

Please sign in to comment.