8

背景シーンの画像と、前にオブジェクトがある同じシーンの画像があります。次に、背景を差し引いたフォアグラウンドのオブジェクトのマスクを作成します。どちらの画像もRGBです。

私はすでに次のコードを作成しました:

cv::Mat diff;
diff.create(orgImage.dims, orgImage.size, CV_8UC3);
diff = abs(orgImage-refImage);

cv::Mat mask(diff.rows, diff.cols, CV_8U, cv::Scalar(0,0,0));
//mask = (diff > 10);

for (int j=0; j<diff.rows; j++) {
    // get the address of row j
    //uchar* dataIn= diff.ptr<uchar>(j);
    //uchar* dataOut= mask.ptr<uchar>(j);
    for (int i=0; i<diff.cols; i++) {
        if(diff.at<cv::Vec3b>(j,i)[0] > 30 || diff.at<cv::Vec3b>(j,i)[1] > 30 || diff.at<cv::Vec3b>(j,i)[2] > 30)
            mask.at<uchar>(j,i) = 255;
    }
}

私はこれを正しくやっているかどうかわかりませんか?

4

2 に答える 2

9

OpenCV のinRange関数を見てください。これにより、3 チャンネルの画像に対して複数のしきい値を同時に設定できます。

したがって、探していたマスクを作成するには、次の手順を実行します。

inRange(diff, Scalar(30, 30, 30), Scalar(255, 255, 255), mask);

これは、各ピクセルに自分でアクセスしようとするよりも高速です。

編集:皮膚検出があなたがしようとしているものである場合、最初に皮膚検出を行い、その後、背景減算を行って背景を削除します。それ以外の場合、皮膚検出器は、減算によって引き起こされる強度シフトを考慮に入れる必要があります。

皮膚検出の優れたテクニックについて、私の他の回答を確認してください。

編集 :

これはもっと速いですか?

int main(int argc, char* argv[])
{
    Mat fg = imread("fg.jpg");
    Mat bg = imread("bg.jpg");

    cvtColor(fg, fg, CV_RGB2YCrCb);
    cvtColor(bg, bg, CV_RGB2YCrCb);

    Mat distance = Mat::zeros(fg.size(), CV_32F);

    vector<Mat> fgChannels;
    split(fg, fgChannels);

    vector<Mat> bgChannels;
    split(bg, bgChannels);

    for(size_t i = 0; i < fgChannels.size(); i++)
    {
        Mat temp = abs(fgChannels[i] - bgChannels[i]);
        temp.convertTo(temp, CV_32F);

        distance = distance + temp;
    }


    Mat mask;
    threshold(distance, mask, 35, 255, THRESH_BINARY);

    Mat kernel5x5 = getStructuringElement(MORPH_RECT, Size(5, 5));
    morphologyEx(mask, mask, MORPH_OPEN, kernel5x5);

    imshow("fg", fg);
    imshow("bg", bg);
    imshow("mask", mask);

    waitKey();

    return 0;
}

このコードは、入力画像に基づいて次のマスクを生成します。

ここに画像の説明を入力

最後に、単純なしきい値処理方法を使用して取得したものを次に示します。

    Mat diff = fgYcc - bgYcc;
    vector<Mat> diffChannels;
    split(diff, diffChannels);

    // only operating on luminance for background subtraction...
    threshold(diffChannels[0], bgfgMask, 1, 255.0, THRESH_BINARY_INV);

    Mat kernel5x5 = getStructuringElement(MORPH_RECT, Size(5, 5));
    morphologyEx(bgfgMask, bgfgMask, MORPH_OPEN, kernel5x5);

これにより、次のマスクが生成されます。 ここに画像の説明を入力

于 2011-10-31T20:43:01.907 に答える
2

このようにやっていると正しい結果が得られると思います:(YCrCb色空間で)しかし、各ピクセルへのアクセスは遅いので、別のアルゴリズムを見つける必要があります

    cv::Mat mask(image.rows, image.cols, CV_8U, cv::Scalar(0,0,0));

    cv::Mat_<cv::Vec3b>::const_iterator itImage= image.begin<cv::Vec3b>();
    cv::Mat_<cv::Vec3b>::const_iterator itend= image.end<cv::Vec3b>();
    cv::Mat_<cv::Vec3b>::iterator itRef= refRoi.begin<cv::Vec3b>();
    cv::Mat_<uchar>::iterator itMask= mask.begin<uchar>();

    for ( ; itImage!= itend; ++itImage, ++itRef, ++itMask) {
        int distance = abs((*itImage)[0]-(*itRef)[0])+
                        abs((*itImage)[1]-(*itRef)[1])+
                        abs((*itImage)[2]-(*itRef)[2]);

        if(distance < 30)
            *itMask = 0;
        else
            *itMask = 255;
    }
于 2011-11-02T17:47:59.493 に答える