DIPlib / diplib

Quantitative Image Analysis in C++, MATLAB and Python
https://diplib.org
Apache License 2.0
211 stars 48 forks source link

Expose ChainCode::PrepareCodeTable in Python? #122

Closed anntzer closed 1 year ago

anntzer commented 1 year ago

Component PyDIP 3.3.0

Describe the bug AFAICT, PyDIP currently doesn't expose PrepareCodeTable (or Code.Delta4()/Code.Delta8()), which means that one cannot convert a list of chaincodes into a list of coordinates (other than by copy-pasting and hard-coding the deltas4/deltas8 tables given in chain_code.h). Actually the API of PrepareCodeTable is slightly unpythonic (I guess the pointer offsets are usually irrelevant for a python caller), so it may be even better to have e.g. PrepareCodeTable() take no args and just return the position offsets table, but sticking to the C++ API would be fine too.

To Reproduce N/A

System information:

crisluengo commented 1 year ago

Use the Polygon() method to convert the chain codes to coordinates. Though it doesn't return the coordinates of pixels around the edge of the object, but rather coordinates in between the object and background pixels.

We could expose the PrepareCodeTable() method, returning only the position offsets as a list of 2-tuples (which would be straight-forward to convert to a NumPy array). I agree the offsets are likely not useful in Python code, none of the Image methods that use an offset for indexing are exposed to Python. But then we might as well expose the deltas4 and deltas8 arrays (they're currently not documented, but public).

The alternative is to add a method similar to Polygon() that converts the chain codes to the corresponding pixel coordinates. This could be added to the C++ API, and exposed to Python. Maybe Coordinates(), returning a dip::CoordinateArray.

anntzer commented 1 year ago

Unless I am mistaken, Polygon() doesn't allow (at least from Python) to convert to coordinates either?

crisluengo commented 1 year ago

The dip.Polygon object returned uses the buffer protocol, so you can cast it to a NumPy array. It actually implicitly casts, so you can directly use it as input to NumPy functions. You can also index it directly to get back an (x,y) tuple, and iterate over it.

anntzer commented 1 year ago

Ah, sorry, I didn't realize that, thanks for pointing this out.

Still, what I care about is indeed the pixels on the edge, not the coordinates between object and background, so some way of getting coordinates from the chaincode would be appreciated.

anntzer commented 1 year ago

Thanks for the quick fix :)