뭔진 모르지만 좋아보임..나중에 한번 봐야지..
http://read.pudn.com/downloads113/sourcecode/graph/text_recognize/474247/2/%E8%8D%A4%E5%A4%AF%20-%20LswVisionMouse/MouthFeature.cpp__.htm
#include "StdAfx.h" #include "MouthFeature.h" CMouthFeature::CMouthFeature() { m_boundaryMin = m_boundaryMax = cvPoint( 1, 1 ); threshold= 130; m_pPrevBuffer = new unsigned char[ TRACK_CAMERA_WIDTH*TRACK_CAMERA_HEIGHT ]; memset( m_pPrevBuffer, 0, TRACK_CAMERA_WIDTH*TRACK_CAMERA_HEIGHT ); m_count = 0; m_projScale = 10; m_switch1 = 0; m_switch2 = 0; m_switch3 = 0; m_switch4 = 0; m_switch5 = 0; m_segmentCountX=0; m_segmentCountY=0; m_bIsActive = false; m_mouthHeightOffset = 0; m_threshImage = cvCreateImage( cvSize( TRACK_CAMERA_WIDTH, TRACK_CAMERA_HEIGHT ), 8, 1 ); } CMouthFeature::~CMouthFeature() { delete [] m_pPrevBuffer; } void CMouthFeature::drawBoundary( CvArr* image ) { cvRectangle( image, m_boundaryMin, m_boundaryMax, CV_RGB(255,0,0) ); } void CMouthFeature::removeNoise( IplImage* greyImage ) { int i; int size = TRACK_CAMERA_WIDTH*TRACK_CAMERA_HEIGHT; int thresh = 12; for( i=0; i<size; i++ ) { if( abs( greyImage->imageData[ i ] - m_pPrevBuffer[ i ] ) < thresh ) { greyImage->imageData[ i ] = m_pPrevBuffer[ i ]; } m_pPrevBuffer[ i ] = greyImage->imageData[ i ]; } } #include "highgui.h" void CMouthFeature::updateStep1( IplImage* greyImage, IplImage* rgbFrame ) { switch( m_switch1 ) { case 0: break; case 1: cvCvtColor( rgbFrame , rgbFrame, CV_RGB2HSV); cvSetImageCOI(rgbFrame,1); cvCopy(rgbFrame,greyImage); cvSetImageCOI(rgbFrame,0); cvCvtColor( rgbFrame, rgbFrame, CV_HSV2RGB); break; case 2: IplImage* tempB = cvCreateImage( cvSize( TRACK_CAMERA_WIDTH, TRACK_CAMERA_HEIGHT ), 8, 1 ); IplImage* tempG = cvCreateImage( cvSize( TRACK_CAMERA_WIDTH, TRACK_CAMERA_HEIGHT ), 8, 1 ); cvCvtPixToPlane( rgbFrame, tempB, tempG, greyImage, NULL); cvReleaseImage( &tempB ); cvReleaseImage( &tempG ); break; } cvCopy(greyImage,m_threshImage); cvThreshold(m_threshImage,m_threshImage,threshold,255,CV_THRESH_BINARY_INV); adjustThreshold(); } void CMouthFeature::updateStep2( IplImage* greyImage ) { if( m_switch2 > 0 ) removeNoise( greyImage ); } void CMouthFeature::updateStep3( IplImage* greyImage ) { if( m_switch3 > 0 ) { cvSmooth( greyImage, greyImage ); cvDilate( greyImage, greyImage, NULL, 1 ); cvErode( greyImage, greyImage, NULL, 3 ); } } void CMouthFeature::updateStep4( IplImage* greyImage ) { switch( m_switch4 ) { case 0: cvThreshold( greyImage, greyImage, threshold, 0, CV_THRESH_TOZERO_INV ); break; case 1: cvThreshold( greyImage, greyImage, threshold, 0, CV_THRESH_TOZERO ); break; case 2: cvThreshold( greyImage, greyImage, threshold, 255, CV_THRESH_BINARY_INV ); break; } } void CMouthFeature::updateStep5( IplImage* greyImage, IplImage* rgbFrame, bool isFaceThere ) { bool projectInv = false; if( m_switch5 > 0 ) projectInv = true; cvCvtColor( greyImage, rgbFrame, CV_GRAY2RGB ); if( isFaceThere ) { calcProjection( rgbFrame, greyImage, projectInv ); } drawBoundary( rgbFrame ); } void CMouthFeature::updateStep6() { } void CMouthFeature::updateFrame( IplImage* greyImage, IplImage* rgbFrame, bool isFaceThere ) { updateStep1( greyImage, rgbFrame ); updateStep2( greyImage ); updateStep3( greyImage ); updateStep4( greyImage ); updateStep5( greyImage, rgbFrame, isFaceThere ); updateStep6(); adjustThreshold(); } void CMouthFeature::calcProjectionHori( IplImage* image, IplImage* grey, bool projectInv ) { int yy; float maxHistoHori, minHistoHori; int maxPos; m_hMin1 = m_hMin2 = maxPos = 0; maxHistoHori = 0; minHistoHori = 999; int upCount=0; int downCount=0; int prevSum=0; int dx = m_boundaryMax.x - m_boundaryMin.x; int dy = m_boundaryMax.y - m_boundaryMin.y; int boundaryWidth = m_boundaryMax.x - m_boundaryMin.x; for( yy=m_boundaryMin.y; yy<m_boundaryMin.y+dy/2; yy++ ) { float sumX = 0; for( int xx=m_boundaryMin.x; xx<m_boundaryMax.x; xx++ ) { unsigned char pixel = grey->imageData[ yy*grey->width+xx ]; if( projectInv ) pixel = 255 - pixel; sumX += pixel * m_projScale; } sumX /= boundaryWidth; m_histoBuf[ yy ] = sumX; if( sumX > maxHistoHori ) { maxHistoHori = sumX; maxPos = yy; } prevSum = sumX; cvLine( image, cvPoint( m_boundaryMax.x+1, yy ), cvPoint( m_boundaryMax.x+sumX, yy ), CV_RGB(0,0,255),1 ); } int startX = m_boundaryMin.x; int endX = m_boundaryMax.x; for( yy=m_boundaryMin.y+dy/2; yy<m_boundaryMax.y; yy++ ) { float sumX = 0; for( int xx=startX; xx<endX; xx++ ) { unsigned char pixel = grey->imageData[ yy*grey->width+xx ]; if( projectInv ) pixel = 255 - pixel; sumX += pixel * m_projScale; } startX++; endX--; sumX /= boundaryWidth; m_histoBuf[ yy ] = sumX; if( sumX > maxHistoHori ) { maxHistoHori = sumX; maxPos = yy; } prevSum = sumX; cvLine( image, cvPoint( m_boundaryMax.x+1, yy ), cvPoint( m_boundaryMax.x+sumX, yy ), CV_RGB(0,0,255),1 ); } cvLine( image, cvPoint( m_boundaryMax.x+1, maxPos ), cvPoint( m_boundaryMax.x+maxHistoHori, maxPos ), CV_RGB(255,255,255),1 ); minHistoHori = maxHistoHori * 0.2f; for( yy=maxPos-1; yy>=m_boundaryMin.y; yy-- ) { if( m_histoBuf[ yy ] < minHistoHori ) { cvLine( image, cvPoint( m_boundaryMax.x+1, yy ), cvPoint( m_boundaryMax.x+minHistoHori, yy ), CV_RGB(255,255,255),1 ); break; } if( yy == m_boundaryMin.y) cvLine( image, cvPoint( m_boundaryMax.x+1, yy ), cvPoint( m_boundaryMax.x+minHistoHori, yy ), CV_RGB(255,255,255),1 ); } m_hMin1 = yy; for( yy=maxPos+1; yy<m_boundaryMax.y; yy++ ) { if( m_histoBuf[ yy ] < minHistoHori ) { cvLine( image, cvPoint( m_boundaryMax.x+1, yy ), cvPoint( m_boundaryMax.x+minHistoHori, yy ), CV_RGB(255,255,255),1 ); break; } if( yy == m_boundaryMax.y-1 ) cvLine( image, cvPoint( m_boundaryMax.x+1, yy ), cvPoint( m_boundaryMax.x+minHistoHori, yy ), CV_RGB(255,255,255),1 ); } m_hMin2 = yy; if( m_hMin1 < 0 ) m_hMin1 = 0; } void CMouthFeature::calcProjectionVerti( IplImage* image, IplImage* grey, bool projectInv ) { int xx; float maxHistoVerti, minHistoVerti; int maxPos; m_vMin1 = m_vMin2 = maxPos = 0; maxHistoVerti = 0; minHistoVerti = 999; int boundaryHeight = m_boundaryMax.y - m_boundaryMin.y; for( xx=m_boundaryMin.x; xx<m_boundaryMax.x; xx++ ) { long sumY = 0; for( int yy=m_hMin1; yy<m_hMin2; yy++ ) { unsigned char pixel = grey->imageData[ yy*grey->width+xx ]; if( projectInv ) pixel = 255 - pixel; sumY += pixel * m_projScale; } sumY /= boundaryHeight; m_histoBuf[ xx ] = sumY; if( sumY > maxHistoVerti ) { maxHistoVerti = sumY; maxPos = xx; } cvLine( image, cvPoint( xx, m_boundaryMin.y-1 ), cvPoint( xx, m_boundaryMin.y-sumY ), CV_RGB(0,255,0),1 ); } cvLine( image, cvPoint( maxPos, m_boundaryMin.y-1 ), cvPoint( maxPos, m_boundaryMin.y-maxHistoVerti ), CV_RGB(255,255,255),1 ); minHistoVerti = maxHistoVerti * 0.2f; for( xx=m_boundaryMin.x; xx<m_boundaryMax.x; xx++ ) { if( m_histoBuf[ xx ] > minHistoVerti ) { cvLine( image, cvPoint( xx, m_boundaryMin.y-1 ), cvPoint( xx, m_boundaryMin.y-minHistoVerti ), CV_RGB(255,255,255),1 ); break; } if( xx == m_boundaryMax.x-1 ) cvLine( image, cvPoint( xx, m_boundaryMin.y-1 ), cvPoint( xx, m_boundaryMin.y-minHistoVerti ), CV_RGB(255,255,255),1 ); } m_vMin1 = xx; for( xx=m_boundaryMax.x-1; xx>=m_boundaryMin.x; xx-- ) { if( m_histoBuf[ xx ] > minHistoVerti ) { cvLine( image, cvPoint( xx, m_boundaryMin.y-1 ), cvPoint( xx, m_boundaryMin.y-minHistoVerti ), CV_RGB(255,255,255),1 ); break; } if( xx == m_boundaryMin.x ) cvLine( image, cvPoint( xx, m_boundaryMin.y-1 ), cvPoint( xx, m_boundaryMin.y-minHistoVerti ), CV_RGB(255,255,255),1 ); } m_vMin2 = xx; } void CMouthFeature::calcProjection( IplImage* image, IplImage* grey, bool projectInv ) { calcProjectionHori( image, grey, projectInv ); calcProjectionVerti( image, grey, projectInv ); } int CMouthFeature::getCount() { return m_count; } void CMouthFeature::setCount( int num ) { m_count = num; } void CMouthFeature::setMinBoundary( CvPoint minPt ) { m_boundaryMin = minPt; m_boundaryMin.x = max( m_boundaryMin.x, 0 ); m_boundaryMin.y = max( m_boundaryMin.y, 0 ); m_boundaryMin.y += m_mouthHeightOffset; } void CMouthFeature::getMinBoundary( CvPoint& minPt ) { minPt = m_boundaryMin; } void CMouthFeature::setMaxBoundary( CvPoint maxPt ) { m_boundaryMax = maxPt; if( TRACK_CAMERA_WIDTH-1 < m_boundaryMax.x - m_boundaryMin.x ) m_boundaryMax.x = m_boundaryMin.x + 799; if( TRACK_CAMERA_WIDTH-1 < m_boundaryMax.y - m_boundaryMin.y ) m_boundaryMax.y = m_boundaryMin.y + 799; m_boundaryMax.x = max( m_boundaryMax.x, 1 ); m_boundaryMax.y = max( m_boundaryMax.y, 1 ); m_boundaryMax.y += m_mouthHeightOffset; } void CMouthFeature::getMaxBoundary( CvPoint& maxPt ) { maxPt = m_boundaryMax; } int CMouthFeature::getVerMin1() { return m_vMin1; } int CMouthFeature::getVerMin2() { return m_vMin2; } int CMouthFeature::getHorMin1() { return m_hMin1; } int CMouthFeature::getHorMin2() { return m_hMin2; } void CMouthFeature::setNormalWidth() { float width = m_boundaryMax.x - m_boundaryMin.x; m_normalWidth = (float)(m_vMin2-m_vMin1)/width; } void CMouthFeature::setNormalHeight() { float height = m_boundaryMax.x - m_boundaryMin.x; m_normalHeight = (float)(m_hMin2-m_hMin1)/height; } float CMouthFeature::getNormalWidth() { setNormalWidth(); return m_normalWidth; } float CMouthFeature::getNormalHeight() { setNormalHeight(); return m_normalHeight; } void CMouthFeature::resetThreshold() { threshold = 140; } void CMouthFeature::setStaticThreshold( int thresh ) { threshold = thresh; } void CMouthFeature::adjustThreshold() { int x,y,i; int pX = m_boundaryMax.x - m_boundaryMin.x; int pY = m_boundaryMax.y - m_boundaryMin.y; int interval=5; int x1 = m_vMin1-interval; int x2 = m_vMin2+interval; int y1 = m_hMin1-interval; int y2 = m_hMin2+interval; if( x1<m_boundaryMin.x ) x1=m_boundaryMin.x; if( y1<m_boundaryMin.y ) y1=m_boundaryMin.y; if( x2>m_boundaryMax.x ) x2=m_boundaryMax.x; if( y2>m_boundaryMax.y ) y2=m_boundaryMax.y; bool black; int whiteCount; int blackCount=0; int state=0; int startX=0, lastX=0; int yThresh = m_boundaryMin.y + pY*0.66f; for( x=x1; x<x2; x++ ) { black=false; for( y=y1; y<y2; y++ ) { i = y*TRACK_CAMERA_WIDTH+x; if( (unsigned char)m_threshImage->imageData[i]==0 ) { black=true; break; } } if( black ) { blackCount++; } switch(state) { case 0: if( black ) { state++; whiteCount=0; } break; case 1: if( !black ) { if( ++whiteCount>=2 ) state++; } break; case 2: if( black ) { m_segmentCountX++; whiteCount=0; state=1; } break; } } if( m_segmentCountX>=1 || blackCount==0 ) { threshold--; m_segmentCountX=0; } state=0; blackCount=0; for( y=y1; y<y2; y++ ) { black=false; for( x=x1; x<x2; x++ ) { i = y*TRACK_CAMERA_WIDTH+x; if( (unsigned char)m_threshImage->imageData[i]==0 ) { black=true; break; } } if( black ) blackCount++; switch(state) { case 0: if( black ) { state++; whiteCount=0; } break; case 1: if( !black ) { if( ++whiteCount>=2 ) state++; } break; case 2: if( black ) { m_segmentCountY++; whiteCount=0; state=1; } break; } } if( m_segmentCountY>=1 ) { threshold++; m_segmentCountY=0; } }