poniedziałek, 15 lutego 2010

Prosty detektor skóry oparty o wektor RGB

Witam po długiej przerwie. Już wiele razy pisałem o tym co planuję, wiele pomysłów na tego bloga przechodziło przez myśl. Ostatecznie wyszło tak, że nie pisałem nic. Więc porzucam te wszystkie pomysły i pisać będę krótsze notki, może częściej, może rzadziej, ale przynajmniej blog będzie dawał czasami znak życia :)

Dzisiaj powraca temat detekcji skóry, ponieważ ostatnio dość mocno nad tym pracuję. Jak kiedyś o tym wspomniałem, najprostsze techniki opierają się o proste zależności między wartościami odpowiednich kanałów obrazu. Dzisiaj jedna z takich metod dająca zaskakująco dobre wyniki (zwłaszcza po zastosowaniu erozji ;). Jej opis znajdziemy tutaj pod tytułem "Human Skin Colour Clustering for Face Detection". Nie owijając w bawełnę, poniżej kod.
IplImage* process(IplImage* img)
{
IplImage * toRet = cvCreateImage(cvGetSize(img), 8, 1);

for (int y = 0; y < img->height; y++)
{
uchar* ptr = (uchar*) (img->imageData + y * img->widthStep);
uchar* ptrRet = (uchar*) (toRet->imageData + y * toRet->widthStep);
for (int x = 0; x < img->width; x++)
{
double b, g, r;

b = ptr[3 * x];
g = ptr[3 * x + 1];
r = ptr[3 * x + 2];
double min = b;
double max = b;
if (min > g)
min = g;
if (min > r)
min = r;
if (max < g)
max = g;
if (max < r)
max = r;
if (r <= 95 ||
g <= 40 ||
b <= 20 ||
max - min <= 15 ||
fabs(r - g) <= 15 ||
r <= g ||
r <= b)
{
ptrRet[x] = 0;
}
else
{
ptrRet[x] = 255;
}
}
}
cvErode(toRet,toRet,NULL,1);
return toRet;
}
W komentarzach możecie podzielić się "wrażaniami" :) U mnie na jednej kamerce działa świetnie, na drugiej gorzej niż średnio :) Wynik działania:
Światło Kamera 1 Kamera 2
Naturalne
Sztuczne
Naturalne + Sztuczne