0

I'm working on creating a vision tracking program using a pipeline. In my pipeline I have the following code:

@staticmethod
def __approx_contours(input_contours):
    output = []
    kp = None
    for contour in input_contours:
        error = 0.1*cv2.arcLength(contour, True)
        approx = cv2.approxPolyDP(contour, error, True)
        print(approx)
        kp = Keeper(approx)
        print(kp)
    if kp == None:
        return output
    for x,y in zip(kp.getX(),kp.getY()):
        output.append((x,y))
    kp.empty()
    return output

and here is Keeper class

class Keeper:

    _x = []
    _y = []

    # constructor, requires a 3-D array
    def __init__(self, third_dim):
        if third_dim.ndim == 3:
            for row in third_dim:
                for col in row:
                    self._x.append(col[0])
                    self._y.append(col[1])
        else:
            raise NotThirdDimension("Entered array was not three dimensional")
        print(self._x)
        print(self._y)

    # return object "X" array
    def getX(self):
        return self._x

    # return object "Y" array
    def getY(self):
        return self._y

    def empty(self):
        self._x = []
        self._y = []

Disregard the print statements in __init__, they are only for debugging purposes.

Example output in current state:

[[[183 169]]

 [[187 323]]]
Keeper
[183, 187]
[169, 323]
<keeper.Keeper object at 0x05199630>

[[[ 62 117]]

 [[ 93 366]]

 [[187 256]]]
Keeper
[183, 187, 62, 93, 187]
[169, 323, 117, 366, 256]
<keeper.Keeper object at 0x06F10B70>

It appears that the values in my Keeper object are not being reset, despite calling kp.empty(). I've also noted that the Keeper object is changing place in memory, perhaps this is part of the issue but I'm not sure where I am going wrong. Full code is available here

Miki
  • 40,887
  • 13
  • 123
  • 202
darkman9333
  • 131
  • 1
  • 2
  • 12
  • You shouldn't write getters and setters in Python. Also, you've made `_x` and `_y` *class attributes*, which likely isn't what you intended. Furthermore, your `__approx_contours` method should probably just be a module-level function rather than a static method... why the `__` name-mangling? Is this a use-case for name-mangling? If not, then don't do it. In sum, `Python != Java` – juanpa.arrivillaga Jan 28 '17 at 03:23
  • How exactly are you calling calling your static method? You only empty it at the end. Likely, the issue is arising because you make `_x` and `_y` *class variable* instead of *instance variables*. Then, when you do `self._x = []; self._y = []` in `empty` you *create new instance variables that shadow the class variables*. But you've already mutated the class variables, and the changes will still be visible even if you use `empty`. – juanpa.arrivillaga Jan 28 '17 at 03:32
  • 1
    Also, the `Keeper` object isn't changing place in memory, you are making a new obect every iteration of your loop: `kp = Keeper(approx)`. – juanpa.arrivillaga Jan 28 '17 at 03:35
  • @juanpa.arrivillaga I call my static method in [this](https://bitbucket.org/gauszman/python-vision-pipeline/src/b10ea3cbf12d242c7192e9e6bd7e235f3e1051cb/runner.py?at=master&fileviewer=file-view-default) class – darkman9333 Jan 28 '17 at 03:46
  • I am almost sure the problem is that you've definied `_x` and `_y` as **class attributes** rather than **instance attributes**. – juanpa.arrivillaga Jan 28 '17 at 03:48
  • @juanpa.arrivillaga By that you mean the `_` in front of them? I've made the change and I still have the same issue - x and y are not resetting, they accumulate. – darkman9333 Jan 28 '17 at 03:51
  • 1
    No, adding a single `_` does absolutely nothing out of the ordinary. You've made it a **class attribute**. http://stackoverflow.com/questions/207000/python-difference-between-class-and-instance-attributes – juanpa.arrivillaga Jan 28 '17 at 03:53
  • 1
    Again, you are clearly trying to write Java in Python. They are not the same language. Please check out a Python-specific tutorial on OOP. The [official tutorial](https://docs.python.org/3/tutorial/classes.html) is actually quite good. – juanpa.arrivillaga Jan 28 '17 at 03:56
  • @juanpa.arrivillaga Ok, I think I understand my issue. I'm still new to python and my first language was Java. Thank you for clarifying and providing insight. – darkman9333 Jan 28 '17 at 04:01

1 Answers1

2

The issue was as user @juanpa.arrivillaga said, I was using class attributes instead of instance attributes. To remedy my issue the following changes needed to be made to Keeper:

class Keeper:

    # constructor, requires a 3-D array
    def __init__(self, third_dim):
        self.x = []
        self.y = []
        if third_dim.ndim == 3:
            for row in third_dim:
                for col in row:
                    self.x.append(col[0])
                    self.y.append(col[1])
darkman9333
  • 131
  • 1
  • 2
  • 12