ラベル OpenCV の投稿を表示しています。 すべての投稿を表示
ラベル OpenCV の投稿を表示しています。 すべての投稿を表示

2024年4月21日日曜日

【OpenCV】VideoCapture()によるカメラからの画像・動画撮影

 画像処理ライブラリOpenCVでカメラによる画像・動画撮影を行う場合VideoCapture()を使う。


OpenCVを使うにはインポートが必要。

import cv2



1. カメラによる画像撮影

 PC等デバイスに接続されているカメラを使用する場合、始めにcv2.VideoCapture()の引数にデバイス番号を与え、VideoCaptureオブジェクトを生成する。PCに接続しているカメラが1台の場合通常、デバイス番号は0となる。カメラから画像を読み出す場合、生成したVideoCaptureオブジェクトに対してread()を使う。戻り値はretval, imageの2つ。retvalには画像が取得できたかどうかが返され、戻り値はTrue,Falseとなる。imageには取得した画像が返される。

 デバイス番号0を指定しPCのカメラでVideoCaptureオブジェクトを生成、read()で画像を習得し、imwrite()で画像を保存する例。cap.release()VideoCaptureオブジェクトのメモリを開放している。

import cv2

cap = cv2.VideoCapture(0)
retval, image = cap.read()

cv2.imwrite('capture.png', image)

cap.release()


 カメラのフレームレート、画像サイズを取得するには、生成したVideoCaptureオブジェクトに対して、get()を適用する。get()の引数をcv2.CAP_PROP_FPSとすることでフレームレート、cv2.CAP_PROP_FRAME_WIDTHとすることで画像幅、cv2.CAP_PROP_FRAME_HEIGHTとすることで画像高さが取得できる

import cv2

cap = cv2.VideoCapture(0)

fps = cap.get(cv2.CAP_PROP_FPS)
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)

print(fps, width, height)

 実行結果

30.0 640 480


2. カメラによる動画撮影

 カメラから動画を取得して保存する場合、VideoCapture()で取得した画像をVideoWriterオブジェクトに逐次追加する。この際に保存する動画サイズを取得画像と揃える必要がある。
次の例では
VideoCaptureオブジェクトcapの生成
②capのフレームレート、画像幅、高さの取得
VideoWriterオブジェクトoutの生成(コーデックmp4vを指定、フレームレート、画像幅、高さはcapと同じとする)
④capの読み出し、outへの書き込みを100回繰り返す
⑤cap,outのリリース
の手順でカメラから動画を撮影している。なお、cap.getによって取得した画像幅、高さはfloat型のためVideoWriterオブジェクトと幅、高さ指定の際にはint()で整数型に変更する。

import cv2

cap = cv2.VideoCapture(0)

fps = cap.get(cv2.CAP_PROP_FPS)
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)

fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') 
out = cv2.VideoWriter('video.mp4', fourcc, fps, (int(width), int(height))) 

for i in range(100):
    retval, image = cap.read()
    out.write(image)

cap.release()
out.release()     


3. リファレンス

OpenCV > VideoCapture Class Reference > VideoCapture()
OpenCV > VideoCapture Class Reference > VideoCaptureProperties
OpenCV > VideoCapture Class Reference > read()
OpenCV > VideoCapture Class Reference > release()

使用したバージョン:Python 3.10.4 / OpenCV 4.9.0

2022年5月8日日曜日

【OpenCV】画像の生成

 画像処理ライブラリOpenCVの画像はNumpyndarray形式なので、画像を新規に生成する場合ndarrayを作成すればよい


OpenCV、Numpyを使うにはインポートが必要。
OpenCV

import cv2

Numpyは、しばしば次のようにnpと略されてインポートされる。

import numpy as np



1. グレースケール画像の生成

 グレースケール画像は0-255の256画素値の1チャンネル画像。全要素の値が0のndarrayを生成するnumpy.zeros、全要素の値が1のndarrayを生成するnumpy.ones、全要素が任意の値となるndarrayを生成するnumpy.fill等により生成する。

 numpy.zerosで幅400ピクセル高さ250ピクセルの黒い画像(画素値0)を生成する例。OpenCVの画像フォーマットは(高さのピクセル数、幅のピクセル数、チャンネル数)でグレースケール画像はチャンネル数が1なので引数に(250, 400, 3)を指定する。またdata-typeとして符号なし8ビット整数のデータ型を指定する引数、numpy.uint8を指定する。

import numpy as np
import cv2

img = np.zeros((250, 400, 1), np.uint8)

cv2.imwrite('img.jpg', img)

実行結果





 numpy.zerosで生成した全要素の値が0のndarrayに100を加算し、全要素が100のndarrayとして灰色の画像を作成する例

import numpy as np
import cv2

img = np.zeros((250, 400, 1), np.uint8)+100

cv2.imwrite('img.jpg', img)

実行結果





 全要素の値が1のndarrayを生成するnumpy.onesを使用する例。

import numpy as np
import cv2

img = np.ones((250, 400, 1), np.uint8)*200

cv2.imwrite('200.jpg', img)

実行結果





 全要素が任意の値を持つndarrayを生成するnumpy.fullを使用する例。引数にはndarrayの形状の他、要素の値(ここでは150)を指定する。

import numpy as np
import cv2

img = np.full((250, 400, 1), 150, np.uint8)

cv2.imwrite('img.jpg', img)

実行結果





2. カラー画像の生成

 カラー画像ではチャンネル数がB(青)、G(緑)、R(赤)の3チャンネルとなるため、(高さのピクセル数、幅のピクセル数、チャンネル数3)ndarrayを生成すればよい。また、チャンネル別の値はインデクシングで設定できる。
幅400高さ250ピクセルの3チャンネルの画像を生成しBチャンネルの画素値を100、Gチャンネルの画素値を250、Rチャンネルの画素値を30とする例。

import numpy as np
import cv2

img = np.zeros((250, 400, 3), np.uint8)

img[:, :, 0] = 100  # Bチャンネルの値を100
img[:, :, 1] = 250  # Gチャンネルの値を250
img[:, :, 2] = 30  # Rチャンネルの値を30

cv2.imwrite('img.jpg', img) 

実行結果





3. リファレンス

Numpy > numpy.zeros
Numpy > numpy.ones
Numpy > numpy.full

使用したバージョン:Python 3.10.4 / OpenCV 4.5.5

2022年5月6日金曜日

【OpenCV】画像のアルファブレンド

 アルファブレンドは2つ(以上)の画像を係数を用いて合成する方法。画像処理ライブラリOpenCVaddWeightedによるアルファブレンドおよびndarrayの和によるアルファブレンドについて説明する。


OpenCVを使うには次のようにインポートが必要。
import cv2

例に用いる画像'buiding.jpg', 'girl.jpg'(幅450x高さ300ピクセル)は以下を使用(フリー写真素材ぱくたそより)

'buiding.jpg'



'girl.jpg'





1. addWeightedによるアルファブレンド

 addWeightedは2つの画像を係数をかけて合成する。合成する画像のサイズは同じでないといけない。
書式は以下。

cv.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]] ) -> dst

src1src2が合成する2つの画像。下式のようにalphasrc1に対する係数、betasrc2に対する係数、gammaはオフセットとなる。

dst = src1*alpha + src2*beta + gamma

 カラー画像のように複数のチャンネルがある場合は、各チャンネルごとに合成される。また、画素値の上限255を超えた場合は255となり飽和(白飛び)する。


alpha:0.5beta:0.5gamma:0として画像を合成する例

import cv2

src1 = cv2.imread('building.jpg')
src2 = cv2.imread('girl.jpg')

blend = cv2.addWeighted(src1, 0.5, src2, 0.5, 0)	

cv2.imwrite('blend.jpg', blend)



alpha:0.2beta:0.2gamma:150として画像を合成する例

import cv2

src1 = cv2.imread('building.jpg')
src2 = cv2.imread('girl.jpg')

blend = cv2.addWeighted(src1, 0.25, src2, 0.25, 150)	

cv2.imwrite('blend.jpg', blend)



2. ndarrayの和によるアルファブレンド

 OpenCVの画像はnumpy.ndarrayなので演算による合成が可能。addWeightedalpha:0.2beta:0.2gamma:150と同じ処理をする例。addWeightedと同じ結果が得られる。

import cv2

src1 = cv2.imread('building.jpg')
src2 = cv2.imread('girl.jpg')

blend = src1*0.25 + src2*0.25 + 150	

cv2.imwrite('blend.jpg', blend)



 addWeightedで合成できるのは2つの画像だがnumpy.ndarrayの演算では合成する画像の数に制限はない。
さらに3つ目の画像'mountain.jpg'を合成する例。

'mountain.jpg' (幅450x高さ300ピクセル)は以下を使用(フリー写真素材ぱくたそより)



import cv2

src1 = cv2.imread('building.jpg')
src2 = cv2.imread('girl.jpg')
src3 = cv2.imread('mountain.jpg')

blend = src1*0.3 + src2*0.3 + src3*0.3	

cv2.imwrite('blend3.jpg', blend)




3. リファレンス

OpenCV > Operations on arrays > addWeighted()

使用したバージョン:Python 3.10.4 / OpenCV 4.5.5

【OpenCV】cvtColorによるBGRからグレースケール, HSVへの色空間変換

 画像処理ライブラリOpenCVcvtColorにより色空間の変換ができる。頻繁に行われるBGR色空間からグレースケールへの変換、BGR色空間からHSV色空間への変換を説明する。

OpenCVを使うには次のようにインポートが必要。

import cv2

 使用する画像 'iwojima.jpg'(幅400ピクセルx高さ300ピクセル)は以下(フリー写真素材ぱくたそより)





1. BGR色空間からグレースケールへの変換

 cvtColorの書式は以下。dstが変換前の画像、srcが変換後の画像、codeが変換方法を示すコードとなる。

dst = cvtColor(src, code)

BGR色空間→グレースケール変換の場合、codecv2.COLOR_BGR2GRAYを用いる。

dst = cvtColor(src, cv2.COLOR_BGR2GRAY)

BGR色空間→グレースケール変換し変換後の画像をファイルに保存する例

import cv2
from cv2 import imwrite

img = cv2.imread('iwojima.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

cv2.imwrite('gray.jpg', gray)



2. BGR色空間からHSV色空間への変換

 HSV色空間はH(Hue:色相)、S(Saturation:彩度)、V(Value:明度)3チャンネルからなる色空間で、OpenCVではH[0,179], S[0,255],V[0,255]の範囲の値をとる。OpenCVのカラー画像はBGR色空間だが、HSV色空間に変換することで色相、彩度、明度を独立して調整することが可能になる。

 BGR色空間→HSV色空間の変換の場合、codecv2.COLOR_BGR2HSVを用いる。

dst = cvtColor(src, cv2.COLOR_BGR2HSV)

HSV色空間→BGR色空間の変換の場合、codecv2.COLOR_HSV2BGRを用いる。

dst = cvtColor(src, cv2.COLOR_HSV2BGR)

HSV色空間の画像はimwriteによるファイル保存等ができないため、BGR色空間に変換する必要がある。

色相Hの値を90°変更する例。h値が90より小さい画素に90加算、h値が90より大きい画素は90引いている。

import cv2
import numpy as np
from cv2 import imwrite

img = cv2.imread('iwojima.jpg')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

hsv[:, :, 0] = np.where(hsv[:, :, 0]<90,
                        hsv[:, :, 0]+90,
                        hsv[:, :, 0]-90)
bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)

cv2.imwrite('h90.jpg', bgr)



彩度Sの値を0.5倍する例。

import cv2
from cv2 import imwrite

img = cv2.imread('iwojima.jpg')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

hsv[:, :, 1] = hsv[:, :, 1]*0.5
bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)

cv2.imwrite('s05.jpg', bgr)



明度Vの値に+30加算する例。加算後に255を越えた画素は255としている。

import cv2
import numpy as np
from cv2 import imwrite

img = cv2.imread('iwojima.jpg')
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

hsv[:, :, 2] = np.where(hsv[:, :, 2]<226, 
                        hsv[:, :, 2]+30,
                        255)
bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)

cv2.imwrite('v30.jpg', bgr)



3. リファレンス

OpenCV > Color Space Conversions > cvtColor()
OpenCV > Color conversions

使用したバージョン:Python 3.10.4 / OpenCV 4.5.5

2022年4月19日火曜日

【OpenCV】split/mergeによるチャンネルの分離/合成

 画像処理ライブラリOpenCVsplit/mergeによりチャンネルの分離と合成ができる
OpenCVを使うには次のようにインポートが必要。

import cv2

 使用する画像 'tulip.jpg'(幅400ピクセルx高さ267ピクセル)は以下(フリー写真素材ぱくたそより)


'tulip.jpg'





1. splitによるチャンネルの分離

 BGRの3チャンネルのカラー画像をsplitで分離するとB,G,R各チャンネルに分離される。

import cv2

img = cv2.imread('tulip.jpg')
print(img.shape)

b, g, r = cv2.split(img)
print(b.shape)

実行結果

(267, 400, 3)
(267, 400)


 OpencCVの画僧ファイルはnumpy.ndarray形式なので、同じ操作はインデクシングでも可能。splitよりもこちらの方が速度の面で有利とされている。

import cv2

img = cv2.imread('tulip.jpg')
print(img.shape)

b = img[:, :, 0]
g = img[:, :, 1]
r = img[:, :, 2]
print(b.shape)

実行結果

(267, 400, 3)
(267, 400)


2. mergeによるチャンネルの合成

 splitにより分離したB,G,Rチャンネルを、R,B,Gに入れ替えてmergeにより合成する例。mergeの引数は配列なのでタプルかリストになる、つまりカッコが二重になる点に注意が必要。

import cv2

img = cv2.imread('tulip.jpg')
b, g, r = cv2.split(img)
merge = cv2.merge((r, b, g))

cv2.imwrite('merge.jpg', merge)



3. リファレンス

OpenCV > Operations on arrays > split()
OpenCV > Operations on arrays > merge()

使用したバージョン:Python 3.8.12 / OpenCV 4.5.5

2022年4月4日月曜日

【OpenCV】max/minによる比較明(暗)合成

画像処理ライブラリOpenCVmax/minにより2つの画像の比較明/暗合成ができる
OpenCVを使うには次のようにインポートが必要。

import cv2

また合成する画像 'yellow.png'(幅400ピクセルx高さ300ピクセル)、'purple.png'(幅400ピクセルx高さ300ピクセル) は以下

'yellow.png'



'purple.png'





1. 比較明合成/比較暗合成

maxminの書式は以下の通り。src1、src2の各画素値を比較して大きい方(max)/小さい方(min)の画素値からなる新しい画像を生成する。src1、src2は同じサイズでないといけない。比較はチャンネルごと実施される。

dst = cv2.max(src1, src2)
dst = cv2.min(src1, src2)

例の画像をmaxで合成する場合。yellow.pngの画素値は(B, G, R) = (0, 255, 255)、purple.pngの画素値は(B, G, R) = (255, 0, 255)で各チャンネルごとに大きい画素値が採用されるため、生成される画像は(B, G, R) = (255, 255, 255)、つまり白になる。

import cv2

src1 = cv2.imread('purple.png')
src2 = cv2.imread('yellow.png')
dst = cv2.max(src1, src2)

cv2.imwrite('max.png', dst)



例の画像をImageChops.darkerで合成する場合。yellow.pngの画素値は(B, G, R) = (0, 255, 255)、purple.pngの画素値は(B, G, R) = (255, 0, 255)で各チャンネルごとに小さい画素値が採用されるため、生成される画像は(B, G, R) = (0, 0, 255)、つまり赤になる。

import cv2

src1 = cv2.imread('purple.png')
src2 = cv2.imread('yellow.png')
dst = cv2.min(src1, src2)

cv2.imwrite('min.png', dst)


2. リファレンス

OpenCV > Operations on arrays > max()
OpenCV > Operations on arrays > min()

使用したバージョン:Python 3.8.12 / OpenCV 4.5.5

2022年2月8日火曜日

【OpenCV】imwriteによる画像保存

画像処理ライブラリOpenCVで画像をファイルに保存するにはimwriteを使う。
OpenCVを使うには次のようにインポートが必要。

import cv2




1. imwriteの書式

imwriteの書式は以下

cv2.imwrite(filename, img[, params])	
引数 意味
filename パスとファイル名(+拡張子)。 サポートされている拡張子は以下(OpenCV 4.5.5)
-Windows bitmaps - *.bmp, *.dib
-JPEG files - *.jpeg, *.jpg, *.jpe
-JPEG 2000 files - *.jp2
-Portable Network Graphics - *.png
-WebP - *.webp
-Portable image format - *.pbm, *.pgm, *.ppm *.pxm, *.pnm
-PFM files - *.pfm
-Sun rasters - *.sr, *.ras
-TIFF files - *.tiff, *.tif
-OpenEXR Image files - *.exr
-Radiance HDR - *.hdr, *.pic
-Raster and Vector geospatial data supported by GDAL
img 保存する画像
params オプション。Imwrite flagsを指定。
パラメーターID、パラメーター値をセットで指定する。


jpegファイルを読み出して、pngファイルに保存する例。

import cv2

img = cv2.imread('test.jpg')

cv2.imwrite('test.png', img)


2. jpeg保存時のcv2.IMWRITE_JPEG_QUALITY

jpegファイルで保存する際にImwrite flagsとしてcv2.IMWRITE_JPEG_QUALITYと値を指定することで保存時のクオリティ設定ができる。値は0-100の間で設定する(大きいほど高品質)。指定しない場合はデフォルト値の95となる。
下の画像 'promenade.jpg' を保存する(フリー写真素材ぱくたそより)。画像サイズ400x600ピクセルでファイルサイズ239KB。



品質80で保存。ファイルサイズが102KBになる。

import cv2

img = cv2.imread('promenade.jpg')
cv2.imwrite('promenade_80.jpg', img, (cv2.IMWRITE_JPEG_QUALITY, 80))


品質20で保存。ファイルサイズが28.6KBになる。

import cv2

img = cv2.imread('promenade.jpg')
cv2.imwrite('promenade_20.jpg', img, (cv2.IMWRITE_JPEG_QUALITY, 20))




3. リファレンス

OpenCV > Image file reading and writing > imwrite()
OpenCV > Flags used for image file reading and writing > ImwriteFlags

使用したバージョン:Python 3.8.12 / OpenCV 4.5.5

2022年2月7日月曜日

【OpenCV】flipによる画像反転

画像処理ライブラリOpenCVで画像を上下左右に反転する場合flipを使う。
OpenCVを使うには次のようにインポートが必要。

import cv2




1. flipの書式

VideoWriterの書式は以下

cv2.flip(src, flipCode[, dst])
引数 意味
src 反転する画像
flipCode 反転方向を決めるコード
0:上下反転(x軸周りの反転)
0より大きい(1など):左右反転(y軸周りの反転)
0より小さい(-1など):上下左右反転


2. 画像の反転

下の画像 'moon.jpg' を反転する(フリー写真素材ぱくたそより)。



flipCode 0:上下反転(x軸周りの反転)

import cv2

img = cv2.imread('moon.jpg')
flip = cv2.flip(img, 0)

cv2.imwrite('flip0.jpg', flip)


flipCode 1:左右反転(y軸周りの反転)

import cv2

img = cv2.imread('moon.jpg')
flip = cv2.flip(img, 1)

cv2.imwrite('flip1.jpg', flip)


flipCode -1:上下左右反転

import cv2

img = cv2.imread('moon.jpg')
flip = cv2.flip(img, -1)

cv2.imwrite('flip-1.jpg', flip)


3. リファレンス

OpenCV > Operations on arrays > flip()

使用したバージョン:Python 3.8.12 / OpenCV 4.5.5

2022年2月2日水曜日

【OpenCV】VideoWriterによる動画の保存

 画像処理ライブラリOpenCVで動画ファイルを保存する場合、VideoWriter_fourccにより動画コーデックを指定しVideoWriterでVideoWriter型オブジェクトを生成、VideoWriter型オブジェクトに画像を追加し動画として保存する。
OpenCVを使うには次のようにインポートが必要。

import cv2




1. VideoWriterの書式

VideoWriterの書式は以下

cv2.VideoWriter(filename, fourcc, fps, frameSize[, isColor])
引数 意味
filename 保存する動画ファイル名
fourcc FourCC(Four Character Code:フォーシーシー)。動画のコーデックを指定する4文字のコード。'MJPG','mp4v','X264','XVID'等(使用できるコーデックは環境に依存する)。
(*'mp4v')もしくは('m', 'p', '4', 'v')の形式で指定する
fps 動画のフレームレート。フレーム/秒
frameSize 動画のフレームサイズ。(x, y)のピクセル
isColor オプション。0以外の場合カラーフォーマット、0の場合はグレースケールフォーマットとなる。


2. 動画の保存例

 位置とサイズが変わる青い円をコーデックX264、コンテナ(拡張子)mp4で動画保存する場合。VideoWriter_fourccでコーデックのfourccを指定しVideoWriterでVideoWriterオブジェクトを生成、そこに画像を記録する。最後にvideo.release()でVideoWriterオブジェクトを解放する。 フレームレートは25.0フレーム/秒、フレームサイズは640x360を指定。同じサイズの画像を追加して動画化する。

import cv2
import numpy as np

fourcc = cv2.VideoWriter_fourcc(*'X264')  
video  = cv2.VideoWriter('movie.mp4', fourcc, 25.0, (640, 360)) 

for i in range(100):
    img = np.zeros((360, 640, 3), np.uint8)
    cv2.circle(img, (i*6, i*3), i, (255, 0, 0), -1, cv2.LINE_AA)
    video.write(img) 
    
video.release()




同じ動画をコーデックMJPG、コンテナ(拡張子)MOVで保存する場合。

import cv2
import numpy as np

fourcc = cv2.VideoWriter_fourcc(*'MJPG')  
video  = cv2.VideoWriter('movie.MOV', fourcc, 25.0, (640, 360)) 

for i in range(100):
    img = np.zeros((360, 640, 3), np.uint8)
    cv2.circle(img, (i*6, i*3), i, (255, 0, 0), -1, cv2.LINE_AA)
    video.write(img) 
    
video.release()


同じ動画をコーデックmp4v、コンテナ(拡張子)mp4で保存する場合。

import cv2
import numpy as np

fourcc = cv2.VideoWriter_fourcc(*'mp4v')  
video  = cv2.VideoWriter('movie.mp4', fourcc, 25.0, (640, 360)) 

for i in range(100):
    img = np.zeros((360, 640, 3), np.uint8)
    cv2.circle(img, (i*6, i*3), i, (255, 0, 0), -1, cv2.LINE_AA)
    video.write(img) 
    
video.release()


同じ動画をコーデックXVID、コンテナ(拡張子)aviで保存する場合。

import cv2
import numpy as np

fourcc = cv2.VideoWriter_fourcc(*'XVID')  
video  = cv2.VideoWriter('movie.avi', fourcc, 25.0, (640, 360)) 

for i in range(100):
    img = np.zeros((360, 640, 3), np.uint8)
    cv2.circle(img, (i*6, i*3), i, (255, 0, 0), -1, cv2.LINE_AA)
    video.write(img) 
    
video.release()


3. リファレンス

OpenCV > cv::VideoWriter Class Reference > VideoWriter()
OpenCV > cv::VideoWriter Class Reference > fourcc()
Video Codecs by FOURCC

使用したバージョン:Python 3.8.12 / OpenCV 4.5.5

2022年1月26日水曜日

【OpenCV】warpAffineによるアフィン変換

 画像処理ライブラリOpenCVで画像のアフィン変換を行うwarpAffineについて説明する。
アフィン変換は変更前後で並行性を保つ変換で任意の形の平行四辺形から別の形の平行四辺形への変形。


OpenCVを使うには次のようにインポートが必要。
import cv2

例に用いる画像'paper.jpg'(幅600x高さ400ピクセル)は以下を使用(フリー写真素材ぱくたそより)




1. 書式

 cv2.warpAffineの書式は以下の通り。

dst = cv2.warpAffine(src, M, 
        dsize[, dst[, flags[, borderMode[, borderValue]]]])
引数 意味
dst 変換後の画像
src 元画像
M 2x3の変換行列
dsize 変換後の画像サイズ。(幅, 高さ)のタプルで指定
flags interpolation(補完方法)の指定など


2. getAffineTransformを用いた変換行列の生成

変換行列Mを生成するためにはgetAffineTransformを用いる。変換前の座標3点と変換後の座標3点をそれぞれ二次元ndarryで与えることで変換行列が生成される。

例の画像に対して
返還前の座標3点[175, 113], [104, 210], [285, 159]から
返還前の座標3点[100,100], [100,200], [200,100]へ変換する例。

import cv2
import numpy as np

img = cv2.imread('paper.jpg')
rows,cols,ch = img.shape

pts1 = np.float32([[175, 113], [104, 210], [285, 159]])
pts2 = np.float32([[100,100], [100,200], [200,100]])

M = cv2.getAffineTransform(pts1, pts2)

dst = cv2.warpAffine(img, M, (cols, rows))

cv2.imwrite('dst.jpg', dst)

実行結果





変換前、返還後の座標3点をそれぞれの画像に図示すると以下の通り。斜めから見た種類を正面から見た像に変換できる。

変換前



変換後





3. リファレンス

OpenCV > Geometric Image Transformations > warpAffine()
OpenCV > Geometric Image Transformations > getAffineTransform()

使用したバージョン:Python 3.8.8 / OpenCV 4.0.1

2022年1月16日日曜日

【OpenCV】動画ファイルの読み出しとプロパティ取得、キャプチャー画像の保存

画像処理ライブラリOpenCVで動画ファイルを扱う場合、VideoCaptureにより動画ファイルからVideoCapture型オブジェクトを生成する。
OpenCVを使うには次のようにインポートが必要。

import cv2




1. 動画ファイルの読み出しとプロパティ取得

動画ファイルからVideoCapture型オブジェクトを生成する際には以下のようにする。またVideoCapture型オブジェクトの使用後はreleaseにより解放する。

cap = cv2.VideoCapture(filename)

cap.release()


動画ファイルのプロパティを取得するにはVideoCapture型オブジェクトにたいしてgetを使う。書式は以下。

cv2.VideoCapture.get(propId)

propIdには取得したいProperty identifierを指定する。多数あるが代表的なものは以下。

Property identifier 意味
cv2.CAP_PROP_FRAME_WIDTH フレームの幅
cv2.CAP_PROP_FRAME_HEIGHT フレームの高さ
cv2.CAP_PROP_FPS 動画のフレームレート。フレーム/秒
cv2.CAP_PROP_FRAME_COUNT 動画のフレーム数


例に用いる動画 '1203_640x360.mp4' は以下の 動画AC「側転をしてカメラ目線で笑顔でポーズする女性」を使用。





import cv2

# VideoCaptureオブジェクトの生成
cap = cv2.VideoCapture('1203_640x360.mp4')

# getメソッドによるプロパティ取得
# フレームの幅
print(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
# フレームの高さ
print(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# フレームレート
print(cap.get(cv2.CAP_PROP_FPS))
# 総フレーム数
print(cap.get(cv2.CAP_PROP_FRAME_COUNT))

# VideoCaptureオブジェクトのリリース
cap.release()

実行結果。以下のプロパティが表示される。
フレームの幅 : 640ピクセル
フレームの高さ : 360ピクセル
フレームレート : 29.97フレーム/秒
総フレーム数 : 201フレーム

640.0
360.0
29.97002997002997
201.0


2. キャプチャー画像の保存

動画ファイルから指定のフレームまたは指定の経過時間のフレームを画像として保存する場合、VideoCapture型オブジェクトにたいしてsetによりフレームまたは経過時間を指定し、readによりフレームを読み出す。
setの書式は

cv2.VideoCapture.set(propId, value)

propIdはフレーム数を指定する際にはcv2.CAP_PROP_POS_FRAMES、経過時間(msec)を指定する場合はcv2.CAP_PROP_POS_MSECを用いる。valueはフレーム数または時間を指定する。


動画のフレーム100を画像に保存する例。

import cv2

# VideoCaptureオブジェクトの生成
cap = cv2.VideoCapture('1203_640x360.mp4')

# フレーム100に移動
cap.set(cv2.CAP_PROP_POS_FRAMES, 100)

# 画像の取得
ret, frame = cap.read()

# 画像保存
cv2.imwrite('frame100.jpg', frame)

# VideoCaptureオブジェクトのリリース
cap.release()

実行結果





動画の4000msec(4秒)のフレームを画像に保存する例。

import cv2

# VideoCaptureオブジェクトの生成
cap = cv2.VideoCapture('1203_640x360.mp4')

# 4000msec(4秒)に移動
cap.set(cv2.CAP_PROP_POS_MSEC, 4000)

# 画像の取得
ret, frame = cap.read()

# 画像保存
cv2.imwrite('msec4000.jpg', frame)

# VideoCaptureオブジェクトのリリース
cap.release()

実行結果





3. リファレンス

OpenCV > cv::VideoCapture Class Reference > VideoCapture()
OpenCV > cv::VideoCapture Class Reference > release()
OpenCV > cv::VideoCapture Class Reference > set()
OpenCV > cv::VideoCapture Class Reference > get()
OpenCV > Flags for video I/O > VideoCaptureProperties

使用したバージョン:Python 3.8.8 / OpenCV 4.0.1

2022年1月14日金曜日

【OpenCV】画像へカラーマップを適用(applyColorMap)

 カラーマップは色の組み合わせを定義した情報のことで、画像にカラーマップを適用することで画素値に対応した色が割り当てられる。画素値の大小を視覚的にわかりやすくするために用いられる。画像処理ライブラリOpenCVapplyColorMapによりカラー画像またはグレースケール画像へカラーマップを適用できる。
OpenCVを使うには次のようにインポートが必要。

import cv2



1. applyColorMapの書式

 applyColorMap の書式は以下の通り。変換する画像とカラーマップの種類を指定すればよい。

dst = cv2.applyColorMap(src, colormap) 
引数 意味
src 変換する画像。グレースケールまたはカラー画像
colormap カラーマップの種類
カラーマップの名前または番号で指定
Opencv4.0.0では0~12の13種類、4.5.5では0~21まで22種類が使用可能

カラーマップの種類はリファレンスを参照のこと。
OpenCV > ColorMaps in OpenCV



2. カラーマップ適用例

 

以下の画像'test.jpg'にカラーマップ(COLORMAP_JET、COLORMAP_HSV、COLORMAP_HOT)を適用する場合。





import cv2

img = cv2.imread('test.jpg')

# cv2.COLORMAP_JET
dst = cv2.applyColorMap(img, cv2.COLORMAP_JET)
cv2.imwrite('jet.jpg', dst)

# cv2.COLORMAP_HSV
dst = cv2.applyColorMap(img, cv2.COLORMAP_HSV)
cv2.imwrite('hsv.jpg', dst)

# cv2.COLORMAP_HOT
dst = cv2.applyColorMap(img, cv2.COLORMAP_HOT)
cv2.imwrite('hot.jpg', dst)

実行結果

cv2.COLORMAP_JETを適用



cv2.COLORMAP_HSVを適用



cv2.COLORMAP_HOTを適用





 colormapを番号で指定しても同じ結果が得られる。

import cv2

img = cv2.imread('test.jpg')

# cv2.COLORMAP_JET
dst = cv2.applyColorMap(img, 2)
cv2.imwrite('jet.jpg', dst)

# cv2.COLORMAP_HSV
dst = cv2.applyColorMap(img, 9)
cv2.imwrite('hsv.jpg', dst)

# cv2.COLORMAP_HOT
dst = cv2.applyColorMap(img, 11)
cv2.imwrite('hot.jpg', dst)


3. リファレンス

OpenCV > ColorMaps in OpenCV

使用したバージョン:Python 3.8.8 / OpenCV 4.0.1

2022年1月4日火曜日

【OpenCV】画像のヒストグラム算出とヒストグラム比較(calcHist, compareHist)

 画像処理ライブラリOpenCVcalcHistにより画像の画素値分布を示すヒストグラムを計算できる。またcompareHistにより2つの画像ヒストグラムを比較できる。


OpenCVを使うには次のようにインポートが必要。
import cv2


1. calcHistによるヒストグラム算出

 calcHist の書式は以下の通り。

cv.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]]	) 
引数 意味
images ヒストグラムを計算する画像
channels ヒストグラムを計算するチャンネルのインデックス指定。グレースケール画像の場合は[0]、カラー画像の場合は[0],[1],[2](B,G,R)のいずれかを指定
mask 特定の領域のみヒストグラムを算出する場合のマスク画像の指定。指定しない場合はnoneとする
histSize ヒストグラムのビン(階級)の数。全画素値を指定する場合は[256]とする
ranges ヒストグラムを算出する画素値の範囲。通常は[0,256]を指定


以下の画像'miyako.jpg'(フリー写真素材ぱくたそより)についてヒストグラムを計算する。画像サイズは幅600高さ400ピクセル。





import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('miyako.jpg')
color = ('b','g','r')
for i, col in enumerate(color):
    histr = cv2.calcHist([img], [i], None, [256], [0,256])
    plt.plot(histr,color = col)
    plt.xlim([0,256])
plt.show()

実行結果





2. マスク画像による特定個所のヒストグラム算出

 画像の特定領域のヒストグラムを算出する場合は、ヒストグラムを計算したい領域を白、計算から除きたい領域を黒にしたマスク画像を用意しcalcHistに与える。マスク画像のサイズは計算する画像と同じにする。

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('miyako.jpg')

mask = np.zeros(img.shape[:2], np.uint8)
mask[250:350, 50:550] = 255
cv2.imwrite('mask.jpg', mask)

color = ('b','g','r')
for i, col in enumerate(color):
    histr = cv2.calcHist([img], [i], mask, [256], [0,256])
    plt.plot(histr,color = col)
    plt.xlim([0,256])
plt.show()

実行結果



マスク画像





3. compareHistによるヒストグラム比較

 compareHistにより2つのヒストグラムの類似度を算出できる。ヒストグラム類似度は各階級の度数の差を積算することで求められる。算出アルゴリズムは複数ありいずれかを指定する。

compareHist の書式は以下の通り。

cv.compareHist(H1, H2, method) 
引数 意味
H1, H2 比較するヒストグラム
method/td> ヒストグラム算出アルゴリズムの指定
HISTCMP_CORREL
HISTCMP_CHISQR
HISTCMP_INTERSECT
HISTCMP_BHATTACHARYYA
HISTCMP_HELLINGER
HISTCMP_CHISQR_ALT
HISTCMP_KL_DIV


'miyako.jpg'と'sunflower.jpg'(フリー写真素材ぱくたそより)についてチャンネル0(B)のヒストグラムを比較する例。









import cv2
import matplotlib.pyplot as plt

img1 = cv2.imread('miyako.jpg')
img2 = cv2.imread('sunflower.jpg')

hist1 = cv2.calcHist([img1], [0], None, [256], [0,256])
plt.plot(hist1, color = 'b') 
plt.show()

hist2 = cv2.calcHist([img2], [0], None, [256], [0,256])
plt.plot(hist2, color = 'b')
plt.show()

print(cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL))

実行結果

0.2950604095552982








4. リファレンス

OpenCV > Histograms > calcHist()
OpenCV > OpenCV Tutorials > Histogram Calculation
OpenCV > Histograms > compareHist()
OpenCV > OpenCV Tutorials > Histogram Comparison
OpenCV > Histograms > HistCompMethods

使用したバージョン:Python 3.8.8 / OpenCV 4.0.1

2021年12月20日月曜日

【OpenCV】画像のモルフォロジー変換(erode, dilate, morphologyEx)

 二値化画像に対して膨張・収縮などの処理を行う(モルフォロジー変換)。画像処理ライブラリOpenCVerodeにより収縮、dilateにより膨張、morphologyExによりオープニングやクロージングの処理ができる。


OpenCVを使うには次のようにインポートが必要。
import cv2


1. erode(収縮処理)

 erodeには処理する二値化画像およびカーネルサイズを引数として与え、目的の画素を囲むカーネルサイズ内の画素が全て1(白)であれば目的の画素を1、1つでも0(黒)があれば0とする。これにより背景が黒、前景が白で描かれている画像では前景の周囲が削れら収縮される。
次の画像'text.png'を(5x5)のカーネルで処理する場合。

text.png





import cv2
import numpy as np

img = cv2.imread('text.png', 0)
kernel = np.ones((5, 5), np.uint8)
erosion = cv2.erode(img, kernel, iterations = 1)

cv2.imwrite('erosion.png', erosion)

実行結果





2. dilate(膨張処理)

 dilateerodeと逆に、目的の画素を囲むカーネルサイズ内の画素が全て0(黒)であれば目的の画素を0、1つでも1(白)があれば1とする。これにより背景が黒、前景が白で描かれている画像では前景の周囲が追加され膨張する。
'text.png'を(5x5)のカーネルで処理する場合。

import cv2
import numpy as np

img = cv2.imread('text.png', 0)
kernel = np.ones((5, 5), np.uint8)
dilation = cv2.dilate(img, kernel, iterations = 1)

cv2.imwrite('dilation.png', dilation)

実行結果





3. opening(オープニング処理)

 openingは収縮、膨張処理を順に行う。背景(黒)と前景(白)からなる画像に白いノイズが乗っている場合に、初めの収縮処理によりノイズが消去され、続く膨張処理で収縮処理で小さくなった前景が膨張して元通りのサイズとなる。これによりノイズ除去が可能。オープニング処理を行うにはmorphologyExを用い、その引数に処理する画像とカーネルの他、cv2.MORPH_OPENを与える。
次の画像'text_noise_white.png'を(5x5)のカーネルで処理する場合。

'text_noise_white.png'





import cv2
import numpy as np

img = cv2.imread('text_noise_white.png', 0)
kernel = np.ones((5, 5), np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)

cv2.imwrite('opening.png', opening)

実行結果





4. closing(クロージング処理)

 closingは膨張、収縮処理を順に行う。背景(黒)と前景(白)からなる画像に黒いノイズが乗っている場合に、初めの膨張処理により前景に乗った黒いノイズが消去され、続く収縮処理で膨張処理で大きくなった前景が収縮して元通りのサイズとなる。これによりノイズ除去が可能。クロージング処理を行うにはmorphologyExを用い、その引数に処理する画像とカーネルの他、cv2.MORPH_CLOSEを与える。
次の画像'text_noise_black.png'を(5x5)のカーネルで処理する場合。



import cv2
import numpy as np

img = cv2.imread('text_noise_black.png', 0)
kernel = np.ones((5, 5), np.uint8)
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

実行結果





5. リファレンス

OpenCV > Image Filtering > erode()
OpenCV > Image Filtering > dilate()
OpenCV > Image Filtering > morphologyEx()

使用したバージョン:Python 3.8.8 / OpenCV 4.0.1