OpenCV実験python3 cv2.imreadの使い方、データ構造

とりあえず見よう見真似でpython3 OpenCVのツールをやっつけで作成したのですが、やはりよくわからない点だらけです。そんな状態でもそれなりのもが作れてしまうOpenCVのユーザの多さや簡便さが優れているものと思いますが、もう少しちゃんと基本中の基本はちゃんと理解しとかないとこれより先に知識が進まなそうですので、基本の基本から実験検証してみましたので、初心者の方の参考になれば幸いです。特にデータ構造が自分にはよくわからないので、検証してみました。

OpenCV4.0.0で実験しています。

cv2.imreadの使い方

もう何度も使っているcv2.imread(’ファイル名’)ですが、これを実際にどのようなデータ配列が作成されているのか確認してみます。テスト画像は左半分が赤、右半分が青、80x80ピクセルくらいの簡単な画像ファイルです。

赤青画像

オフィシャルサイト?のGettingStartedを参考にしてみます(バージョンは違いますが)。

Getting Started with Images

cv2.imreadの第一引数はファイルパスで、2番目の引数はOpenCV3では3つオプションがあります。

・cv2.IMREAD_COLOR (デフォルト値。intで1。カラーのまま読み込み)

・cv2.IMREAD_GRAYSCALE (グレー#スケール読み取り。intで0)

・cv2.IMREAD_UNCHANGED (intで-1。アルファチャンネルも読み込み。今回は検証しない。)

実際に引数を変えて画像を読み込むとデータ構造が、同じcv2.imreadでも変わってくるのを実際にみてみましょう。

#kiso.py
import cv2
import numpy as np

infile ='test.jpg'

#引数0,1。-1は後回し
img = cv2.imread(infile,cv2.IMREAD_COLOR)
for i in img:
        print(i)

・cv2.IMREAD_COLORの場合の出力

これはわかりやすいです。列毎(横の列)のピクセルがBGR(RGBではなくて)値が配列になっているのがわかります。

[[  0   0 254]
 [  0   0 254]
 [  0   0 254]
 #途中省略
 [255  38   0]
 [255  38   0]
 [255  38   0]]
#次の列
[[  0   0 254]
 [  0   0 254]
 [  0   0 254]
 #途中省略
 [255  38   0]
 [255  38   0]
 [255  38   0]]

・cv2. IMREAD_GRAYSCALE の場合の出力

[76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76
 76 76 76 76 76 76 76 76 76 76 77 77 76 76 76 76 77 76 78 75 77 76 50 51 51
 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51
 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51]
#次の列
[76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76 76
 76 76 76 76 76 76 76 76 76 76 77 77 76 76 76 76 77 76 78 75 77 76 50 51 51
 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51
 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51 51]
#これがひたすら続く。

グレースケールするということは具体的にはOpenCV4.0.0のサイトを見ると

https://docs.opencv.org/4.0.0/dc/d38/group__gapi__colorconvert.html#ga3e8fd8197ab16811caf9b31cb1e08a05


dst(I)=0.114∗src(I).B+0.587∗src(I).G+0.299∗src(I).R

という式がでていますので、
[ 0 0 254]はdst=0.114*0+0.587*0+0.2999*254=76 がグレースケール値

[255 38 0] はdst=0.114*255+0.587*38+0.2999*0=51 がグレースケール値

と正しそうな値が計算されます。

データ構造が違うので、たまにshapeを使ってピクセルのサイズを取りますが、取り方がちがってくる、ということですよね。

print(img.shape)

#cv2.IMREAD_COLOR 
(94, 93, 3)

# cv2. IMREAD_GRAYSCALE
(94, 93)

#高さ(h)が94ピクセル,幅(w)が93ピクセルです

よくこんな感じの画像のピクセルサイズを取るサンプルコードをみますが、これは当然グレースケールで読み込む、という前提です。カラーで読み込んだ場合はエラーですね。

w, h = img.shape[::-1]

#カラー読み込み時エラー
ValueError: too many values to unpack (expected 2)

[::-1]は逆順で要素を取り出す、ってことですよね。私のように素人プログラマが出しそうなエラーですよね。。