OpenCV_色抽出とマスキング

マスキング:
描画など作業したくない領域を指定し、保護すること。
包み隠す、覆い隠す。画像処理では隠したい領域は黒、抽出したい領域は白。

 

色抽出

下記画像から赤 (255, 0, 0) を抽出する。

f:id:koshinRan:20170927111711p:plain


写真などから赤を抽出する際は、薄~濃と赤の色にも範囲があるので、
HSV に画像を変換し、lower、upper もHSV で指定する必要あり。
ex) では 赤は一種類のみなので RGB のまま行った。

ex)

    cv::Mat colorImg = cv::imread("./000color.png");

    cv::Mat redOnlyImg = cv::Mat::zeros(colorImg.rows, colorImg.cols, CV_8UC1);
    // cv::Mat redOnlyImg; でも OK
    auto lower = cv::Scalar(0, 0, 254);
    auto upper = cv::Scalar(0, 0, 255);

    cv::inRange(colorImg, lower, upper, redOnlyImg);
    cv::imshow("getRed", redOnlyImg);

redOnlyImg の画像。
f:id:koshinRan:20170927233244p:plain

 

jpg 画像は NG 。輪郭がきれいにならない。( クリックで拡大 )
f:id:koshinRan:20170927235836p:plain

 

HSV で行う場合は、

    cv::cvtColor(colorImg, colorImg, CV_BGR2HSV, 3);
    auto lower = cv::Scalar(0, 255, 254);
    auto upper = cv::Scalar(1, 255, 255);

cv::cvtColor の最後の引数はチャンネル数。

 

・cv::inRange の cv::Scalar において、
    下限も上限も設定した値は範囲に含む
    古いバージョンだと下限はその値を含むが上限は含まない。

・cv::Mat::zeros は、行列要素を 0 で埋めて初期化
・cv::Mat::ones は、行列要素を 1 で埋めて初期化

 

マスキング

 上記で赤 (255, 0, 0) で抽出した範囲外をマスク。

以下のコードを追加する。

    cv::Mat maskImg;
    colorImg.copyTo(maskImg, redOnlyImg);
    cv::imshow("mask", maskImg);

このように表示される。

f:id:koshinRan:20170927233329p:plain

 

 

抽出とマスクのまとめソース

上のソースをまとめただけ。

    cv::Mat colorImg = cv::imread("./000color.png");
    cv::Mat redOnlyImg = cv::Mat::zeros(colorImg.rows, colorImg.cols, CV_8UC1);
   
    auto lower = cv::Scalar(0, 0, 254);
    auto upper = cv::Scalar(0, 0, 255);
   
    cv::inRange(colorImg, lower, upper, redOnlyImg);
   
    cv::Mat maskImg;
    colorImg.copyTo(maskImg, redOnlyImg);
   
    cv::imshow("mask", maskImg);

 

 

 遊び

 

    cv::Mat img = cv::imread("./001img.jpg");
    cv::Mat maskImg;
    img.copyTo(maskImg, redOnlyImg);
    cv::imshow("mask", maskImg);

f:id:koshinRan:20170927233435p:plain

 

    colorImg.copyTo(img, redOnlyImg);
    cv::imshow("mask", img);

f:id:koshinRan:20170927233529p:plain

 

 

こちらから。
http://d.hatena.ne.jp/Kazzz/20130218/p1
http://tansu2android.blogspot.jp/2014/01/android-opencv_17.html
http://lang.sist.chukyo-u.ac.jp/classes/OpenCV/py_tutorials/py_imgproc/py_colorspaces/py_colorspaces.html#converting-colorspaces
http://www.cellstat.net/mask/
http://opencv.jp/opencv-2.1/cpp/miscellaneous_image_transformations.html#cv-cvtcolor
http://opencv.jp/opencv-2svn/py/core_operations_on_arrays.html#inrange
http://d.hatena.ne.jp/Kazzz/20130118/p1
http://opencv.jp/cookbook/opencv_mat.html
https://dictionary.goo.ne.jp/jn/208105/meaning/m0u/
http://www.cellstat.net/bitwise/

 

以上。

--Memo1--
    cv::bitwise_and(src1, src2, dst);
img1(黒白) と img2(黒白) のインターセクトを求める時
( 重なり箇所をマスクする時 ) に役に立った関数。
だが論理演算とか意味不。


--Memo2--
取得したい色の範囲が不明ならば、
地道にサンプルのみを手作業で切り取ってそれらの色を出力し、
最大最小を決める。
1)サンプルのみ切り取り、
2)背景が黒などサンプルにない色の画像に貼り付け、
3)ソースで背景色以外の画素値を出力、
4)出力した値をExcel などに貼り付け、
5)最大最小を決定。