"None" in Python and "nothing" in Julia for feature matching function

724 views
Skip to first unread message

i ce

unread,
Jun 17, 2016, 2:42:32 PM6/17/16
to julia-users

I am using PyCalland @pyimport cv2 to implement an OpenCV feature-matching program in Julia.


I have an example of the code I want to use in Python (see Brute-Force Matching with SIFT Descriptors and Ratio Test in this link: http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_feature2d/py_matcher/py_matcher.html for the full Python code.)


Everything up to the point of drawMatchesKnn() works fine, but I have issues with the outImg argument when converting to Julia.


Documentation for drawMatchesKnn() is pasted below: 
(and can also be found here: 
http://docs.opencv.org/3.0-beta/modules/features2d/doc/drawing_function_of_keypoints_and_matches.html#drawmatches


Pythoncv2.drawMatchesKnn(img1, keypoints1, img2, keypoints2, matches1to2[, outImg[, matchColor[, singlePointColor[, matchesMask[, flags]]]]]) → outImg

Parameter description:

  • img1 – First source image.
  • keypoints1 – Keypoints from the first source image.
  • img2 – Second source image.
  • keypoints2 – Keypoints from the second source image.
  • matches1to2 – Matches from the first image to the second one, which means that keypoints1[i] has a corresponding point in keypoints2[matches[i]] .
  • outImg – Output image. Its content depends on the flags value defining what is drawn in the output image. See possible flags bit values below.
  • matchColor – Color of matches (lines and connected keypoints). If matchColor==Scalar::all(-1) , the color is generated randomly.
  • singlePointColor – Color of single keypoints (circles), which means that keypoints do not have the matches. If singlePointColor==Scalar::all(-1) , the color is generated randomly.
  • matchesMask – Mask determining which matches are drawn. If the mask is empty, all matches are drawn.
  • flags – Flags setting drawing features. Possible flags bit values are defined by DrawMatchesFlags.

As you can see from the sample program, the drawMatchesKnn() line in Python would look like this:
img3 = cv2.drawMatchesKnn(train,kp1,query,kp2,good,None,flags=2) (the key argument is argument 6, specified as "None")


I'm having problems because I don't really know what an equivalent, working example in Julia would be.



I tried this:
img3 = cv2.drawMatchesKnn(train,kp1,query,kp2,good)

And got this error: (so arg6 is required)

LoadError: PyError (:PyObject_Call) <type 'exceptions.TypeError'>
TypeError("Required argument 'outImg' (pos 6) not found",)



This: (passing the scalar value 0, which worked for the method drawKeyPoints() in another program)
img3 = cv2.drawMatchesKnn(train,kp1,query,kp2,good,0,flags=2)

and got this error:

LoadError: PyError (:PyObject_Call) <type 'exceptions.SystemError'>
SystemError('NULL result without error in PyObject_Call',)



and this:
img3 = cv2.drawMatchesKnn(train,kp1,query,kp2,good,nothing,flags=2)

and got this error:

LoadError: PyError (:PyObject_Call) <type 'exceptions.SystemError'>
SystemError('NULL result without error in PyObject_Call',)


Seems tricky to me because None in Python and nothing in Julia do not appear to behave the same way.


Anything else I could try? What could the problem be, and how can I fix it?


Thanks for reading!
Any help is much appreciated.

Gabriel Gellner

unread,
Jun 17, 2016, 3:58:29 PM6/17/16
to julia-users
Have you tried passing `:none` in the argument list. I find that PyCall does the correct conversion on the symbol.

Stefan Karpinski

unread,
Jun 17, 2016, 4:06:49 PM6/17/16
to Julia Users
Converting between Python/None <=> Julia/nothing seems like something that PyCall should maybe do since they are pretty much equivalent. Maybe open an issue here: https://github.com/stevengj/PyCall.jl?

Gabriel Gellner

unread,
Jun 17, 2016, 6:00:58 PM6/17/16
to julia-users
Hmmm. Must be something different causing the problem.

When I check:
```jl
using PyCall
PyObject(nothing)
```
I get the expected `PyObject None` back.

I Ce

unread,
Jun 17, 2016, 8:59:34 PM6/17/16
to julia-users
Thank you for the replies,Gabriel and Stefan.

img3 = cv2.drawMatchesKnn(train,kp1,query,kp2, good, :none, flags=4)

yields the same error:

LoadError: PyError (:PyObject_Call) <type 'exceptions.SystemError'>
SystemError('NULL result without error in PyObject_Call',)

while loading In[60], in expression starting on line 22

 in pyerr_check at /home/-/.julia/v0.5/PyCall/src/exception.jl:56 [inlined]
 in pyerr_check at /home/-/.julia/v0.5/PyCall/src/exception.jl:61 [inlined]
 in macro expansion at /home/-/.julia/v0.5/PyCall/src/exception.jl:81 [inlined]
 in #pycall#46(::Array{Any,1}, ::Function, ::PyCall.PyObject, ::Type{PyCall.PyAny}, ::Array{UInt8,2}, ::Vararg{Any,N}) at /home/-/.julia/v0.5/PyCall/src/PyCall.jl:510
 in (::PyCall.#kw##pycall)(::Array{Any,1}, ::PyCall.#pycall, ::PyCall.PyObject, ::Type{PyCall.PyAny}, ::Array{UInt8,2}, ::Vararg{Any,N}) at ./null:0
 in #call#47(::Array{Any,1}, ::PyCall.PyObject, ::Array{UInt8,2}, ::Vararg{Any,N}) at /home/-/.julia/v0.5/PyCall/src/PyCall.jl:522
 in (::PyCall.#kw#PyObject)(::Array{Any,1}, ::PyCall.PyObject, ::Array{UInt8,2}, ::Vararg{Any,N}) at ./null:0
 in include_string(::String, ::String) at ./loading.jl:380
 in eventloop(::ZMQ.Socket) at /home/-/.julia/v0.5/IJulia/src/IJulia.jl:143
 in (::IJulia.##24#30)() at ./task.jl:310

I guess I'll open an issue on GitHub.

Cedric St-Jean

unread,
Jun 18, 2016, 5:24:59 PM6/18/16
to julia-users
I don't have a solution to offer, unfortunately, but I will confirm that `nothing` gets auto-converted to `None`. I'd guess that the issue is elsewhere. You might be able to debug it further / code around the problem by writing a Python function that accepts the Julia arguments and passes them on to cv2.drawMatchesKnn. Then you can test various combinations and find out which argument is the culprit.

I Ce

unread,
Jun 20, 2016, 2:42:34 PM6/20/16
to julia-users
Thanks Cedric,

Upon some further inquiry, I agree. 

I do not think it is the  `outImg` argument that is the problem, `nothing` worked just fine for another OpenCV function that had `None` written as a Python equivalent, as did the arguments for kp1, kp2, and the train and query images. The only thing left is good[] array, which was frankly a bit more difficult to work with because of the PyCall conversion between Python's nested lists and Julia's Abstract Arrays.

In short, I changed this Python piece:
good[] is of type `list`
good = []
for m,n in matches:
    if m.distance < 0.75*n.distance:
        good.append([m])

To this in Julia:
good[] is of type `Array{Any,1}`
good = []
for i=1:size(matches,1)
     if matches[i,1][:distance] < 0.75*matches[i,2][:distance]
        push!(good, matches[i,1])
    end
end

To anyone, does it look like this could have caused a problem?

Thank you



On Friday, June 17, 2016 at 2:42:32 PM UTC-4, I Ce wrote:
Reply all
Reply to author
Forward
0 new messages