旅行好きなソフトエンジニアの備忘録

プログラミングや技術関連のメモを始めました

【OpenCV】 照明ムラがある環境での二値化

照明ムラがある環境下で二値化を行い対象物を抽出しようとする場合、普通に二値化処理を行うと大抵上手く抽出できません。
下の画像はその例で、画像上部が明るめ、画像下部が暗めのになっています。この画像から米粒を抜き出そうとして大津の方法を適用すると、照明ムラの影響を受けて上手く抽出できていないことが分かります。
f:id:ni4muraano:20170520213509p:plain:w200    f:id:ni4muraano:20170520213534j:plain:w200
このような時の対処法の例がMathWorksのホームページに掲載されており、今回はOpenCVで実装します。

jp.mathworks.com

// 画像をグレースケールで読み込む
Mat gray;
imread("non_uniform_illumination_example.png", IMREAD_GRAYSCALE).copyTo(gray);
if (gray.empty())
{
    throw runtime_error("Failed to open image");
}

// オープニングを実行して背景を取り出す
Mat element = getStructuringElement(MORPH_ELLIPSE, cv::Size(15, 15));
Mat background;
morphologyEx(gray, background, CV_MOP_OPEN, element);

// 前景を取得する
Mat foreground;
absdiff(gray, background, foreground);

// 二値化して米粒を抽出する
Mat binary;
threshold(foreground, binary, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);

f:id:ni4muraano:20170520213509p:plain
元画像

f:id:ni4muraano:20170520214658j:plain
背景

f:id:ni4muraano:20170520214708j:plain
前景

f:id:ni4muraano:20170520214715j:plain
米粒