使用Docker在jupyter中运行OpenCv

时间:2016-04-22 15:49:51

标签: python opencv docker jupyter

我想制作一个支持OpenCV的易于运行的jupyter笔记本,并作为Docker镜像提供。

这个概念是让一个docker容器运行jupyter内核并通过主机中的浏览器访问笔记本。与this类似的东西。

然而,问题是OpenCV似乎依赖于正在运行的Gtk环境。因此尝试运行以下代码:

import numpy as np
import cv2
img = cv2.imread('pendulum.png',0)
cv2.imshow('image',img) 

jupyter内核崩溃的结果:

(image:603): Gtk-WARNING **: cannot open display: 
[I 15:23:49.808 NotebookApp] KernelRestarter: restarting kernel (1/5)

有没有办法绕过这种依赖关系并让Docker容器中的OpenCV在主机系统的浏览器中显示图像?

重现问题的步骤:

Dockerfile:

FROM ubuntu:16.04

RUN apt-get update

RUN apt-get update --fix-missing && apt-get install -y wget bzip2 ca-certificates \
    libglib2.0-0 libxext6 libsm6 libxrender1 \
    git mercurial subversion

RUN echo 'export PATH=/opt/conda/bin:$PATH' > /etc/profile.d/conda.sh && \
    wget --quiet https://repo.continuum.io/archive/Anaconda3-4.0.0-Linux-x86_64.sh && \
    /bin/bash /Anaconda3-4.0.0-Linux-x86_64.sh -b -p /opt/conda && \
    rm /Anaconda3-4.0.0-Linux-x86_64.sh

ENV PATH /opt/conda/bin:$PATH

RUN conda install -y -c https://conda.binstar.org/menpo opencv3

RUN apt-get install -y libgomp1
RUN apt-get install -y libgtk2.0-0 x11-xserver-utils libcanberra-gtk3-module
RUN mkdir /home/user
RUN groupadd -r user -g 777 && \
useradd -u 431 -r -g user -d /home/user -s /sbin/nologin -c "Docker image user" user

RUN apt-get install -y libcanberra-gtk*

RUN chown -R user:user /home/user

USER user
WORKDIR /home/user

要执行的命令:

docker build -t opencv-play .
docker run -v /home/user/.Xauthority:/home/user/.Xauthority -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY -u user -v `pwd`:/home/user -p 8008:8008 -t -i opencv-play
jupyter notebook --ip='*' --no-browser --port=8008   #Inside the container
#Open the browser, URL-> http://localhost:8008
#Run the above code in jupyter

4 个答案:

答案 0 :(得分:3)

有两种可能的解决方案:

  1. 允许您的容器访问本地XServer。这将显示所有图形输出,就像您直接在主机上而不是在Docker容器中运行软件一样。为此,您需要设置DISPLAY环境变量,并且需要将X11套接字传递给容器。在您的示例中,您将:

    $ docker run -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY -v `pwd`:/home/workspace -p 8008:8008 -t -i opencv-play
    
    • -v /tmp/.X11-unix:/tmp/.X11-unix将X11套接字传递给容器
    • -e DISPLAY=$DISPLAY将显示环境变量设置为主机系统上的变量
  2. 如果您不需要图形输出,则可以运行假冒'没有显示任何输出的X服务器。 Xvfb是一个不需要任何访问监视器的显示服务器。要使用它,您需要在映像中安装Xvfb,即将apt-get install xvfb添加到Dockerfile。然后,当您运行容器时,首先需要启动xvfb并相应地设置DISPLAY。我通常使用一个小脚本来执行此操作,然后启动您的命令,例如

    #!/bin/bash
    export DISPLAY=0:0
    Xvfb $DISPLAY &
    jupyter notebook --ip='*' --no-browser --port=8008
    

    这将在后台启动Xvfb,然后启动jupyter,它将所有图形输出传递到0:0上的Xvfb显示服务器。将此脚本添加到图像,然后按以下方式运行:

    docker run -v `pwd`:/home/workspace -p 8008:8008 -t -i opencv-play /path/to/the/script
    

    请注意,需要将DISPLAY传递给容器。

答案 1 :(得分:1)

我的建议是不要使用OpenCV进行绘图,而是使用matplotlib。 这为您提供了更好的绘图(OpenCV绘图功能非常有限),并且还允许直接笔记本输出。

您可以选择使用inline后端,将每个绘图呈现为PNG(?)图像并将其显示在笔记本中。但是,这不允许缩放,平移等。

notebook后端允许缩放等,但上次尝试时边缘非常粗糙。

无论哪种方式,要使用它,您都可以使用%matplotlib魔法选择后端。

实施例

import matplotlib.pyplot as plt
%matplotlib inline

plt.imshow(img)
plt.title('My image')
plt.show()

对于notebook后端,只需改为%matplotlib notebook

使用图片时,通常最好不要插入plt.imshow来调用

plt.imshow(img, interpolation='none')

“正常”桌面后端(Gtk,Qt)需要调用plt.show(),但inline后端(以及notebook后端不需要调用吗?我不需要记住)。

答案 2 :(得分:1)

为了能够在docker的jupyter内部运行opencv,我以与其他用户相同的方式进行了以下操作,但是方式更加明确:

在主持人中:

xhost +local:root

docker run -it --name yolo_cuda8 -v "/home/dl001/dhiren/robust_tracking/camera/:/home/notebooks" -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=$DISPLAY -p 8888:8888 new_cuda8 bash

内部容器:

jupyter notebook --port=8888 --ip=0.0.0.0 --allow-root --no-browser

值得通过发出 echo $ DISPLAY 命令来检查主机中的 DISPLAY 变量,并验证并设置docker容器中是否没有该变量。

env
export DISPLAY=:1

参考:

link

link2

答案 3 :(得分:0)

在评论和其他研究之后,我设法让窗户加载但是一旦打开它们就无法关闭。 :P

以下是如何操作:

FROM ubuntu:16.04

RUN apt-get update

RUN apt-get update --fix-missing && apt-get install -y wget bzip2 ca-certificates \
    libglib2.0-0 libxext6 libsm6 libxrender1 \
    git mercurial subversion

RUN echo 'export PATH=/opt/conda/bin:$PATH' > /etc/profile.d/conda.sh && \
    wget --quiet https://repo.continuum.io/archive/Anaconda3-4.0.0-Linux-x86_64.sh && \
    /bin/bash /Anaconda3-4.0.0-Linux-x86_64.sh -b -p /opt/conda && \
    rm /Anaconda3-4.0.0-Linux-x86_64.sh

ENV PATH /opt/conda/bin:$PATH

RUN conda install -y -c https://conda.binstar.org/menpo opencv3

RUN apt-get install -y libgomp1
RUN apt-get install -y libgtk2.0-0 x11-xserver-utils libcanberra-gtk3-module


RUN mkdir /home/user
RUN groupadd -r user -g 777 && \
useradd -u 431 -r -g user -d /home/user -s /sbin/nologin -c "Docker image user" user

RUN apt-get install -y libcanberra-gtk*

RUN chown -R user:user /home/user

USER user
WORKDIR /home/user
CMD jupyter notebook --ip='*' --no-browser --port=8008

运行图片:

docker run -v /home/user/.Xauthority:/home/user/.Xauthority -v /tmp/.X11-unix:/tmp/.X11-unix -e DISPLAY=unix$DISPLAY -u root -v `pwd`:/home/user -p 8008:8008 -t -i opencv-play

启动笔记本(localhost:8008)。

运行以下代码:

import numpy as np
import matplotlib.pyplot as plt
import cv2

img = cv2.imread('pendulum.jpg',0)    #Make sure you have the image
cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()