1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ラズパイのカメラモジュールで撮影した画像を表示する

Last updated at Posted at 2020-12-28

手持ちのラズパイ4にカメラモジュールV2.1を付けたので、試しに簡単なプログラムを作成してみました。その際色々苦労したので、調べ直す必要がないようにメモを残します。

#openCVを使ったプログラム
openCVにはカメラ取り込む機能もあり、また画面表示の機能もあるので非常に便利です。

test.py
import cv2
camera = cv2.VideoCapture(0)
camera.set(cv2.CAP_PROP_FRAME_WIDTH,640)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT,480)
while True:
    _,image = camera.read()
#エフェクトを追加する行
    cv2.imshow('camera',image)
    key = cv2.waitKey(1)
    if key != -1:
        break
camera.release()
cv2.destroyAllWindows()

ウィンドウ上でキーを押すと、停止するようになっています。

##プログラムの説明
カメラの初期化は下の部分で行っています。画面サイズは特定の値を入れないと画像が崩れます。またVideoCaptureの引数はデバイスIDなので環境により変化するかもしれません。

camera = cv2.VideoCapture(0)
camera.set(cv2.CAP_PROP_FRAME_WIDTH,640)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT,480)

連続して画像を撮るのは下の部分で行っています。camera.readメソッドによりループが回る度にframeに新しい画像データを入れています。

while True:
    _,image = camera.read()

ウィンドウ表示は下の部分で行っています。waitKeyメソッドがないと表示されません。

    cv2.imshow('camera',image)
    key = cv2.waitKey(1)

開いたウィンドウを閉じる処理は下の部分で行っています。

camera.release()
cv2.destroyAllWindows()

#picameraとpygameを使ったプログラム
openCVだけもよいのですが、同じウィンドウ上にアイコン表示やマウス操作も考えるとpygameを使った方が便利そうです。(ついでに、画像取り込みをpicameraモジュールにしてみました。)ネットではcaptureメソッドを使っているサイトが多々ありましたが、今回はcapture_continuousメソッドを使っています。

test2.py
import picamera
from picamera.array import PiRGBArray
import pygame
import cv2                                                           #エフェクト用
width = 480
height = 640
camera = picamera.PiCamera()
camera.resolution = (height,width)
pygame.init()
screen = pygame.display.set_mode((width,height))
rawCapture = PiRGBArray(camera,size=(height,width))
for frame in camera.capture_continuous(rawCapture,format='rgb',use_video_port=True):
    image = frame.array
#エフェクトを追加する行
    surf = pygame.surfarray.make_surface(image)
    screen.blit(surf,(0,0))
    pygame.display.flip()
    rawCapture.truncate(0)

終了する際はCtrl+Cでプログラムを止めてください。

##プログラムの説明
カメラの初期化は下の部分で行っています。resolutionで取り込む画像の大きさを決めていますが、何故か縦と横の並びが逆になっています。

camera = picamera.PiCamera()
camera.resolution = (height,width)

pygameのウィンドウ表示は下の部分で行っています。

pygame.init()
screen = pygame.display.set_mode((width,height))

連続して画像を撮るのは下の部分で行っています。capture_continuousメソッドはgeneratorを作成し、ループが回る度にframeに新しい画像データを入れています。なお、use_video_port=Trueは直にビデオポートからデータを取り出すことにより高速化を図るものです。また、最後のtruncateメソッドがないと新しい画像を取り込むことができません。

rawCapture = PiRGBArray(camera,size=(height,width))
for frame in camera.capture_continuous(rawCapture,format='rgb',use_video_port=True):
    ....
    ....
    rawCapture.truncate(0)

pygameの描写に関しては下の部分で行っています。frame.arrayの部分で画像をRGBの3次元配列(480,640,3)にしています。それをpygame.surfarray.make_surfaceメソッドでpygameに使えるsurface形式に変換し、blitメソッドで画面に書き込み、flipメソッドで画面更新をしています。

    image = frame.array
    surf = pygame.surfarray.make_surface(image)
    screen.blit(surf,(0,0))
    pygame.display.flip()

#エフェクトの追加(openCV、picamera+pygame共通)
picameraモジュールにもエフェクトがありますが)ここではopenCVのエフェクトを入れてみます。プログラムの#エフェクトを追加する行を下のように変更すると、エッジ検出の画像に変えることができます。

    image = cv2.Canny(image,100,200)

画像データを受け取ったimage変数はRGBの配列形式のデータになっておりnumpyの配列と同じように演算が可能なので、直接RGBの数値を操作し画像編集をすることもできます。

#さいごに
どの方法でも画像読み込みが遅いのが気になります。もっと高速化できる方法がないかを調べたいと思います。

1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?