DEV Community

Cover image for Elixir OpenCV で hello world
Masatoshi Nishiguchi
Masatoshi Nishiguchi

Posted on

Elixir OpenCV で hello world

何事でも基本が大切だと思います。プログラミングではよく "hello, world\n" を印字したりします。OpenCV でもそれ相当のことをやってみたいと思います。

セットアップ

Mix.install([
  {:nx, "~> 0.5.0"},

  # OpenCV をつかうため
  {:evision, "0.1.31"},

  # 画像をテンソルに変換するため
  {:stb_image, "~> 0.6.0"},

  # 画像を Web からダウンロードするため
  {:req, "~> 0.3.0"},

  # Livebook 上で画像を表示するため
  # {:kino, "~> 0.9.0"}
])
Enter fullscreen mode Exit fullscreen mode

Elixir で OpenCV

cocoa-xu/evision を使うと OpenCV のほとんどの関数にElixirからアクセスできます。

cocoa-xu/evisionパッチバージョンでも破壊的な変更があるようのでバージョンをロックしておいた方が無難そうです。

https://qiita.com/RyoWakabayashi/items/2846133bc7014319d172

cocoa-xu/evision の作者は好んで Cv エイリアスを使用しているのでそれに則ります。

https://github.com/cocoa-xu/evision/tree/main/examples

alias Evision, as: Cv
Enter fullscreen mode Exit fullscreen mode

HelloWorld モジュールをつくる

画像を Web からダウンロードし、Evision.Mat に変換します。

https://qiita.com/mnishiguchi/items/1006b5cea9287a91a2d3

グラフィカルユーザーインターフェース(GUI)で画像を表示するときには Evision.HighGui モジュールが便利です。

  • Evision.HighGui.imshow/2
    • 画像ウインドウを表示
  • Evision.HighGui.waitKey/1
    • 画像ウインドウを自動で閉じるまでの時間をミリ秒で指定
    • 0 の場合はなんらかのキーが押下されるまで開いたまま
  • Evision.HighGui.destroyAllWindows/0
    • 全ての画像ウインドウを閉じる

https://hexdocs.pm/evision/Evision.HighGui.html

以下のモジュールはターミナルでもLivebookでもイゴきます。

defmodule HelloWorld do
  alias Evision, as: Cv

  @wait_time_ms 30_000

  def download_image(url) do
    Req.get!(url)
    |> then(& &1.body)
    |> StbImage.read_binary!()
    |> StbImage.to_nx()
    |> Cv.Mat.from_nx_2d()
    |> Cv.cvtColor(Cv.Constant.cv_COLOR_BGR2RGB())
  end

  def show_image_gui(img_list) when is_list(img_list) do
    for {label, img_mat} <- img_list do
      Cv.HighGui.imshow(label, img_mat)
    end

    Cv.HighGui.waitKey(@wait_time_ms)

    Cv.HighGui.destroyAllWindows()
  end

  def show_image_gui(label, img_mat) do
    show_image_gui([{label, img_mat}])
  end
end
Enter fullscreen mode Exit fullscreen mode

最初は原典に忠実に実施しようと思います。

hello world 1

ウィキペディアの画像をダウンロードして、それをGUIに表示します。

hello_img_mat1 =
  HelloWorld.download_image(
    "https://upload.wikimedia.org/wikipedia/commons/2/21/Hello_World_Brian_Kernighan_1978.jpg"
  )

HelloWorld.show_image_gui("hello OpenCV", hello_img_mat1)
Enter fullscreen mode Exit fullscreen mode

画像ウインドウがフォーカスされている状態でなんらかのキーを押すと閉じることができます。

CleanShot 2023-05-03 at 21.50.15.gif

hello world 2

せっかく OpenCV を使っているので色チャネル(BGR)を分離する技を使ってみよう思います。それぞれの色の強さを視覚的に確認できます。

hello_img_mat2 =
  HelloWorld.download_image(
    "https://upload.wikimedia.org/wikipedia/commons/8/8c/PSP-Homebrew.jpeg"
  )

HelloWorld.show_image_gui([
  {"Red", hello_img_mat2[[.., .., 2]]},
  {"Green", hello_img_mat2[[.., .., 1]]},
  {"Blue", hello_img_mat2[[.., .., 0]]},
  {"BGR", hello_img_mat2}
])
Enter fullscreen mode Exit fullscreen mode

CleanShot 2023-05-03 at 22.10.36.gif

Do your career a big favor. Join DEV. (The website you're on right now)

It takes one minute, it's free, and is worth it for your career.

Get started

Community matters

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay