OpenCV4でGstreamerからの入力を受け取り表示する方法

markdown-img-paste-20210924003658374.webp
目次

はじめに

この記事では、Raspberry Piのカメラユニットの映像を別PCで動かしているOpenCVで受信し、表示する方法をGolangとGstreamerを使って実現します。Gstreamerを使って映像を配信し、Golangでその映像を受信して表示する方法を紹介します。Raspberry Pi 4を使用して配信と受信を行い、Golangを使っているため、どのOSでもある程度の使い回しが可能です。

Gstreamerでの配信について

配信する側もゆくゆくはソフトとして作っていきますが、今回はコマンドラインで代用します。

Gstreamerの動作確認

インストール済みだとは思いますが、映像を配信できるかを確かめます。

videotestsrcで起動すると映像が配信されます。pattern=snowを選択すると、 地デジになる前のテレビで電波が届いていないときに表示されていたような映像が流れます。(伝わるかしら)映画ドラえもんブリキのラビリンスで、深夜子どもたちが見ていたあのジャギジャギの映像です。

参考 videotestsrc

gst-launch-1.0 -v videotestsrc pattern=snow ! video/x-raw,width=1280,height=720 ! autovideosink

実行するとこんな感じで映像が取得されます。

ジャギジャギなのはあまり落ち着かないので別の映像で試します。

gst-launch-1.0 -v videotestsrc ! video/x-raw,width=1280,height=720 ! autovideosink

後ろでYoutube見ているのがバレちゃいますが、Terminalと合わせてこのように出力されているのが確認できます。

gocvでGstreamerの映像を取得する

映像の配信で使用していたautovideosinkをappsinkに変更すればOKです。

gst-launch-1.0 -v videotestsrc ! video/x-raw,width=1280,height=720 ! appsink

指定されたサイズの映像が、appsinkに流れています。 Terminalでは時間が経過するばかりで、映像が表示されません。

gocvを使ってappsinkを表示するプログラムを書いていきます。 gocvのTutorialにあるHello, videoをべ-スに作ります。

OpenVideoCaptureにgstreamerのコマンドを引数にとして渡してやればOKです。

実行コード

package main

import (
    "gocv.io/x/gocv"
)

func main() {
    src := `videotestsrc ! video/x-raw,width=1280,height=720 ! appsink`
    webcam, _ := gocv.OpenVideoCapture(src)
    window := gocv.NewWindow("Hello")
    img := gocv.NewMat()

    for {
        webcam.Read(&img)
        window.IMShow(img)
        window.WaitKey(1)
    }
}

実行結果

先ほどと表示内容に変化はないですが、Windowの名前がHelloになっていることが確認できます。

機器間配信のテスト

次は機器間をまたいで映像を取得します。 Golangで組む前にコマンドで動作することを確認しましょう。

Raspberry pi4(カメラ配信サーバ)IP:192.168.0.3

GstreamerからVideoカメラのデバイスを指定し、配信を開始します。 RTPパケットを使って映像配信を行っていきます。 udpsinkでは受信先のIPアドレスとポート番号を指定してあげます。

gst-launch-1.0 -v v4l2src device=/dev/video1 ! "image/jpeg,width=640, height=360,framerate=30/1" ! rtpjpegpay ! udpsink host=192.168.0.4 port=9000

Raspberry pi4 (映像受信サーバ) IP:192.168.0.4

gst-launch-1.0 -e -v udpsrc port=9000 ! application/x-rtp, encoding-name=JPEG,payload=26 ! rtpjpegdepay ! jpegdec ! autovideosink

実行結果

カメラ配信サーバに取り付けたUSBカメラの映像を同一ネットワークにおいている別の機器で出力してみました。 想像以上に遅延なくて少し驚いています。こんなに低遅延で実現できるのが驚いています。

tcpserversinkで配信したときは20秒ぐらい遅延があったのでそれを思うとかなり高速になっています。 あとは、WindowsとRaspberry pi2ってのも影響しているのでしょうか。 今回はRaspberry pi4を2台構成で組んでいるのでかなり安定しているように思います。いいですね。

golangから呼び出してみよう

この記事の本題に入ります。

Raspberry pi4 (映像受信サーバ) IP:192.168.0.4

Golangから読み出してやるときMat型で呼び出すためにappsinkを使います。

jpegdec以下をこのように変換します。

jpegdec ! videoconvert ! appsink

全文コード

package main

import (
    "gocv.io/x/gocv"
)

func main() {
    src := `udpsrc port=9000  ! application/x-rtp, encoding-name=JPEG,payload=26 ! rtpjpegdepay ! jpegdec ! videoconvert ! appsink`
    webcam, _ := gocv.OpenVideoCapture(src)
    window := gocv.NewWindow("Hello")
    img := gocv.NewMat()

    for {
        webcam.Read(&img)
        window.IMShow(img)
        window.WaitKey(1)
    }
}

Raspberry pi4(カメラ配信サーバ)IP:192.168.0.3

Golangから呼び出すコードを書いていきます。 Gstreamerで呼び出したコマンドをexecで実行してあげます。 他に良いやり方があれば是非教えて下さい。お待ちしております。

全文コード

package main

import (
  "fmt"
  "os"
  "os/exec"
    "strings"
)

func main() {
    args := strings.Fields("-v v4l2src device=/dev/video1 ! image/jpeg,width=640, height=360,framerate=30/1 ! rtpjpegpay ! udpsink host=192.168.0.4 port=9000")
    out, err := exec.Command("gst-launch-1.0", args...).Output()
    if err != nil {
      fmt.Println(err.Error())
      os.Exit(1)
    }
    fmt.Println(string(out))

}

実行結果

良い感じに動いています。 やりましたね!!

まとめ

この記事では、GolangとGstreamerを使ってRaspberry Piのカメラユニットの映像を別PCで動かしているOpenCVで受信し、表示する方法を紹介しました。Raspberry Pi 4で配信と受信を行い、Golangで書いているため、どのOSでもある程度使い回しができる

Related Post

> OpenCV4でGstreamerからの入力を受け取り表示する方法
Raspberry Pi 4とCamera Moduleでエラー対処法
> OpenCV4でGstreamerからの入力を受け取り表示する方法
Raspberry Pi OS再インストール後のSSH接続エラーの対処法
> OpenCV4でGstreamerからの入力を受け取り表示する方法
Windowsでgocvインストール時のエラー対処法
> OpenCV4でGstreamerからの入力を受け取り表示する方法
Raspberry PiでOpenCVインストールのトラブルシューティング
> OpenCV4でGstreamerからの入力を受け取り表示する方法
Raspberry piにGoとgocv(OpenCV 4)環境をインストールする
> OpenCV4でGstreamerからの入力を受け取り表示する方法
Raspberry PiとGStreamerを使ってWebカメラ映像を配信する方法

おすすめの商品

>