1

We have a need to accept pictures as input, and then manipulate/overlay image data above sections of "flesh" in the original image.

Has anyone dealt with easy technologies to facilitate this kind of process? Have read about OpenCV, but am hopeful that there's an easier path.

Alex
  • 41
  • 4

1 Answers1

1

I think the easiest path IS opencv for what you want to do.

There's a link about 'simpler' stuff: http://media.packetlife.net/media/blog/attachments/413/nbar_flesh_tone.html (If you got a Cisco server where you want to prioritize non-flesh colored images.)

This thread Nude image detection - OPENCV Links to : https://csel.cs.colorado.edu/~xingx/project/privacy.html (No code, research on video 'nude' detection.)

You can look at O'reilly Opencv book. There's a hsv color space example for flesh color explained there. This book explains it well. (There are some google book pages available if you search.)

You can also look at the camshift opencv example.

This is a link to the problem space in opencv. (If you want some code, or read a bit about using the color space HSV or CIE Lab* color space) http://tech.groups.yahoo.com/group/OpenCV/message/45158

Some code copied from that opencv group that gives a mask for the 'flesh color':

src_RGB = RGB-Image (IPL_DEPTH_8U , 3); // Source
mask_BW = GRAY-Image (IPL_DEPTH_8U , 3);// Resulting Mask same size as source !!
//after GetSkinMask you can use cvAnd between src_RGB and mask_BW.


void GetSkinMask(IplImage * src_RGB, IplImage * mask_BW, int
erosions=1, int dilations=7)
{   

CvSize size;

CvSize sz = cvSize( src_RGB->width & -2, src_RGB->height & -2);
//get the size of input_image (src_RGB)

IplImage* pyr = cvCreateImage( cvSize(sz.width/2, sz.height/2), 8,   3 ); //create 2 temp-images

IplImage* src = cvCreateImage(cvGetSize(src_RGB), IPL_DEPTH_8U ,3);
cvCopyImage(src_RGB, src);

IplImage* tmpYCR = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U , 3);
cvPyrDown( src, pyr, 7 );
//remove noise from input
cvPyrUp( pyr, src, 7 );

cvCvtColor(src ,tmpYCR , CV_RGB2YCrCb);

uchar Y;
uchar Cr;
uchar Cb;

CvPixelPosition8u pos_src;
CvPixelPosition8u pos_dst;

int x =0;
int y =0;

CV_INIT_PIXEL_POS(pos_src,(unsigned char *) tmpYCR->imageData,
tmpYCR->widthStep,    cvGetSize(tmpYCR), x,y, tmpYCR->origin);

CV_INIT_PIXEL_POS(pos_dst,    (unsigned char *) mask_BW->imageData,
mask_BW->widthStep,    cvGetSize(mask_BW),   x,y, mask_BW->origin);

uchar * ptr_src;
uchar * ptr_dst;


for( y=0;y<src-> height; y++)
{

    for ( x=0; x<src->width; x++)
    {

        ptr_src = CV_MOVE_TO(pos_src,x,y,3);
        ptr_dst = CV_MOVE_TO(pos_dst,x,y,3);

        Y = ptr_src[0];
        Cb= ptr_src[1];
        Cr= ptr_src[2];

        if( Cr > 138 && Cr < 178 &&
        Cb + 0.6 * Cr >200 && Cb + 0.6 * Cr <215)
        {
            ptr_dst[0] = 255;
            ptr_dst[1] = 255;
            ptr_dst[2] = 255;
        }
        else
        {
            ptr_dst[0] = 0;
            ptr_dst[1] = 0;
            ptr_dst[2] = 0;
        }


    }
}

if(erosions>0) cvErode(mask_BW,mask_BW,0,erosions);
if (dilations>0) cvDilate(mask_BW,mask_BW,0,dilations);

cvReleaseImage(&pyr);
cvReleaseImage(&tmpYCR);
cvReleaseImage(&src);
}
Community
  • 1
  • 1
knowledge_is_power
  • 868
  • 1
  • 11
  • 10