ETロボコンでopenCVを利用する機会が出そうだったので、画像処理について学習した事をここにまとめておきます
(実際にETロボコンで使用する際はC++でコードを書くことになりそうですが・・・)
あと書いていたらかなり多くなってしまったので2つに分けようかと思っています
画像処理とは
画像→画素の集まり(RGB値)
画像処理→画像を解析しやすくする、情報を抽出しやすくする
-
画像処理の例
- グレースケール化
- 平滑化→画像を滑らかにする
- Canny エッジ(輪郭)の検出
- グレースケール化
OpenCVとは
open source(一部特許があるものもある。)
マルチプラットフォーム、C++, Python, java, matlab
機能としては画像、動画の読み込みや表示を行ったりもできる
カメラモデル、機械学習用のライブラリもある
画像の座標は基本的に左上に原点。下へy軸、右へx軸をとる
-
pythonでは、numpy array にy、x、colorの順に格納される(openCV独自の配列の設定)
- colorというのは、RGB値(もしくはHSV値)を並べた16bitの値のことを言う
-
C++の方が速いが、コードが長くなる。Pythonの方がコードが短くかけるが、書き方次第でC++よりは遅い。ほかのライブラリとの連携は強い
- ただし、Python+openCVは情報が少ない
色空間とグレースケール
RGB
R(red),G(green),B(blue)それぞれの値で一つの座標を決めることで色を決定する。値の範囲はそれぞれ0~255
openCVでは、RGB値は(B,G,R)の順番で数値を並べる
HSV
-
H:色相
- 値の範囲は0~359。角度によって色の種類を表す
-
S:彩度
- 値の範囲は0~100。Hで決められた色がどのくらい含まれているか。0に行くほど白に近い
-
V:明度
- 値の範囲は0~100。色の明るさを表す。0は黒を示す。100は明るく白に近づく
-
HSVのメリットは色が表しやすい
- openCVでは各値を以下の範囲で表現する
- H 0~179 (0-359を2で割った値と考える)
- S 0~255
- V 0~255
グレースケール
-
演算量を抑えるためによく使われる。2値化にも長けている。RGB値を以下の式でグレースケールに変換できる
- Gray = 0.2989 R + 0.5870 G + 0.1140 B
RGB, HSVと違い一つのパラメータのみで演算が可能なので、演算にも相性が良い
画像処理のライブラリ
基本的に使用頻度の高そうなものから説明。以下のimport文は省略してあるので、使用する際はこの import文を使用すること
import cv2
基本的な画像の読み出し関連全般
画像を読み出す際の、RGB,HSV,グレースケールでの読み出し方を以下に示す
# 画像をRGB表現で読み出し
img = cv2.imread("sample.jpg") # 「sample.jpg」はファイルパス
# 画像を読み出し、HSV表現にコンバート
img = cv2.imread("sample.jpg") # 「sample.jpg」はファイルパス
img_hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV ) # RGBからHSVへ変換
# 画像をグレースケールで読み出し
img = cv2.imread("sample.jpg",0) # 「sample.jpg」はファイルパス
# 画像の大きさ(おまけ)
img.shape # 画像のデータ概要(y,x,color)が入っている
基本的な画像の書き出し関連全般
同ディレクトリにグレースケール化した画像を書き出すサンプルを以下に示す。
img = cv2.imread("sample.jpg",0) # 「sample.jpg」はファイルパス
# 「sample.jpg」をグレースケール化した「sample_gray.jpg」を作成
cv2.imwrite("sample_gray.jpg",img)
画像のリサイズ
img = cv2.imread("sample.jpg") # 「sample.jpg」はファイルパス
size = (300,200) # (幅、高さ)
img_resize = cv2.resize(img, size) # sizeの大きさでリサイズ
画像の2値化
画像の2値化とは、画像を白と黒だけで表現する事を意味する。この2値化を行う際、白か黒かを判断する閾値が必要になる。その閾値をユーザが設定する場合としない場合があるので、その2つに分けて説明する。
閾値をユーザが設定する場合
img = cv2.imread("sample.jpg") # 「sample.jpg」はファイルパス
threshold = 100 # 閾値。閾値以上の値は255にする
ret,img_th = cv2.threshold(img, threshold,255, cv2.THRESH_BINARY)
閾値をユーザが設定しない場合
閾値をユーザが設定しない場合はいくつかパターンがあるので別に説明します。
大津の2値化
分離度が最も大きくなるときの閾値を求める。ヒストグラムも関わってくるので説明は割愛。
こちらを参考のこと→https://algorithm.joho.info/image-processing/otsu-thresholding/
img = cv2.imread("sample.jpg") # 「sample.jpg」はファイルパス
ret2,img_o = cv2.threshold(img,0,255,cv2.THRESH_OTSU) # ret2に閾値が入る
適応的二値化処理
- ある一定範囲内でそれぞれ閾値を設定する。よって相対的に明るいものは白と判断される。以下の場合は周囲3近傍で閾値を決定
img = cv2.imread("sample.jpg") # 「sample.jpg」はファイルパス
img_ada = cv2.adaptiveThreshold(img,
255,cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 3, 1)