Посмотрите на функцию inRange из OpenCV. Это позволит вам одновременно установить несколько порогов для 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);
Это дает следующую маску: