LoginSignup
2
1

More than 1 year has passed since last update.

【#UnitV2入門】camera_streamを改造して、リアルタイムエッジ抽出をやってみた♪

Last updated at Posted at 2021-11-02

今回は、UnitV2で遊んでみた。

しかし、その道のりが長かったので、まとめます

以下の解説で、「VSCodeを使うので、VSCode devcontainerの機能を使います」
ということで、VSCode+Docker containerを利用というのは、Windows10だと、WSL2+VSCodeということで、それなりにハードルは、高い。
さらに、ししかわさんのサイトの通りやっても、OpenCVのversionが現在4.4.0から4.5.4に上がってウワンには動かせなかった。
ということで、WSL2インストールからのお話をまとめることとする。
【参考】
M5Stack UnitV2Frameworkをビルドする:ししかわの二足ロボ研修 Part.6
SSH Connect
UnitV2
WSL2の環境構築手順

WSL2環境構築

新しいマシンのインストールは、以下のリンクのとおりで実施できる。
Power shellを管理者権限で開いて以下を実行して、helpが出たら以下の古い場合の手順へ

wsl --install

WSL のインストール

古い場合の手順

以前のバージョンの WSL の手動インストール手順
WSL2 + Docker Desktop + VSCode(Remote - Containers) でGoの開発環境構築

管理者として PowerShell を開き、以下を実行します。

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart

[設定] メニューで、最新の Windows バージョンに更新

Windows Updateを実施し、最新版に更新する

仮想マシンの機能を有効にする

管理者として PowerShell を開き、以下を実行します。

dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

Linux カーネル更新プログラム パッケージをダウンロードする

x64 マシン用 WSL2 Linux カーネル更新プログラム パッケージ
をダウンロードしてダブルクリックしてインストールする。

WSL 2 を既定のバージョンとして設定する

PowerShell を管理者権限で開いて次のコマンドを実行する
これを実行すると、次にインストールするubuntu 20.04のベースWSLがWSL2になる。

wsl --set-default-version 2

Microsoft Store を開き、ubuntu20.04を選択

StoreでWSLやubuntuで検索すると候補が出てくる。ちなみにubuntuもインストールできるが、バージョンが時々になるとのこと。
やり直したいときのuninstallは「アプリと機能」からアンインストールして、やり直しします。
Windows Subsystem for LinuxからUbuntuをアンインストール

インストール状況の確認

PowerShellを管理者権限で開いて以下を実行すると2が確認できる

PS C:\WINDOWS\system32> wsl -l -v
  NAME            STATE           VERSION
* Ubuntu-20.04    Running         2

また、ubuntuもWSLのコマンドラインから以下で確認できる。

$  lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.3 LTS
Release:        20.04
Codename:       focal

vscodeのインストール

Dockerインストール

以下をダウンロードしてインストールする。
Docker Desktop for Windows
Power Shellを管理者権限で開いて以下実行し、確認する。

PS C:\WINDOWS\system32> docker version
error during connect: In the default daemon configuration on Windows, the docker client must be run with elevated privileges to connect.: Get "http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.24/version": open //./pipe/docker_engine: The system cannot find the file specified.
Client:
 Cloud integration: 1.0.17
 Version:           20.10.8
 API version:       1.41
 Go version:        go1.16.6
 Git commit:        3967b7d
 Built:             Fri Jul 30 19:58:50 2021
 OS/Arch:           windows/amd64
 Context:           default
 Experimental:      true

WSL2でも同様に、ただしこちらはDockerをactivateしていないと注意がでたので、

$ docker version
The command 'docker' could not be found in this WSL 2 distro.
We recommend to activate the WSL integration in Docker Desktop settings.
For details about using Docker Desktop with WSL 2, visit:
https://docs.docker.com/go/wsl2/

Desctopに出ているポップからactivate(Docker start;下図参照)を実行した。
その後、以下のようにUbuntu上でもpermission deniedが出ているが上と同様な情報が得られる。
docker_start.jpg

$ docker version
Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/version": dial unix /var/run/docker.sock: connect: permission denied
Client: Docker Engine - Community
 Cloud integration: 1.0.17
 Version:           20.10.8
 API version:       1.41
 Go version:        go1.16.6
 Git commit:        3967b7d
 Built:             Fri Jul 30 19:54:22 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

そして、

$ sudo docker version
[sudo] password for ubuntu:
Client: Docker Engine - Community
 Cloud integration: 1.0.17
 Version:           20.10.8
 API version:       1.41
 Go version:        go1.16.6
 Git commit:        3967b7d
 Built:             Fri Jul 30 19:54:22 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.8
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.16.6
  Git commit:       75249d8
  Built:            Fri Jul 30 19:52:31 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.4.9
  GitCommit:        e25210fe30a0a703442421b0f60afac609f950a3
 runc:
  Version:          1.0.1
  GitCommit:        v1.0.1-0-g4144b63
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

VScodeのインストール

Thanks for downloading VS Code for Windows!
から、ダウンロードしてインストール。
これで、以下のコマンドで立ち上げられます。

$ code .

VSCoceの拡張機能 Remote-Containersをインストール

Docker Official Images

Docker Official Images

venv利用して仮想環境構築+requirements.txtでインストール

WSL2で仮想環境構築

まず、WSL2上で以下の作業を実施。python_ex2という仮想環境を構築する。

$ python3 -m venv python_ex2
$ cd python_ex2
ubuntu@DESKTOP-4CJ3TFH:~/python_ex2$ source bin/activate
(python_ex2) ubuntu@DESKTOP-4CJ3TFH:~/python_ex2$ code .

最後のcode .でVSCodeを立ち上げると、下の図の最下段のバーのようにこの仮想環境の属性が見える。
インストールは、requirements.txtで行えるものと追加でpytorch関係をpipでインストールした。
結果として、pip freezeして出力したものをrequirements.txtに張り付けた。
vscode_env_requirements_py.jpg

ubuntu@DESKTOP-4CJ3TFH:~/python_ex2$ pip install -r requirements.txt
Collecting cycler==0.10.0
  Using cached cycler-0.10.0-py2.py3-none-any.whl (6.5 kB)
Collecting kiwisolver==1.3.2
  Using cached kiwisolver-1.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl (1.2 MB)
Collecting matplotlib==3.4.3
  Using cached matplotlib-3.4.3-cp38-cp38-manylinux1_x86_64.whl (10.3 MB)
Collecting numpy==1.21.3
  Using cached numpy-1.21.3-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl (15.7 MB)
Collecting Pillow==8.4.0
  Using cached Pillow-8.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.1 MB)
Collecting pyparsing==3.0.3
  Using cached pyparsing-3.0.3-py3-none-any.whl (96 kB)
Collecting python-dateutil==2.8.2
  Using cached python_dateutil-2.8.2-py2.py3-none-any.whl (247 kB)
Collecting six==1.16.0
  Using cached six-1.16.0-py2.py3-none-any.whl (11 kB)
Collecting typing-extensions==3.10.0.2
  Using cached typing_extensions-3.10.0.2-py3-none-any.whl (26 kB)
Installing collected packages: six, cycler, kiwisolver, python-dateutil, numpy, pyparsing, Pillow, matplotlib, typing-extensions
Successfully installed Pillow-8.4.0 cycler-0.10.0 kiwisolver-1.3.2 matplotlib-3.4.3 numpy-1.21.3 pyparsing-3.0.3 python-dateutil-2.8.2 six-1.16.0 typing-extensions-3.10.0.2
ubuntu@DESKTOP-4CJ3TFH:~/python_ex2$ pip3 install torch torchvision torchaudioCollecting torch
  Using cached torch-1.10.0-cp38-cp38-manylinux1_x86_64.whl (881.9 MB)
Collecting torchvision
  Using cached torchvision-0.11.1-cp38-cp38-manylinux1_x86_64.whl (23.3 MB)
Collecting torchaudio
  Downloading torchaudio-0.10.0-cp38-cp38-manylinux1_x86_64.whl (2.9 MB)
     |████████████████████████████████| 2.9 MB 2.1 MB/s 
Requirement already satisfied: typing-extensions in ./python_ex2/lib/python3.8/site-packages (from torch) (3.10.0.2)
Requirement already satisfied: pillow!=8.3.0,>=5.3.0 in ./python_ex2/lib/python3.8/site-packages (from torchvision) (8.4.0)
Requirement already satisfied: numpy in ./python_ex2/lib/python3.8/site-packages (from torchvision) (1.21.3)
Installing collected packages: torch, torchvision, torchaudio
Successfully installed torch-1.10.0 torchaudio-0.10.0 torchvision-0.11.1

これでpython環境が構築できました。
いよいよUnitV2の環境を構築します。

UnitV2を使う

ここからは、以下の参考の記事の通りにすすめます。
【参考】
【中級者向け】M5Stack UnitV2のOpenCVバージョンを上げる手順

gitする

WSL2上で、以下のようにgitする。

$ git clone https://github.com/mongonta0716/UnitV2Framework-docker.git
$ cd UnitV2Framework-docker
$ code .

VSCodeが開いたら、reopen in containerして、環境構築

一か所、opencv2の所在が参考とは異なっていたので、以下に変更
"/external/opencv/install/arm/include/opencv4/opencv2",

c_cpp_properties.json
{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**",
                "/external/opencv/install/arm/include/opencv4/opencv2", 
                "${workspaceFolder}/include",
                "${workspaceFolder}/include/ncnn"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/clang",
            "cStandard": "c11",
            "cppStandard": "c++14",
            "intelliSenseMode": "linux-clang-x64"
        }
    ],
    "version": 4
}

以下で、cmakeすると、

cmake -B build/arm -DOPENCV_DIR=/external/opencv/build/arm/ -DCMAKE_TOOLCHAIN_FILE=./platforms/arm.toolchain.cmake -DTARGET=camera_stream .
cmake --build build/arm

以下のように、bin配下にcamera_streamが作られている。
VSCODE_Docker_Opencv_454.jpg
ちなみに、camera_streamのコードは、以下の通り

camera_stream.cpp
#include <opencv2/core/utility.hpp>
#include <opencv2/tracking.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc/types_c.h>
#include <iostream>
#include <cstring>
#include "framework.h"

using namespace cv;

#define IMAGE_DIV 2

int main( int argc, char** argv )
{
    startFramework("Camera Stream", 640, 480);
    int low_quality_mode = false;

    while(1)
    {
        Mat mat_src;
        getMat(mat_src);

        if(low_quality_mode == true)
        {
            resize(mat_src, mat_src, Size(), 1.0f / IMAGE_DIV, 1.0f / IMAGE_DIV, INTER_AREA);
        }

        std::string payload;
        if(readPIPE(payload))
        {
            try
            {
                DynamicJsonDocument doc(1024);
                deserializeJson(doc, payload);
                if((doc["config"] == "web_update_data") || (doc["config"] == getFunctionName()))
                {
                    if(doc["operation"] == "enable")
                    {
                        low_quality_mode = true;
                        sendPIPEMessage("Low Quality Mode Enabled.");
                    }
                    else
                    {
                        low_quality_mode = false;
                        sendPIPEMessage("Low Quality Mode Disabled.");
                    }
                }
            }
            catch(...)
            {
                fprintf(stderr, "[ERROR] Can not parse json.");
            }
        }

        Mat gray_img;
        cvtColor(mat_src, gray_img, CV_BGR2GRAY);
        sendMat(gray_img);
    }

    return 0;
}

try~catchの部分を削除すると、以下のようにシンプルになる。
以下はこのコードですすめ、入れ替えができているかを見ることとする。

camera_stream.cpp
#include <opencv2/core/utility.hpp>
#include <opencv2/tracking.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc/types_c.h>
#include <iostream>
#include <cstring>
#include "framework.h"

using namespace cv;

#define IMAGE_DIV 2

int main( int argc, char** argv )
{
    startFramework("Camera Stream", 640, 480);
    int low_quality_mode = false;

    while(1)
    {
        Mat mat_src;
        getMat(mat_src);

        //Mat gray_img;
        //cvtColor(mat_src, gray_img, CV_BGR2GRAY);
        //sendMat(gray_img);
        sendMat(mat_src);
    }

    return 0;
}

まず、上と同じようにVSCodeのターミナルで、以下を実行してbuildする。

$ cmake -B build/arm -DOPENCV_DIR=/external/opencv/build/arm/ -DCMAKE_TOOLCHAIN_FILE=./platforms/arm.toolchain.cmake -DTARGET=camera_stream .
$ cmake --build build/arm

opencv4.5.4のlibを転送するために、VSCodeにインストールされた資材を参考の通り圧縮し、UnitV2に転送する。

cd /external/opencv/install/arm
tar -zcvf /workspaces/UnitV2Framework-docker/opencv.tar.gz bin include lib share

以下参考のとおり、UnitV2側でsudoを利用できるようにする
M5Stack UnitV2を弄るための備忘録

次にUnitV2に入って、

$ ssh m5stack@10.254.239.1

以下で書き込み可にする。

unitv2% sudo chmod 666 /dev/null

PC側に戻って、scpで先ほどの圧縮ファイルとcamera_streamを転送

unitv2% ctrl-D
$ cd ~/UnitV2Framework-docker
$ scp ./opencv.tar.gz m5stack@10.254.239.1:/home/m5stack
$ scp bin/camera_stream m5stack@10.254.239.1:/home/m5stack

そして、転送したファイルをunitv2上で解凍する。

unitv2% sudo cp opencv.tar.gz /
        cd /
        sudo zcat opencv.tar.gz | sudo tar -xvf -

次にcamera_streamの入れ替えをする。
実行ファイルは、/home/m5stack/payload/binに置かれてる。
※念のため元のファイルはバックアップを取りましょう。

unitv2% cd /home/m5stack
unitv2% sudo mv payload/bin/camera_stream camera_stream.bak
unitv2% sudo mv camera_stream payload/bin

これで、UnitV2を以下のように再起動すると、web(http://10.254.239.1/)に新しい実行ファイルが起動しているのがわかります。
※立ち上がりにタイムラグ(1min程度)かかります

unitv2% sudo reboot

以下の部分のコメントアウト部分が白黒画像、元のものがカラーであり、これを入れ替えてbuildし、一連の置き換えをすると変更されたことがわかります。

        //Mat gray_img;
        //cvtColor(mat_src, gray_img, CV_BGR2GRAY);
        //sendMat(gray_img);
        sendMat(mat_src);

ちょっと書き換えて

以下の参考から「カメラからの映像をリアルタイムにエッジ抽出」のコードを参考にcamera_streamを書き換えてみました。
【参考】
OpenCV 4.3 (C++) で Hello World と顔検出

Real_time_edge_extract.cpp
#include "opencv2/imgproc.hpp"
#include <opencv2/core/utility.hpp>
#include <opencv2/tracking.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc/types_c.h>
#include <iostream>
#include <cstring>
#include "framework.h"


using namespace cv;

int main(int, char**) {

    //VideoCapture cap(0);
    //if(!cap.isOpened()) return -1;
    startFramework("Camera Stream", 640, 480);
    int low_quality_mode = false;

    while(1)
    {
        Mat mat_src;
        getMat(mat_src);
        Mat edges;
        //namedWindow("edges", WINDOW_AUTOSIZE);

        //cap >> mat_src;

        // 色をグレースケールに
        cvtColor(mat_src, edges, COLOR_BGR2GRAY);

        // ガウスフィルターで画像をぼかす
        GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5);

        // キャニー法によるエッジ抽出
        Canny(edges, edges, 0, 30, 3);

        // ウィンドウを表示
        //imshow("edges", edges);
        //if(waitKey(30) >= 0) break;
        sendMat(edges);
    }

  return 0;
}

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1