RaspberryPiでOpenCVを使ってみる【つまづき編】

RaspberryPiでOpenCVを使ってみる【つまづき編】

f:id:ueponx:20170226143214j:plain

やっと、OpenCVに手をだす感じになってきたのですが、即挫折させられるという運の無さ。 急いでいる人は以下の手順でOKです。

$ sudo apt-get install libopencv-dev
$ sudo apt-get install python-opencv
$ sudo apt-get install libgl1-mesa-dri
$ x11vnc -storepasswd
$ sudo mkdir /home/pi/.config/autostart/
$ sudo vim /home/pi/.config/autostart/x11vnc.desktop (設定ファイルの中身は下を参照)
$ sudo vi /boot/config.txt(設定ファイルの中身は下を参照)
$ sudo raspi-config(設定後再起動)

インストール作業

以前のエントリでも、opnecvの開発パッケージ、pythonopencvモジュールの2つはインストールしていますので、あえてやらなくてもいいのかなとは思いますがバージョンアップもあるかなということで行いました。

$ sudo apt-get install libopencv-dev
$ sudo apt-get install python-opencv

一ヶ月ほど前に入れたにも関わらず、バージョンアップが行われていたので時間がかかりました。

インストールを行ったOpenCVのバージョンの確認方法

インストールするとバージョンがあとからわからなくなることがあるのですが以下のファイルにバージョンが記載されています。

$ less /usr/include/opencv2/core/version.hpp
(略)

/*
  definition of the current version of OpenCV
  Usefull to test in user programs
*/

#ifndef __OPENCV_VERSION_HPP__
#define __OPENCV_VERSION_HPP__

#define CV_VERSION_EPOCH    2
#define CV_VERSION_MAJOR    4

#define CV_VERSION_EPOCH    2
#define CV_VERSION_MAJOR    4
#define CV_VERSION_MINOR    9
#define CV_VERSION_REVISION 1

(略)

/* old  style version constants*/
#define CV_MAJOR_VERSION    CV_VERSION_EPOCH
#define CV_MINOR_VERSION    CV_VERSION_MAJOR
#define CV_SUBMINOR_VERSION CV_VERSION_MINOR

#endif

この時点(2017/02/25)でのインストールではversionは2.4.9になっていたようです。

インストールでは難なく完了するので後はサンプルを動かすだけです。以前のエントリーでも画面表示は行っていませんでしたがUSBカメラからのキャプチャは行っていましたので、どちらかというとGUIっぽい表示にすることがメインのチェックとなります。

OpenCVのサイトに行けばサンプルも結構あるのでそれを編集しています。

カメラ画像をX上で表示する使用するサンプルcamera.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import cv2.cv as cv
import time

cv.NamedWindow("camera", 1)

capture = cv.CaptureFromCAM(0)

# 画像サイズの指定
cv.SetCaptureProperty(capture,cv.CV_CAP_PROP_FRAME_WIDTH,320)
cv.SetCaptureProperty(capture,cv.CV_CAP_PROP_FRAME_HEIGHT,240)

while True:
    img = cv.QueryFrame(capture)
    cv.ShowImage("camera", img)
    if cv.WaitKey(10) > 0:
        break
cv.DestroyAllWindows()

「カチャカチャカチャ・・・ッターンッ!!」これで出来上がったぜいぇーいとなるはずだったんです。

実行時エラーがでました。

$ python camera.py
Xlib:  extension "RANDR" missing on display ":11.0".

(camera:31765): GdkGLExt-WARNING **: Window system doesn't support OpenGL.

お前の環境だとOpenGLに対応してね~から実行は無理というものでした。オゥフ。 これまでは画像のキャプチャのみを行っていたので表示系まではやっていなかったので気がついてイなかったみたいです。というかXを使っていなかったというのが正しいw。

今回はコンソール(Teraterm)の代わりにWindowsにデフォルトでインストールされている【リモートデスクトップ接続】を使っていました。これが原因なんだろうなあと思って、気が重くなりました。個人的には経験からLinux系の設定のツラミはほぼほとんどがX関係っていうことが多くキツイ目にあっていたので。

といっても、GUIの無い画像処理はありえないと思うので解決を模索します。

早速エラーメッセージ関係でググってみると以下の記事にあたりました。

Raspberry Pi • View topic - Enable OpenGL on Raspbian Jessie for OpenCV

内容としては「OpenGL系の対応ライブラリが入っていないのでインストールせよ」というものでした。 では早速インストールしてみます。

$ sudo apt-get install libgl1-mesa-dri

動いてくれ頼む!

$ python camera.py
Xlib:  extension "RANDR" missing on display ":11.0".

(camera:31765): GdkGLExt-WARNING **: Window system doesn't support OpenGL.

変わっていねえ…(一部の数値とか変わるみたいですが、キャプチャ忘れました)

作戦変更へ

どうも以前入れたVNCサーバであるTightVNCserverがX接続すると別のディスプレイ接続環境を生成して、接続を行うという特徴があるというものだったので、純粋にハード的なXではなくソフトウエア上で動いている(表現がおかしいが)Xということだったようです。

X環境は基本設定をしないと共有されるはずですが、それがTightVNCserverにはなかったので若干不思議ではあったのですが、なんとなく理解できました。

そこでRaspberryPiのVNCサーバを

tightvncserver から x11vncに変更することにします。

X11vnc - ArchWiki

一応、ぐぐってみるとと実績があるようでした。

機能がバッティングしていることも考えてアンインストールしてからインストールを行っています。

$ sudo apt-get remove tightvncserver
$ sudo apt-get install x11vnc

インストールは全くトラブルなく終了しました。

x11vncの設定

以下のサイトが詳しく乗っていたので参考にしました。

www.1ft-seabass.jp

流れとしては

  • vnc接続用のパスワード設定
  • vncserverの起動
  • vncviewerからの接続

となります。

それが完了したら

*自動起動を設定

を行います。

vnc接続用のパスワード設定

vncではユーザという考え方以外にもvnc用のパスワードが存在しています。そのパスワードを作成することになります。

$ x11vnc -storepasswd
Enter VNC password:
Verify password:
Write password to /home/pi/.vnc/passwd?  [y]/n y
Password written to: /home/pi/.vnc/passwd

このコマンドで/home/pi/.vnc/passwdにパスワード情報が生成されます。このパスがパスワードファイルのデフォルト場所のようです。

vncserverの起動

後はVNCサーバを起動しますがテストであれば

$ x11vnc -usepw

の実行でいいかなと思います。オプションの-usepwは最初に設定したパスワードを使用するという宣言になります。

起動が正常にできて、このままずーっとVNCサーバを起動状態にする場合には以下の様に実行します。

$ x11vnc -usepw -forever

今回こそはとおもったんですが、失敗しました。

エラーメッセージの内容としては「VNCからXのディスプレイ:0に接続できないです」(意訳)というものでした。

ここからが苦痛でした。

エラーの内容からするとXがどうも立ち上がっていない様子。 しかし、HDMIを接続するとXは立ち上がりログインもできる。

そこで実験としてraspi-configコマンドでCLI環境とし、HDMIを接続しない状態でターミナルを2つ立ち上げて、一つでstartxを起動すると無事に起動しました。(WindowManegerはない状態ではあります。)そのあとにVNCServerを起動するとエラーは発生せず5900ポートで接続してほしい旨のメッセージがでました。

ここで仮説を立ててみました。 HDMIモニターを繋いでいるときにはXが起動している、RaspberryPiはHDMIを繋いでいないとコンポジット側に接続を替えるという仕様だったようなきがするので、強制的にHDMI出力をするモードに させてしまえばXは勝手に起動してくれる?と思い、/boot/config.txtを編集することを試してみました。

$ sudo vim /boot/config.txt

ファイル中ほどにある以下の部分のhdmi_force_hotplug=1のコメント化を解除します。

/boot/config.txtの変更前

(略)
# uncomment if hdmi display is not detected and composite is being output
# hdmi_force_hotplug=1
(略)

/boot/config.txtの変更後

(略)
# uncomment if hdmi display is not detected and composite is being output
hdmi_force_hotplug=1
(略)

ようやくこれでXは自動で起動してくれる様になりました。(これでほぼ1日潰れました) 後は前述のコマンドでVNCServerを起動します。

$ x11vnc -usepw
26/02/2017 13:29:15 -usepw: found /home/pi/.vnc/passwd
26/02/2017 13:29:15 x11vnc version: 0.9.13 lastmod: 2011-08-10  pid: 5984
26/02/2017 13:29:15 XOpenDisplay("") failed.
26/02/2017 13:29:15 Trying again with XAUTHLOCALHOSTNAME=localhost ...
26/02/2017 13:29:15

(略)

The VNC desktop is:      raspberrypi:0
PORT=5900

(略)

そしてリモートデスクトップ接続からRaspberryPiに接続、xrdp経由でVNCに接続となります。 注意点としては

  • 接続後のモジュール選択を【vnc-any】
  • IPには接続する【RaspberryPiのIPアドレス
  • portにはVNCServerの起動時に指定された【ポート番号(初期値は5900)】

を設定することになります。

ログイン画面のダイアログは以下の様になります。

f:id:ueponx:20170226132624j:plain

ここまできたら後は、目的のサンプルプログラムを実行してみます。

f:id:ueponx:20170226133643j:plain

うまく実行でき、やっと第一歩が踏み出せました。

後は自動起動の設定となります。

自動起動設定

まず、/home/pi/.config/autostart/というディレクトリを作成し、そのフォルダの中にx11vnc.desktopというファイルを作成します。

$ sudo mkdir /home/pi/.config/autostart/
$ sudo vim /home/pi/.config/autostart/x11vnc.desktop

x11vnc.desktop

[Desktop Entry]
Encoding=UTF-8
Type=Application
Name=X11VNC
Comment=
Exec=x11vnc -forever -display :0 -rfbauth /home/pi/.vnc/passwd
StartupNotify=false
Terminal=false
Hidden=false

続いてはraspi-configの設定をします。前述の設定ではログインしないと自動設定が行われないので自動でログインする設定にします。セキュリティとしては微妙ですが今回は目を瞑ります。

raspi-configを起動して【3. Boot Options】を選択

f:id:ueponx:20170226140556j:plain

画面が切り替わったら【B1. Desktop / CLI】を選択

f:id:ueponx:20170226140610j:plain

画面が切り替わったら【B4. Desktop Autologin Desktop GUI. automatically logged in as ‘pi’ user】を選択

f:id:ueponx:20170226140627j:plain

設定が終わったら再起動すると、リモートデスクトップから即ログインができるようになっています。

おまけ

リモートデスクトップ接続の画面が狭くなりますが、先程編集した/boot/config.txtに解像度のパラメータもありますので、これを変更することで広くすることができます。

sudo vi /boot/config.txt

/boot/config.txtの変更前

(略)
# framebuffer_width=1280
# framebuffer_height=720
(略)

/boot/config.txtの変更後

(略)
framebuffer_width=1280
framebuffer_height=720
(略)

これで1280*720の解像度で起動が行われます。

f:id:ueponx:20170226143214j:plain

おわりに

思った以上につまずいてしまって泣けましたが、これでもう障壁はないかなと思う(と思いたい)ので、引き続きOpenCVもやっていきたいと思います。

/* -----codeの行番号----- */