I want to use OpenCV on Julia via PyCall - python

I want to use OpenCV on Julia, then I tried to use PyCall.
I made my Python environment by pyenv, therefore, I tried below commands;
julia> ENV["PYTHON"] = "/Users/MYNAME/.pyenv/shims/python"
julia> using Pkg
julia> Pkg.add("PyCall")
Then, I tried a below command and this error message was returned.
julia> using PyCall
ImportError: No module named site
This error message is too short to infer causes.
Anyone knows the causes and how to solve?

PyCall is tested with Anaconda and it works best with the Anaconda installation inbuilt into Julia.
using Pkg
#ENV["PYTHON"] = ""
pkg"add PyCall"
#pkg"build PyCall" #required to restore the default config if you changed it
pkg"add Conda"
using Conda
Conda.runconda(`install -c conda-forge opencv`)
using PyCall
const cv = pyimport("cv2")
Now you are ready to do your work.

There are also Julia bindings for OpenCV, although they haven't been integrated with Julia's artifact system and so still require a certain amount of manual effort to install. To get started, see this blog post.

Related

I have a high-performant function written in Julia, how can I use it from Python?

I have a found a Julia function that nicely does the job I need.
How can I quickly integrate it to be able to call it from Python?
Suppose the function is
f(x,y) = 2x.+y
What is the best and most elegent way to use it from Python?
Assuming your Python and Julia are installed you need to take the following steps.
Run Julia and install PyCall
using Pkg
pkg"add PyCall"
Put your code into a Julia package
using Pkg
Pkg.generate("MyPackage")
In the folder src you will find MyPackage.jl, edit it to look like this:
module MyPackage
f(x,y) = 2x.+y
export f
end
Install pyjulia
python -m pip install julia
(On Linux systems you might want to use python3 instead of python command)
For this step note that while an external Python can be used with Julia. However, for a convenience it might be worth
to consider using a Python that got installed together with Julia as PyCall.
In that case for installation use a command such this one:
%HOMEPATH%\.julia\conda\3\python -m pip install julia
or on Linux
~/.julia/conda/3/python -m pip install julia
Note that if you have JULIA_DEPOT_PATH variable defined you can replace %HOMEPATH%\.julia or ~/.julia/ with its value.
Run the appropiate Python and tell it to configure the Python-Julia integration:
import julia
julia.install()
Now you are ready to call your Julia code:
>>> from julia import Pkg
>>> Pkg.activate(".\\MyPackage") #use the correct path
Activating environment at `MyPackage\Project.toml`
>>> from julia import MyPackage
>>> MyPackage.f([1,2],5)
[7,9]
It is worth noting that the proposed approach in this answer has several advantages over a standalone Julia file which would be possible, although is less recommended. The advantages include:
Packages get precompiled (so they are faster in subsequent runs) and can be loaded as a package in Python.
Packages come with their own virtual environment via 1Project.toml` which makes production deployments much comfortable.
A Julia package can be statically compiled into Julia's system image which can slash itsloading time --- see https://github.com/JuliaLang/PackageCompiler.jl .
EDIT
In February 2022 juliacall was announced, as of December 2022 juliacall might be an easier option for some users - have a look at: How to load a custom Julia package in Python using Python's juliacall
I found that the python package PyCall did not work for me (segaults in unexplicable ways) however the more recent library JuliaCall worked. The differences are listed in the above link to the official pip-package. There is also an example on how to get started but I will describe the process here as well.
Advantages of using juliacall
The advantages of using juliacall over pycall are
it works more reliably for me (python 3.9/3.10, julia 1.6)
I can use my existing Julia environment (in production one might want to create a seperate julia-env which is also possible, see the default way in the docs)
just need a single julia script file (dont need to create a package)
Furthermore the documentation for juliacall is better: https://cjdoris.github.io/PythonCall.jl/stable/juliacall/
Instructions
Install PythonCall into Julia either by entering package mode via ] and writing add PythonCall or execute in normal julia mode:
julia> using Pkg
julia> Pkg.add("PythonCall")
Install the python package juliacall into you python environment:
$ python -m pip install juliacall
note the path of your julia executable. Enter the shell mode in julia with the key ; and execute:
shell> which julia
/home/user/.juliaup/bin/julia
note the path to your julia environment by first importing Pkg and then entering shell mode again to execute:
julia> using Pkg
shell> pwd $(Pkg.envdir())
/home/user/.julia/environments
shell> ls -lah $(Pkg.envdir())
v1.6
So my julia-env path is: /home/user/.julia/environments/v1.6/
Execute the following python script:
import os
# setting env variables so that juliacall finds the correct julia env
# see the github page for docs about env variables https://github.com/cjdoris/PyJuliaPkg
# juliacall makes use of the package pyjuliapkg to find the correct julia version, so you can read up on that here: https://github.com/cjdoris/pyjuliapkg/blob/main/src/juliapkg/find_julia.py
os.environ['PYTHON_JULIAPKG_EXE'] = "/home/user/.juliaup/bin/julia"
os.environ['PYTHON_JULIAPKG_OFFLINE']= 'yes' # such that nothing new is downloaded
os.environ['PYTHON_JULIAPKG_PROJECT'] = '/home/user/.julia/environments/v1.6/'
from juliacall import Main as jl
def main():
print('in main...')
# show installed julia packages to make sure you are in the right env
jl.seval('using Pkg')
jl.seval('Pkg.status()')
# import your script and execute
jl.seval('include("test_julia_simple.jl")')
result = jl.seval('f([2,3], [4,5])')
print(result)
print('...done')
return
if __name__ == "__main__":
main()
The accompanying julia script test_julia_simple.jl contains your function and in this case looks as follows:
function f(x,y)
return 2x.+y
end

Warning: PyPlot is using tkagg backend, which is known to cause crashes on MacOS

Does anyone knows how to change the backend of PyPlot from "TkAgg" to Qt5Agg in Julia ?
I got this warning when I try to Using PyPlot in Julia:
julia> using PyPlot
[ Info: Recompiling stale cache file /Users/tonyspc/.julia/compiled/v1.2/PyPlot/oatAj.ji for PyPlot [d330b81b-6aea-500a-939a-2ce795aea3ee]
┌ Warning: PyPlot is using tkagg backend, which is known to cause crashes on MacOS (#410); use the MPLBACKEND environment variable to request a different backend.
└ # PyPlot ~/.julia/packages/PyPlot/4wzW1/src/init.jl:192
I tried to use the solution posted here: https://github.com/JuliaPy/PyPlot.jl/issues/454
But it failed:
julia> using PyCall
[ Info: Recompiling stale cache file /Users/tonyspc/.julia/compiled/v1.2/PyCall/GkzkC.ji for PyCall [438e738f-606a-5dbb-bf0a-cddfbfd45ab0]
julia> pyimport_conda("PyQt5", "pyqt")
ERROR: PyError (PyImport_ImportModule
The Python package PyQt5 could not be found by pyimport. Usually this means
that you did not install PyQt5 in the Python version being used by PyCall.
PyCall is currently configured to use the Python version at:
/System/Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python
and you should use whatever mechanism you usually use (apt-get, pip, conda,
etcetera) to install the Python package containing the PyQt5 module.
One alternative is to re-configure PyCall to use a different Python
version on your system: set ENV["PYTHON"] to the path/name of the python
executable you want to use, run Pkg.build("PyCall"), and re-launch Julia.
Another alternative is to configure PyCall to use a Julia-specific Python
distribution via the Conda.jl package (which installs a private Anaconda
Python distribution), which has the advantage that packages can be installed
and kept up-to-date via Julia. As explained in the PyCall documentation,
set ENV["PYTHON"]="", run Pkg.build("PyCall"), and re-launch Julia. Then,
To install the PyQt5 module, you can use `pyimport_conda("PyQt5", PKG)`,
where PKG is the Anaconda package the contains the module PyQt5,
or alternatively you can use the Conda package directly (via
`using Conda` followed by `Conda.add` etcetera).
) <type 'exceptions.ImportError'>
ImportError('No module named PyQt5',)
Stacktrace:
[1] pyimport(::String) at /Users/tonyspc/.julia/packages/PyCall/ttONZ/src/PyCall.jl:544
[2] pyimport_conda(::String, ::String, ::String) at /Users/tonyspc/.julia/packages/PyCall/ttONZ/src/PyCall.jl:702
[3] pyimport_conda(::String, ::String) at /Users/tonyspc/.julia/packages/PyCall/ttONZ/src/PyCall.jl:701
[4] top-level scope at REPL[4]:1
However I already installed PyQt5 using brew install pyqt
And I don't know why my matplot library is located at python2 directory not the python3 directory:
julia> pyimport("matplotlib").matplotlib_fname()
"/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/matplotlib/mpl-data/matplotlibrc"
I have python2 that comes with default on my Mac, and installed python3 using Homebrew
MacBook-Pro:~ tonyspc$ which python3
/usr/local/bin/python3
MacBook-Pro:~ tonyspc$ which python
/usr/bin/python
Should I set the ENV["PYTHON"] to "/usr/local/bin/python3" ?
I had a similar problem, and I added this to my .bashrc to run every time:
export MPLBACKEND=qt5agg
Then after doing the ]build PyCall PyPlot and restarting julia, it seemed to find the right backend to plot.
My relevant issue I opened (and the answer I got): https://github.com/JuliaPy/PyPlot.jl/issues/453#issuecomment-527163934
Try setting ENV["PYTHON"] = "/usr/local/bin/python3" in a fresh REPL followed by pkg> build PyCall PyPlot. This should make PyCall (and therefore also PyPlot) use your local Python 3.

Can't load Python PIL.Images module using PyCall from Julia

In Julia I am using the module PyCall
using PyCall: #pyimport
When I then try to use the scikitlearn library's module called ensamble, there is no problem, it works and I can use the module:
#pyimport sklearn.ensemble as skle
However when I try to do the same with the PIL library or PIL library's module Images, it doesn't work.
#pyimport PIL.Image as PILI
I get the following error: ERROR: PyError (:PyImport_ImportModule)
ImportError('No module named PIL.Image',)
[inlined code] from /home/lara/.julia/v0.4/PyCall/src/exception.jl:81
in pyimport at /home/lara/.julia/v0.4/PyCall/src/PyCall.jl:387
Can someone please talk me through the steps to get this working becasue I don't see how this is different from the scikit learn library and ensamble module.
Based on discussion in the comments, the issue appears to be that PyCall is using its own Python installation which does not have the requisite library installed. There are two options:
follow these instructions to change the Python installation referenced by PyCall to your local one in /home/lara/anaconda2.
use Conda.jl to add PIL to the Conda.jl Python install:
Conda.add("Pillow") (you could probably use PIL, but Pillow is a compatible fork that is actively maintained from what I can tell)
The second option is probably slightly preferred, but if you have many packages installed already it may be simpler to try the first option (you can always switch back to the Conda.jl version if something doesn't work).

Python GDal installation

Having some problems with Gdal installation with python 2.7 on Windows 7 32bit. I am running MSVC 2010. I have followed the instruction from the blog website
http://cartometric.com/blog/2011/10/17/install-gdal-on-windows/
The installation is fine. At the end of it, I am able to run ogr2ogr in the MS-DOS and have gotten the similar screen as listed in the blog.
However, when I am trying to use the command "import osgeo" on the Python IDLE GUI shell. A series of error message is released, reading like the following
"DLL error:.........."
I believe that this might mean that the python binding is of wrong version. I have cleared up my installation by removing the following: Python-Gdal binding, Gdal, Python 2.7
After removing them, I have retried my installation with Python 3.2.3 instead and loaded the Gdal package and python binding accordingly. However, the same error returns.
Is there any intermediate steps that I could take to verify the installation. Any other advice I could have to have the bindings installed? Or is my reinstallation method correct?
I have tried to install FWTools too. It doesnt seem to work either. I have run the Python shell from EV-shell and type in "import osgeo". Have gotten the message "no module exist...."
Thanks
Get the precompiled gdal from here:
http://www.lfd.uci.edu/~gohlke/pythonlibs/#gdal
I have some other notes on setting up postgres and postgis 2.0 here if you need it:
http://monkut.webfactional.com/blog/archive/2012/5/2/using-django-14-with-gdal-19-and-postgis-20/

`Fatal Python error: PyThreadState_Get: no current thread` after `import cv´

I installed OpenCV via sudo brew install opencv.
Then I added PYTHONPATH* to my ~/.profile as brew info opencv says**. With env I checked that the path was loaded.
Now everytime I try to import cv, Python gives following error: Fatal Python error: PyThreadState_Get: no current thread Abort trap.
What should I do?
*PYTHONPATH=/usr/local/lib/python2.7/site-packages/:
** actually, it points to folder python2.6 but 2.7 is the Python version I use and cv 2.2. supports it.
cv 2.2 might well support it, but you MUST not mix versions like that. You must use the version built for 2.7 with 2.7, and the version built for 2.6 with 2.6
I seem to think that cv is a python library that depends on a C library - in that case, you can not mix the libraries like that.
cv will need to be re-compiled against 2.7 if you have only a 2.6 version of it.
That said, this type of Fatal Error suggests a bug in the cv library, however, if you're mixing versions like this, then the result is undefined. (It might work by chance, or it might fail randomly as it has for you).

Categories

Resources