I’m trying to use HoughTransform2DLinesImageFilter in python. However, I cannot understand how to use the output of the GetLines() method.
AFAIU, the filter should return a list o the lines detected: how do I iterate over this list? How do access to the parameters of the lines?
What I’m trying to do, is to apply the hough transform for lines to an image and get the lines found by the algorithm.
Here is a sample of the code I’m using
houghF = itk.HoughTransform2DLinesImageFilter[itk.F, itk.F].New()
I expected the var “DetectedLines” to be a list/array of 2 entries. However, it is ‘SwigPyObject’.
My question is: how do I access to the lines contained in the var “DetectedLines”?
I just looked at your question, together with my LKEB colleague Patrick de Koning, who has experience using the SWIG Python wrapper of ITK. Unfortunately, we haven’t found the answer to your question.
DetectedLines wraps a C++ reference to an std::list of LineSpatialObject pointers. I can imagine that the wrapping would have been easier if std::vector was used, instead of std::list. For example, the Python wrapper of ITK’s VectorContainer does provide full access to the underlying std::vector.
I created a PR here. I need to update the test with an image that would give a reasonable result for this filter. @nick: Do you have any simple line image that you could share that we could integrate as a test in ITK?
Interesting. I just installed the latest package using the command you posted to make sure I was reproducing your steps. I tried both with python2.7 and python3.6. It worked for both. I ran the test that I added in ITK here using the line image that is available in this thread.
I investigated the problem I little more: as you pointed out the example works, the segfault comes when running the code inside a function.
I attached a little snippet that reproduces this issue.test.py (536 Bytes)
Could you reproduce it? Is there something wrong in what I’m doing?
hough = itk.HoughTransform2DLinesImageFilter[itk.F, itk.F].New()
# generate an empty image with one spot
print(len(lines2)) // <=== segfault here
Looks like the problem here is that the list of lines is owned by the hough object. The hough object could be destroyed when the RunHough function has returned, and in that case, the list has gone, too.
The most obvious fix to me would be to change the return type in C++:
I think your problem would be fixed by returning the list of lines by value, instead of by reference (&).
By the way, I would prefer to return an std::vector, instead of an std::list.
I think that you are right: that doesn’t happen for the images (e.g. the accumulator) as they are handled with Smart Pointer.
I’m not sure if modify the method to return a copy of the object is a good idea: I think it could break some code developed by other users… is there a way in python to return a copy of this kind of objects?
At the client side: sure, you could create a new Python list inside your RunHough function, and copy each line object (which is if fact a smart pointer) into your list, which you will then return. That should work just fine.
At the Python wrapper side: it might be possible to do return “by value” for GetLines(), even when the C++ code says “by reference”. But personally I wouldn’t really like to introduce such an inconsistency between the C++ API and the Python wrapping.
At the C++ side: theoretically it might break some C++ user code when the list of lines is returned by value, instead of by reference, but I don’t expect that it will affect many users. What particular use case do you think about?