如何在nix系统中使用OpenCV?

6
我正在尝试使用nix软件包管理器运行OpenCV的hello world程序,但它一直报错:
OpenCV错误:未指定错误(该功能未实现。重新构建具有Windows、GTK+2.x或Carbon支持的库。如果您使用的是Ubuntu或Debian,请安装libgtk2.0-dev和pkg-config,然后重新运行cmake或配置脚本),在cvNamedWindow,文件/tmp/nix-build-opencv-2.4.13.drv-0/opencv-2.4.13-src/modules/highgui/src/window.cpp,第483行 终止调用后抛出'cv::Exception'一个实例,内容为 /tmp/nix-build-opencv-2.4.13.drv-0/opencv-2.4.13-src/modules/highgui/src/window.cpp:483: error: (-2) 该功能未实现。重新构建具有Windows、GTK+2.x或Carbon支持的库。如果您使用的是Ubuntu或Debian,请安装libgtk2.0-dev和pkg-config,然后重新运行cmake或配置脚本,在函数cvNamedWindow中。
我使用以下default.nix文件创建了一个nix-shell。
with import <nixpkgs> {}; {
  cimgEnv = stdenv.mkDerivation {
  name = "cimgdev";
  buildInputs = [ pkgconfig stdenv cimg xorg.libX11 boost opencv gnome.gtk ];
  }; 
}

编译并运行以下代码

#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main() {

  Mat image;

  image = imread("lena.jpg", 1);

  if ( !image.data ) {
    cout << "No image data" << endl;
    return -1;
  }

  namedWindow("Display Image", WINDOW_AUTOSIZE);
  imshow("Display Image", image);

  waitKey(0);

  return 0;
}

使用以下命令:
g++ `pkg-config --cflags opencv` opencvtest.cpp `pkg-config --libs opencv` -o opencvtest

代码编译成功了,但是在运行时遇到了之前的错误信息。

我尝试使用CMake,但结果相同。


2
我不熟悉nix,但错误消息显示“安装libgtk2.0-dev和pkg-config”,但您似乎没有指定任何libgtk2.0-dev。 [也可以查看此答案](https://dev59.com/kV4b5IYBdhLWcg3wtjpA#30979195)。 - Ken Y-N
@KenY-N - 我在我的 default.nix 文件中添加了 "gnome.gtk",我相信这是 nix 包中 libgtk2.0-dev 的等效物。 - maou
3个回答

8

OpenCV没有使用GTK支持构建。在opencv软件包定义中,enableGtk2默认为false。要启用它,请在您的default.nix中覆盖该参数:

let
  opencvGtk = opencv.override (old : { enableGtk2 = true; });
in 
   ...
   buildInputs = [... opencvGtk ...];
   ...

除非您想直接使用它,否则无需将gtk2或任何其他内容添加到buildInputs中,只需添加pkgconfig即可。 在冗长的opencv重建之后,构建和运行上述代码(给定lena.jpg)可以正常工作:

it works


$ cd /nix/store/ $ ls | grep opencv $ cd ..opencv.. $ find . -name "*.pc" 可以得到 opencv4.pc,所以我需要 $ g++ pkg-config --cflags opencv4 opencvtest.cpp pkg-config --libs opencv4 -o opencvtest - Tom Huntington

2

我知道这个问题是关于C++的,但是由于这个页面是谷歌搜索结果中第一个为寻找相同问题的Python用户提供解决方案的页面,因此我认为也提供Python的解决方案可能会有用...

所以这里是一个shell.nix示例(将python37替换为您选择的版本):

{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
  name = "dev-shell";
  buildInputs = [
    pkgs.python37Packages.numpy
    pkgs.python37Packages.flask
    # …
    (pkgs.python37Packages.opencv4.override { enableGtk2 = true; })
  ];
}

或者更简洁地说:

{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
  name = "dev-shell";
  buildInputs = with pkgs.python37Packages; [
    numpy
    flask
    # …
    (opencv4.override { enableGtk2 = true; })
  ];
}

编辑 2023-02-09

实际上,正确的方法似乎是:

{pkgs ? import <nixpkgs> {}}:

pkgs.mkShell {
  name = "dev-shell";

  packages = [
    (pkgs.python38.withPackages(ps: [
      ps.numpy
      ps.flask
      (ps.opencv4.override {enableGtk2 = true;})
    ]))
  ];
}

0

首先看一下this.

似乎你的OpenCV构建缺少适当平台的UI支持(主要在highgui库中)。我从OpenCV CMakeLists.txt中获取了这些信息。

status("")
status("  GUI: ")

if(HAVE_QT5)
  status("    QT 5.x:"            HAVE_QT        THEN "YES (ver ${Qt5Core_VERSION_STRING})" ELSE NO)
  status("    QT OpenGL support:" HAVE_QT_OPENGL THEN "YES (${Qt5OpenGL_LIBRARIES} ${Qt5OpenGL_VERSION_STRING})" ELSE NO)
elseif(HAVE_QT)
  status("    QT 4.x:"            HAVE_QT        THEN "YES (ver ${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}.${QT_VERSION_PATCH} ${QT_EDITION})" ELSE NO)
  status("    QT OpenGL support:" HAVE_QT_OPENGL THEN "YES (${QT_QTOPENGL_LIBRARY})" ELSE NO)
else()
  if(DEFINED WITH_QT)
    status("    QT:" NO)
  endif()
  if(DEFINED WITH_WIN32UI)
    status("    Win32 UI:" HAVE_WIN32UI THEN YES ELSE NO)
  else()
    if(APPLE)
      if(WITH_CARBON)
        status("    Carbon:" YES)
      else()
        status("    Cocoa:"  YES)
      endif()
    else()
      if(HAVE_GTK3)
        status("    GTK+ 3.x:" HAVE_GTK THEN "YES (ver ${ALIASOF_gtk+-3.0_VERSION})" ELSE NO)
      elseif(HAVE_GTK)
        status("    GTK+ 2.x:" HAVE_GTK THEN "YES (ver ${ALIASOF_gtk+-2.0_VERSION})" ELSE NO)
      else()
        status("    GTK+:" NO)
      endif()
      status("    GThread :" HAVE_GTHREAD THEN "YES (ver ${ALIASOF_gthread-2.0_VERSION})" ELSE NO)
      status("    GtkGlExt:" HAVE_GTKGLEXT THEN "YES (ver ${ALIASOF_gtkglext-1.0_VERSION})" ELSE NO)
    endif()
  endif()
endif()

status("    OpenGL support:" HAVE_OPENGL THEN "YES (${OPENGL_LIBRARIES})" ELSE NO)
status("    VTK support:" HAVE_VTK THEN "YES (ver ${VTK_VERSION})" ELSE NO)

您可以看到许多GUI支持,包括Gtk2。因此,请按照所述安装ibgtk2.0-dev和pkg-config。确保HAVE_GTK变量有效。通过CMake进行配置后,默认情况下将启用GTK支持。否则,您可以检查它。

如果您发现任何不正确的地方,请编辑/评论。


我在我的default.nix文件中添加了“gnome.gtk”,我相信这相当于nix软件包中的libgtk2.0-dev。pkgconfig也在其中。 - maou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接