Nuitka icon indicating copy to clipboard operation
Nuitka copied to clipboard

OpenCV High-level GUI

Open lwndlnd opened this issue 2 years ago • 8 comments

I'm trying to run a simple program using the OpenCV High-level GUI.

This is a minimal example:

import numpy as np
import cv2

if __name__ == '__main__':
    img = np.zeros((300, 300, 3))
    cv2.imshow("img", img)
    cv2.waitKey(0)

Compiling the code works but when running the executable I get the following error:

➜ (nuitka) ./main.dist/main 
qt.qpa.plugin: Could not find the Qt platform plugin "xcb" in "/path/to/main.dist/cv2/qt/plugins"
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

However the folder main.dist/cv2/qt does not exist. Apparently opencv sets the following environment variables: QT_QPA_PLATFORM_PLUGIN_PATH, QT_QPA_FONTDIR Thus if I add the following to the python example the compiled program works but of course this is less than ideal.

import os
os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = '/home/user/.virtualenvs/nuitka/lib/python3.9/site-packages/cv2/qt/plugins'
os.environ['QT_QPA_FONTDIR'] = '/home/user/.virtualenvs/nuitka/lib/python3.9/site-packages/cv2/qt/fonts' 

I would appreciate any help regarding how to make sure the plugins can be included in the executable.

Here is my environment:

python -m nuitka --version 1.0.6 Commercial: None Python: 3.9.13 (main, May 23 2022, 22:01:06) Flavor: Debian Python Executable: /home/user/.virtualenvs/nuitka/bin/python OS: Linux Arch: x86_64 Distribution: Ubuntu (based on Debian) 20.04.5

  • How did you install Nuitka and Python: pip+virtualenv

python -m pip freeze Nuitka==1.0.6 numpy==1.23.2 opencv-python==4.6.0.66

  • Nuitka command

python -m nuitka --standalone --enable-plugin=numpy main.py

lwndlnd avatar Aug 30 '22 08:08 lwndlnd

Have you tried adding the pyqt5 plugin with --enable-plugin=pyqt5 --include-qt-plugins=xcb?

interseba5 avatar Aug 30 '22 10:08 interseba5

Have you tried adding the pyqt5 plugin with --enable-plugin=pyqt5 --include-qt-plugins=xcb?

With this I get the following error:

(nuitka) ➜ python -m nuitka --standalone --enable-plugin=numpy,pyqt5 --include-qt-plugins=xcb main.py
Nuitka-Options:INFO: Used command line options: --standalone --enable-plugin=numpy,pyqt5 --include-qt-plugins=xcb main.py
Nuitka:WARNING: Using very slow fallback for ordered sets, please install 'orderedset' PyPI package for best Python compile time performance.
Nuitka:INFO: Starting Python compilation with Nuitka '1.0.6' on Python '3.9' commercial grade 'not installed'.
Nuitka-Plugins:INFO: multiprocessing: Injecting pre-module load code for module 'multiprocessing':
Nuitka-Plugins:INFO: multiprocessing:     Monkey patching "multiprocessing" load environment.
Nuitka-Plugins:INFO: multiprocessing: Injecting post-module load code for module 'multiprocessing':
Nuitka-Plugins:INFO: multiprocessing:     Monkey patching "multiprocessing" for compiled methods.
Nuitka:INFO: Completed Python level compilation and optimization.                       
Nuitka:INFO: Generating source code for C backend compiler.
Nuitka:INFO: Running data composer tool for optimal constant value handling.                
Nuitka:INFO: Running C compilation via Scons.
Nuitka-Scons:INFO: Backend C compiler: gcc (gcc).
Nuitka-Scons:INFO: Backend linking program with 107 files (no progress information available).
Nuitka-Scons:WARNING: You are not using ccache.
FATAL: pyqt5: Error, it seems 'PyQt5' is not installed or broken.

After installing PyQT5 the command works but when running the executable the error is the same as before

The file libxcb.so.1 exists in ./main.dist/ but not in ./main.dist/cv2/qt/plugins/platforms

lwndlnd avatar Aug 30 '22 10:08 lwndlnd

It seems that cv2 also has Qt plugins of its own. It probably can be dealt with by similar code, but it will have to be created, and it would be sweet if it indeed coexisted with Qt bindings nicely, but do not have it installed, that makes no sense. The way you specified Qt plugins there, is outright unlikely to work at all, because you are not including mandatory plugins.

kayhayen avatar Aug 30 '22 14:08 kayhayen

If anyone wants to help, checkout the nuitka/plugins/standard/PySidePyQtPlugin.py file and try to have a cv2 plugin, that allows to do similar stuff. The setting of environment variables, that point into the dist, is also done in that plugin, and largely you have to do only what it does. I do not know when I will have to time to look at this.

kayhayen avatar Aug 30 '22 15:08 kayhayen

Just copy files (qt-plugins) from the folder main.dist/pyqt5/qt-plugins (or main.dist/pyside6/qt-plugins) into the new created folder "qt/plugins" in main.dist/cv2/qt/plugins. Or simply copy one file "libqxcb" from main.dist/pyside6/qt-plugins/platforms/libqxcb to get the final dir: main.dist/cv2/qt/plugins/platforms/libqxcb

OualidSai avatar Sep 07 '22 06:09 OualidSai

If at all under your control, make sure to use PySide6, it's far better supported.

kayhayen avatar Sep 07 '22 07:09 kayhayen

Plus the copying is not really enough in the general cased, esp. outside of Windows, we will have to make a plugin update there, but as you know @OualidSai I am busy with something else ;-)

kayhayen avatar Sep 07 '22 07:09 kayhayen

I will be happy @kayhayen because the new stuff will be working :-)

OualidSai avatar Sep 07 '22 07:09 OualidSai

I am confused about this one, I assumed this was about Qt plugins in the cv2 wheel, but I did not immediately see them now. Is this using a Qt binding like PySide or PyQt or is this something I have no yet seen?

kayhayen avatar Sep 23 '22 09:09 kayhayen

Ah, got it, this is only done on Linux, and it is only the platforms plugin for X11. One weakness of my WSL setup is that I have no GUI available, so I will need help to test this one, but basically we just need to set the environment variable and include this as a DLL. Mixing with PySide and PyQt wouldn't work well this way, but probably does not with standard Python either.

kayhayen avatar Sep 23 '22 09:09 kayhayen

Thanks for the pretty much perfect report. Turns out, 3 things had to be done, which are all encapsulated in this yaml and are also part of the original report:

- module-name: 'cv2'
  data-files:
    dirs:
      - 'qt/fonts'
  dlls:
    - from_filenames:
        relative_path: 'qt/plugins/platforms'
        prefixes:
          - 'lib'
      when: 'linux'
  implicit-imports:
    - pre-import-code:
        - |
          import os
          os.environ['QT_QPA_PLATFORM_PLUGIN_PATH'] = os.path.join(os.path.dirname(__file__), 'qt/plugins')
          os.environ['QT_QPA_FONTDIR'] = os.path.join(os.path.dirname(__file__), 'qt/fonts')
      when: 'linux and standalone'

In the old days, this would have needed a dedicated plugin, but it's pretty powerful now.

kayhayen avatar Sep 23 '22 10:09 kayhayen

I got report, that this doesn't work with Anaconda on Linux yet, but only PyPI package so far. I will try and add that as well.

kayhayen avatar Sep 24 '22 06:09 kayhayen

This is part of the stable release 1.1 that I just made, but Anaconda will need more work, shifted to 1.1 hotfix.

kayhayen avatar Sep 25 '22 17:09 kayhayen

It works perfectly with Nuitka 1.1 with virtualenv.

OualidSai avatar Sep 26 '22 12:09 OualidSai