粒をカウントする (粒子解析)

OpenCVは2値画像では白をモノとして認識する

種子は黒色でした。そのため、2値化しても黒くなっています。OpenCVに限らずほとんどの画像処理ライブラリは2値画像においては白をモノとして認識します。このような理由から、後々の処理の際に便利になるので、色を反転し、種子を白にしてしまいます。色の反転は簡単です。チルダ「~」をMat型の前につけると反転した画像になります。下の例のようにします。

Mat img = imread("sample.png", IMREAD_UNCHANGED);
img = ~img; //反転したimgをimgに入れる

収縮処理

種子の画像を2値化した画像を拡大したのが下の1つ目の画像です。2つ目の画像はさらに色反転を行ったものです。このまま輪郭を検出して種子を認識をすると、くっついた種子が2個分に正しくカウントされません。よって、くっついた種子を切り離す処理、すなわち、白い部分を縮ませる処理を行います。これはerode関数により実装されています。今回の動画では4回、この収縮処理を行うことで、くっついた種子をバラバラにしています(3つ目)。ただし、収縮処理をした後の画像から面積などを求めるのは不適当であるということには注意してください。文字通り、面積は小さくなっています。

seed4-3
#include "opencv/cv.h"
#include "opencv/highgui.h"
using namespace cv;
int main(){
    Mat img = imread("seed.jpg", IMREAD_UNCHANGED);
    Mat gray_img;
    cvtColor(img, gray_img, CV_BGR2GRAY);
    Mat bin_img;
    adaptiveThreshold(gray_img, bin_img, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 99, 8);
    //変更ここから
    bin_img = ~bin_img; //色の反転
    Mat element = Mat::ones(5,5,CV_8UC1); //5×5の行列で要素はすべて1 erode処理に必要な行列
    //以下4行は同じことを4回繰り返しています
    erode(bin_img, bin_img, element, Point(-1,-1), 1); //収縮処理
    erode(bin_img, bin_img, element, Point(-1,-1), 1); //収縮処理
    erode(bin_img, bin_img, element, Point(-1,-1), 1); //収縮処理
    erode(bin_img, bin_img, element, Point(-1,-1), 1); //収縮処理
    //変更ここまで
    imshow("IMAGE",bin_img);
    waitKey(10000);
    return 0;
}