Python+OpenCVを用いて画像ファイルの読み書き、表示、色変換、部分処理をする方法をソースコード付きで解説します。
画像の読み込み(cv2.imread)
Python版のOpenCVでは、cv2.imreadメソッドで画像を読み込むことができます。
書式
img = cv2.imread(filename[,flag])
パラメータ | 説明 |
---|---|
filename | 読み込む画像のファイルパス |
flag | cv2.IMREAD_COLOR : RGBカラー画像として読み込む(画像の透明度は無視)。デフォルト値。単に1と指定しても同じ。 cv2.IMREAD_GRAYSCALE : グレースケール画像として読み込む。単に0と指定しても同じ。 cv2.IMREAD_UNCHANGED :透明度(アルファチャンネル)も含めたRGBA画像として読み込む。単に-1と指定しても同じ。 |
img | NumPy配列(読み込んだ画像の画素値を格納) |
読み込みに対応している画像ファイル形式は、「jpg」「png」「bmp」「pgm」「pbm」「ppn」「dib」「jp2」「tiff」「tf」「ras」「sr」です。
読み込んだ画像の画素値はNumPy配列に格納されます。
そのため、通常のNumPy配列と同様に、print関数で中身を確認できます。
ソースコード
サンプルプログラムのソースコードです。
■入力画像(3×3)
rgbとrgbaは3次元配列、grayは2次元配列になります。
それぞれの各要素は各画素の画素値を表しています。
種類 | 説明 |
---|---|
rgb | 最初の要素[ 36 28 237]は、座標(0,0)の画素値です。Windowsの場合、36はBlue、28はGreen、237はRedの濃度です。[ 76 177 34]は、座標(1, 0)の画素値です。 |
gray | 最初の要素91は座標(0,0)の画素値です。122は、座標(1, 0)の画素値です。 |
rgba | 最初の要素[36 28 237 255]は座標(0,0)の画素値です。Windowsの場合、36はBlue、28はGreen、237はRedの濃度、255は透明度です。[ 76 177 34 255]は、座標(1, 0)の画素値です。 |
画像の書き込み(cv2.imwrite)
Python版OpenCVでは、「cv2.imwrite」で画像を出力(書き込み)できます。
cv2.imwrite(filename, img)
パラメータ | 説明 |
---|---|
filename | 書き込み画像のファイル名 |
img | 画像オブジェクト(NumPy配列) |
ソースコード
サンプルプログラムのソースコードです。
#-*- coding:utf-8 -*- import cv2 import numpy as np # 画像の読み込み(RGB) img = cv2.imread("/Users/github/sample/python/opencv/basic/input.png") # 画像の読み込み(グレースケール) gray = cv2.imread("/Users/github/sample/python/opencv/basic/input.png", 0) # 画像の読み込み(RGBA) rgba = cv2.imread("/Users/github/sample/python/opencv/basic/input.png", -1) # 画素値の表示 print("rgb=", img) print("\n------------------------\n") print("gray=", gray) print("\n------------------------\n") print("rgba=", rgba) ''' rgb= [[[ 36 28 237] [ 76 177 34] [204 72 63]] [[ 0 0 0] [255 255 255] [195 195 195]] [[164 73 163] [ 36 28 237] [ 0 0 0]]] ------------------------ gray= [[138 142 98] [ 0 255 195] [120 138 0]] ------------------------ rgba= [[[ 36 28 237 255] [ 76 177 34 255] [204 72 63 255]] [[ 0 0 0 255] [255 255 255 255] [195 195 195 255]] [[164 73 163 255] [ 36 28 237 255] [ 0 0 0 255]]] '''
画像の表示(cv2.imshow)
Python版OpenCVでは「cv2.imshow」で読み込んだ画像ファイルをウィンドウに表示できます。
# -*- coding: utf-8 -*- import cv2 # 入力画像のロード img = cv2.imread('input.png') cv2.imshow("input", img) cv2.waitKey(0) cv2.destroyAllWindows()
画像の高さ・幅・チャンネル数・画素数を取得
Python版OpenCVでは、「cv2.imread」を用いて読み込んだ画像データはNumPy配列に変換されます。
そのため、NumPy配列のshape属性を利用することで画像の高さ・幅・チャンネル数・画素数を調べることができます。
動画版説明
ソースコード
サンプルプログラムのソースコードです。
#-*- coding:utf-8 -*- import cv2 import numpy as np # 画像の読み込み(RGB) img = cv2.imread("a.jpg") height, width, ch = img.shape # 画素数 = 幅 * 高さ size = width * height # 情報表示 print("幅:", width) print("高さ:", height) print("チャンネル数:", ch) print("画素数:", size) print("データ型:", img.dtype) # 1chずつ表示 print("Bの画素値:\n", img[:,:,0]) print("Gの画素値:\n", img[:,:,1]) print("Rの画素値:\n", img[:,:,2])
サンプルプログラムの実行結果です。
■入力画像(3×3)
■標準出力
幅: 3 高さ: 3 チャンネル数: 3 画素数: 9 データ型: uint8 Bの画素値: [[ 35 43 221] [ 0 255 209] [200 0 0]] Gの画素値: [[ 12 198 43] [ 0 255 225] [ 87 0 0]] Rの画素値: [[255 0 50] [ 0 255 226] [174 255 0]]
エラーが出た場合
以下のようなエラーが表示された場合、指定した画像ファイルが見つからなかったため空の配列を処理しようとしてエラーを出しています。
この場合、「cv2.imread(“C:/Users/Downloads/input.jpg”)」という風に絶対パスで画像ファイルのパスを指定してみてください。
cv2.error: OpenCV(4.5.3) C:\Users\runneradmin\AppData\Local\Temp\pip-req-build-sn_xpupm\opencv\modules\imgproc\src\color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cv::cvtColor'
グレースケール変換(cv2.cvtColor)
グレースケール変換とは、次のようにカラー画像をモノクロ調のグレースケール画像に変換する処理です。
OpenCVでは、cv2.cvtColorメソッドでRGBの画像をグレースケール変換できます。
動画解説
ソースコード
#-*- coding:utf-8 -*- import cv2 # 入力画像の読み込み img = cv2.imread("C:\prog\python\input.png") # グレースケール変換 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # グレースケール画像の書き込み cv2.imwrite("C:\prog\python\gray.png", gray) # BGR, B, G, R, Grayの2次元配列を確認 print("BGR=", img) print("-------------") print("Blue=", img[:,:,0]) print("-------------") print("Green=", img[:,:,1]) print("-------------") print("Red=", img[:,:,2]) print("-------------") print("gray=", gray)
HSV色空間に変換(cv2.cvtColor)
HSV色空間とは、「色相(Hue)」「彩度(Saturation)」「明度(Value)」の3つの組み合わせで色を表現する手法です。
HSV色空間は人間が色を知覚する方法と類似しているため、RGB色空間よりも人がイメージした通りの色を作りやすいという特徴があります。
この特徴から、画像処理でも色検出をおこなう場合などにHSV色空間が利用されています。
動画解説
本ページの内容は動画でも解説しています。
OpenCVライブラリでは、cv2.cvtColorメソッドでRGBからHSVに変換できます。
ソースコード
#-*- coding:utf-8 -*- import cv2 import numpy as np # 入力画像の読み込み img = cv2.imread("C:\prog\python\\test\input.jpg") # 方法2(OpenCVで実装) hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 結果を出力 cv2.imwrite("C:\prog\python\\test\hsv.jpg", hsv)
実行結果
■左から入力画像(input.jpg)、出力画像(hsv2.jpg)
お借りした画像:プロ生ちゃん(暮井 慧)
赤、緑、青色の物体を検出
HSV色空間における、赤色、緑色、青色のHue値のおおよその範囲は以下のとおりです。
– | 値の範囲 | 値の範囲(OpenCVの場合) |
---|---|---|
赤色のHue | 0~60, 300~360[度] | 0~30, 150~179 |
緑色のHue | 60~189[度] | 30~90 |
青色のHue | 180~300[度] | 90~150 |
SとVは対象に応じて適宜調整しますが、今回は以下の値域で赤、緑、青を検出します、
— | 値の範囲 | 値の範囲(OpenCVの場合) |
---|---|---|
S | 25~100[%] | 64~255 |
V | 00~100[%] | 0~255 |
Sは彩度(色の鮮やかさ)を示す値・・・下限をさげるほど薄い色も検出します。
Sは明るさを示す値
OpenCVのcv2.inRangeメソッドを使うことで、指定したH、S、V値の範囲でマスクを取ることができます。
#-*- coding:utf-8 -*- import cv2 import numpy as np # 赤色の検出 def detect_red_color(img): # HSV色空間に変換 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 赤色のHSVの値域1 hsv_min = np.array([0,64,0]) hsv_max = np.array([30,255,255]) mask1 = cv2.inRange(hsv, hsv_min, hsv_max) # 赤色のHSVの値域2 hsv_min = np.array([150,64,0]) hsv_max = np.array([179,255,255]) mask2 = cv2.inRange(hsv, hsv_min, hsv_max) # 赤色領域のマスク(255:赤色、0:赤色以外) mask = mask1 + mask2 # マスキング処理 masked_img = cv2.bitwise_and(img, img, mask=mask) return mask, masked_img # 緑色の検出 def detect_green_color(img): # HSV色空間に変換 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 緑色のHSVの値域1 hsv_min = np.array([30, 64, 0]) hsv_max = np.array([90,255,255]) # 緑色領域のマスク(255:赤色、0:赤色以外) mask = cv2.inRange(hsv, hsv_min, hsv_max) # マスキング処理 masked_img = cv2.bitwise_and(img, img, mask=mask) return mask, masked_img # 青色の検出 def detect_blue_color(img): # HSV色空間に変換 hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # 青色のHSVの値域1 hsv_min = np.array([90, 64, 0]) hsv_max = np.array([150,255,255]) # 青色領域のマスク(255:赤色、0:赤色以外) mask = cv2.inRange(hsv, hsv_min, hsv_max) # マスキング処理 masked_img = cv2.bitwise_and(img, img, mask=mask) return mask, masked_img # 入力画像の読み込み img = cv2.imread("C:\prog\python\\test\input.png") # 色検出(赤、緑、青) red_mask, red_masked_img = detect_red_color(img) green_mask, green_masked_img = detect_green_color(img) blue_mask, blue_masked_img = detect_blue_color(img) # 結果を出力 cv2.imwrite("C:\prog\python\\test\\red_mask.png", red_mask) cv2.imwrite("C:\prog\python\\test\\red_masked_img.png", red_masked_img) cv2.imwrite("C:\prog\python\\test\green_mask.png", green_mask) cv2.imwrite("C:\prog\python\\test\green_masked_img.png", green_masked_img) cv2.imwrite("C:\prog\python\\test\\blue_mask.png", blue_mask) cv2.imwrite("C:\prog\python\\test\\blue_masked_img.png", blue_masked_img)
実行結果
サンプルプログラムの実行結果です。
■入力画像(input.png)
■赤色の検出結果
左がマスク画像(red_mask.png)、右がマスキング処理した画像(red_masked_img.png)
■緑色の検出結果
左がマスク画像(green_mask.png)、右がマスキング処理した画像(green_masked_img.png)
■青色の検出結果
左がマスク画像(blue_mask.png)、右がマスキング処理した画像(blue_masked_img.png)
【OpenCV】窓画像の作成(切り取り)
ROI(Region of Interest)とは、画像データのうち、操作の対象として選ぶ領域のことです。
「対象領域」「注目領域」「関心領域」「窓画像」などといいます。
Pythonでは、NumPyのスライスを使うことで、OpenCVで読み込んだ画像の一部分を切り取って窓画像を作成できます。
実行例
■入力画像(左)、出力画像(右)
動画解説
ソースコード
#-*- coding:utf-8 -*- import cv2 import numpy as np # 入力画像とテンプレート画像をで取得 img = cv2.imread("C:\prog\python\input.png") # 窓画像の左上座標 x, y = 50, 100 # 窓画像の幅・高さ w, h = 40, 40 # 入力画像から窓画像を切り取り roi = img[y:y+h, x:x+w] # 窓画像の保存 cv2.imwrite("C:\prog\python\output.png", roi)
【OpenCV】部分処理
Pythonでは、NumPyのスライスを使うことで、OpenCVで読み込んだ画像の一部分だけに処理を施します。
実行例
■入力画像(左)、出力画像(右)
※画像の一部分を黒塗り
ソースコード
#-*- coding:utf-8 -*- import cv2 import numpy as np # 入力画像とテンプレート画像をで取得 img = cv2.imread("C:\prog\python\input.png") # 窓画像の左上座標 x, y = 50, 100 # 窓画像の幅・高さ w, h = 40, 40 # 窓画像を黒塗り(画素値を0に) img[y:y+h, x:x+w] = 0 # 画像の書き込み cv2.imwrite("C:\prog\python\output.png", img)
【OpenCV】画像の圧縮(encode、decode)
Python版OpenCVの「cv2.imencode」で画像の圧縮(エンコード)ができます。
復元(デコード)は、「cv2.imdecode」です。
# -*- coding: utf-8 -*- import cv2 import numpy as np # 入力画像の読み込み img = cv2.imread("input.jpg") # 画像の圧縮(画質は80%) result, encimg = cv2.imencode("img2.jpg", img, [int(cv2.IMWRITE_JPEG_QUALITY), 80]) # 圧縮画像の保存 cv2.imwrite("output.jpg", img)
コメント