在py2app生成的应用中包含opencv

0 投票
3 回答
1300 浏览
提问于 2025-04-17 06:03

我在一台装有OS 10.7.2的Mac上,使用的是苹果自带的Python 2.7.1。我通过源码安装了opencv 2.3.1,并确认在Python中可以成功使用import cv。我创建了一个简单的Python脚本(保存为“cvTest.py”),里面只有import cv这一行,其他什么都没有。然后我用py2app(通过终端命令py2applet --make-setup cvTest.py; python setup.py py2app)来打包这个脚本。当我把生成的独立应用程序移动到另一台没有安装opencv的Mac(同样是OS 10.7.2)上运行时,应用程序崩溃了,控制台显示了以下错误信息:

11-11-10 1:17:38.591 PM [0x0-0xcb9cb9].org.pythonmac.unspecified.cvTest: Traceback (most recent call last):
11-11-10 1:17:38.591 PM [0x0-0xcb9cb9].org.pythonmac.unspecified.cvTest:   File "/Users/ra/Downloads/cvTest.app/Contents/Resources/__boot__.py", line 103, in <module>
11-11-10 1:17:38.591 PM [0x0-0xcb9cb9].org.pythonmac.unspecified.cvTest:     _argv_emulation()
11-11-10 1:17:38.591 PM [0x0-0xcb9cb9].org.pythonmac.unspecified.cvTest:   File "/Users/ra/Downloads/cvTest.app/Contents/Resources/__boot__.py", line 101, in _argv_emulation
11-11-10 1:17:38.591 PM [0x0-0xcb9cb9].org.pythonmac.unspecified.cvTest:     _get_argvemulator().mainloop()
11-11-10 1:17:38.591 PM [0x0-0xcb9cb9].org.pythonmac.unspecified.cvTest:   File "/Users/ra/Downloads/cvTest.app/Contents/Resources/__boot__.py", line 40, in mainloop
11-11-10 1:17:38.591 PM [0x0-0xcb9cb9].org.pythonmac.unspecified.cvTest:     stoptime = Evt.TickCount() + timeout
11-11-10 1:17:38.591 PM [0x0-0xcb9cb9].org.pythonmac.unspecified.cvTest: AttributeError: 'module' object has no attribute 'TickCount'
11-11-10 1:17:38.661 PM cvTest: cvTest Error
11-11-10 1:17:39.888 PM com.apple.launchd.peruser.502: ([0x0-0xcb9cb9].org.pythonmac.unspecified.cvTest[49524]) Exited with code: 255

接着,我创建了一个简单的bash脚本,这样我就可以深入查看这个独立应用程序,并从终端运行应用程序的二进制文件:

#!/bin/bash
CMD=$0
PROGDIR=$(echo $CMD|perl -pe 's|/[^/]*$||')
cd "$PROGDIR"
"./cvTest.app/Contents/MacOS/cvTest"

执行这个操作后,出现了以下错误:

Traceback (most recent call last):
  File "/Users/ra/Downloads/cvTest.app/Contents/Resources/__boot__.py", line 137, in <module>
    _run('cvTest.py')
  File "/Users/ra/Downloads/cvTest.app/Contents/Resources/__boot__.py", line 134, in _run
    execfile(path, globals(), globals())
  File "/Users/ra/Downloads/cvTest.app/Contents/Resources/cvTest.py", line 1, in <module>
    import cv
  File "cv.pyc", line 1, in <module>
ImportError: No module named cv2.cv
2011-11-10 13:18:26.239 cvTest[49578:707] cvTest Error

[Process completed]

那么,这到底是怎么回事呢?为什么会出现错误?有没有办法把opencv和用py2app创建的应用程序打包在一起,这样import cv就能正常工作?

3 个回答

0

找到并添加依赖项到py2app打包文件的方法如下:

import os, sys, glob

frameworks = []
opencvLibs = glob.glob(os.path.join(sys.exec_prefix, 'lib', 'libopencv*.2.4.dylib'))
frameworks.extend(opencvLibs)

setup(app=['myApp'],
    options=dict(py2app=dict(
       frameworks=frameworks,
       includes = ['cv2',.....],
       packages = [........],
       ....
       )
    )

但是不幸的是,这并不能完全解决问题。对我来说,cv2.so这个文件是用静态链接编译的,链接到了@rpath/Python,但在你的pyapp打包文件中,它需要一个相对链接,这样应用程序才能移动。:-(

0

问题在于,py2app会把一个完全不同的Python版本打包到应用里。这个版本是自包含的,也就是说它需要把应用在运行时可能用到的所有库都包含进去(包括OpenCV)。可惜的是,py2app似乎漏掉了一个叫cv2.so的文件,这个文件应该在dist/helloworld.app/Contents/Resources/lib/python2.7/lib-dynload/这个位置(具体可以参考http://pythonhosted.org/py2app/implementation.html)。

这是一个正常安装OpenCV的样子:

bash-3.2$ ls -1 /usr/local/lib/python2.7/site-packages/cv*
/usr/local/lib/python2.7/site-packages/cv.py
/usr/local/lib/python2.7/site-packages/cv.pyc
/usr/local/lib/python2.7/site-packages/cv2.so

所以理论上,把cv2.so复制到dist/helloworld.app/Contents/Resources/lib/python2.X/lib-dynload/这个位置应该能解决问题。

可惜的是,这样做又引入了另一个问题:

bash-3.2$ dist/main_wx.app/Contents/MacOS/main_wx 
Segmentation fault: 11

cv2.so有很多依赖项需要被包含进来:

bash-3.2$ otool -L /usr/local/Cellar/opencv/2.4.5/lib/python2.7/site-packages/cv2.so 
/usr/local/Cellar/opencv/2.4.5/lib/python2.7/site-packages/cv2.so:
        /usr/local/lib/python2.7/site-packages/cv2.so (compatibility version 0.0.0, current version 0.0.0)
        /usr/local/opt/python/Frameworks/Python.framework/Versions/2.7/Python (compatibility version 2.7.0, current version 2.7.0)
        /usr/local/Cellar/opencv/2.4.5/lib/libopencv_core.2.4.dylib (compatibility version 2.4.0, current version 2.4.5)
        /usr/local/Cellar/opencv/2.4.5/lib/libopencv_flann.2.4.dylib (compatibility version 2.4.0, current version 2.4.5)
        /usr/local/Cellar/opencv/2.4.5/lib/libopencv_imgproc.2.4.dylib (compatibility version 2.4.0, current version 2.4.5)
        /usr/local/Cellar/opencv/2.4.5/lib/libopencv_video.2.4.dylib (compatibility version 2.4.0, current version 2.4.5)
        /usr/local/Cellar/opencv/2.4.5/lib/libopencv_ml.2.4.dylib (compatibility version 2.4.0, current version 2.4.5)
        /usr/local/Cellar/opencv/2.4.5/lib/libopencv_highgui.2.4.dylib (compatibility version 2.4.0, current version 2.4.5)
        /usr/local/Cellar/opencv/2.4.5/lib/libopencv_features2d.2.4.dylib (compatibility version 2.4.0, current version 2.4.5)
        /usr/local/Cellar/opencv/2.4.5/lib/libopencv_calib3d.2.4.dylib (compatibility version 2.4.0, current version 2.4.5)
        /usr/local/Cellar/opencv/2.4.5/lib/libopencv_photo.2.4.dylib (compatibility version 2.4.0, current version 2.4.5)
        /usr/local/Cellar/opencv/2.4.5/lib/libopencv_objdetect.2.4.dylib (compatibility version 2.4.0, current version 2.4.5)
        /usr/local/Cellar/opencv/2.4.5/lib/libopencv_contrib.2.4.dylib (compatibility version 2.4.0, current version 2.4.5)
        /usr/local/Cellar/opencv/2.4.5/lib/libopencv_legacy.2.4.dylib (compatibility version 2.4.0, current version 2.4.5)
        /usr/local/Cellar/opencv/2.4.5/lib/libopencv_gpu.2.4.dylib (compatibility version 2.4.0, current version 2.4.5)
        /usr/local/Cellar/opencv/2.4.5/lib/libopencv_ocl.2.4.dylib (compatibility version 2.4.0, current version 2.4.5)
        /usr/local/Cellar/opencv/2.4.5/lib/libopencv_nonfree.2.4.dylib (compatibility version 2.4.0, current version 2.4.5)
        /usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)
        /System/Library/Frameworks/OpenCL.framework/Versions/A/OpenCL (compatibility version 1.0.0, current version 1.0.0)
        /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 56.0.0)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)

我不太确定该怎么处理这些依赖,但我感觉如果不把它们包含进去,什么都不会正常工作。我把这些信息留在这里,希望其他人能用它找到解决办法。

0

老实说,我也不太确定。不过我正在做一个开源项目,主要是关于计算机视觉的(它是对OpenCV的封装),还有其他一些功能(http://www.simplecv.org)。我们遇到的一个问题是,想要在不同平台上部署时,希望能有一键安装的功能。

我们尝试在Windows上使用Innosetup,但遇到了很多问题。我有点受够了,所以开始自己写一个。这个程序基本上是一个引导程序。你下载我们的exe文件,运行它,然后它会拉取一份需要的文件和库的列表,并开始安装。因此,在我们的情况下,即使机器上没有任何库,也能安装我们的软件。它首先安装Python,然后是setuptools,再然后是opencv,等等。

我发布的这个开源应用程序,旨在成为Innosetup的替代品,但可以跨平台使用。如果你想看看现在的进展(大约完成了85%),可以访问: https://github.com/ingenuitas/SimpleCV/blob/installer/install/simplecv-installer.py

我计划在完成后将这个项目分叉,这样它就可以成为一个通用的安装程序,只需提供一个清单文件即可。 这是现有的清单: https://github.com/ingenuitas/SimpleCV/blob/installer/install/manifest.json

撰写回答