简体   繁体   中英

Transfer data between Python objects and numpy arrays?

I am working with images, and I am working with a list of objects of a class I've written, Pixel(x, y) . I am often having to perform operations like this -

std_dev = np.array(map(lambda x: x.std_dev, pixels))
# numpy processing on std_dev ---> new_property
for i, p in enumerate(pixels):
    p.new_property = new_property[i]

What is the most efficient way to "move" this data between Python objects and numpy ? I want to keep the Pixel class, since I would need it for more fine-grained processing on parts of the image.

Update #1
Yes, pixels is a list of Pixel objects. I want to apply gaussian smoothing on a standard deviation map of the image. Every image pixel in the image has a standard deviation value associated to it. I am more interested in a general solution to the above problem rather than my specific case of Gaussian convolution.

You could let all your Pixels know their indices and share the same dictionary of ndarrays as a property->values map. Then use the dictionary key to access your Pixel's property and the Pixel's index to access the position within that property's array. This way your Pixels become something like pointers into those arrays. You'd have to keep the dictionary at a central location, though. For convenience I'd create a master or factory class.
Something like this:

class Pixel(object):
    def __init__(self, x, y, properties):
        # _properties has to be assigned first!
        self._properties = properties
        self._x = x
        self._y = y

    def __getattribute__(self, attr):
        try:
            return super().__getattribute__(attr)
        except AttributeError:
            return self._properties[attr][self._x, self._y]

    def __setattr__(self, attr, value):
        if attr != '_properties' and attr in self._properties:
            self._properties[attr][self._x, self._y] = value
        else:
            super().__setattr__(attr, value)

class Pixelmaster(object):

    def __init__(self, width, height):
        self.properties = dict()
        self.pixels = np.array([[Pixel(x, y, self.properties) for y in range(height)] for x in range(width)])

    def setProperty(self, prop, value):
        if value.shape != self.pixels.shape:
            raise ValueError('Value has wrong shape %s, should have %s!' % (value.shape, self.pixels.shape))
        self.properties[prop] = value
        return value

    def newProperty(self, prop, dtype=float):
        return self.setProperty(prop, np.empty_like(self.pixels, dtype=dtype))

    def getProperty(self, prop):
        return self.properties[prop]

With this you can do stuff like:

master = Pixelmaster(100,100)
# get pixel at position 0, 0
p = master.pixels[0, 0]

# create a new property
master.setProperty('std',np.random.rand(100,100))

print(p.std)

# reassign the pixel's value
p.std = 5

# value is updated at the master...
print(master.properties['std'][0,0])

# ...as well as the pixel itself
print(p.std)

Output:

0.6587814533631399
5.0
5.0

I think you know where to go from here.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM