diff -r 463b4fa9f067 -r 6a6d2ef151e6 plugins/crazychat/camproc.c --- a/plugins/crazychat/camproc.c Wed Oct 18 16:28:51 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,812 +0,0 @@ -/* - * camproc.c - * basecame - * - * Created by CS194 on Mon Apr 26 2004. - * Copyright (c) 2004 __MyCompanyName__. All rights reserved. - * - */ - - -#include "camdata.h" -#include "Utilities.h" -#include "QTUtilities.h" -#include "stdio.h" -#include "math.h" -#include -#include "cc_interface.h" -#include "filter.h" - - -extern int detection_mode; -extern mungDataPtr myMungData; -extern int x_click; -extern int y_click; - - -#define kMinimumIdleDurationInMillis kEventDurationMillisecond -#define BailErr(x) {if (x != noErr) goto bail;} -#define PRE_CALIBRATE_MODE 0 -#define CALIBRATE_MODE 1 -#define SCAN_MODE 2 - -#define CALIB_TOP 190 -#define CALIB_BOTTOM 200 -#define CALIB_LEFT 200 -#define CALIB_RIGHT 210 - -#define CALIB_RADIUS 5 - -#define NUM_FRAMES_EYE_SEARCH 50 -#define EYE_UNCONFIDENCE_LIMIT 7 - -#define BLINK_THRESHOLD 75 -#define BLINK_LENGTH 10 -#define WHITE_THRESH 25 -#define WHITE_COUNT_MAX 200 - - -struct input_instance* instance; -int scan_region_left; -int scan_region_right; -int scan_region_top; -int scan_region_bottom; - -int lum_thresh=150; -int face_left; -int face_right; -int face_top; -int face_bottom; -int old_left_eye_x=50; -int old_left_eye_y=50; -int old_right_eye_x=50; -int old_right_eye_y=50; -int left_eye_x; -int left_eye_y; -int right_eye_x; -int right_eye_y; -int eye_search_frame_count=0; -int bozo_bit=0; -int eye_unconfidence=0; -int last_eye_count_left=0; -int last_eye_count_right=0; -int mouth_ctr_x; -int mouth_ctr_y; -int mouth_size, mouth_left, mouth_right, mouth_top, mouth_bottom; -int white_count; -guint8 head_size_old; -int left_eye_blink_count; -int right_eye_blink_count; - -int left_eye_top, left_eye_bottom, left_eye_right, left_eye_left; -int right_eye_top, right_eye_bottom, right_eye_right, right_eye_left; - -filter_bank *bank; - -static SeqGrabComponent mSeqGrab = NULL; -static SGChannel mSGChanVideo = NULL; -static SGDataUPP mMyDataProcPtr = NULL; -static EventLoopTimerRef mSGTimerRef = 0; -static ImageSequence mDecomSeq = 0; -static EventLoopTimerUPP mSGTimerUPP = nil; -static Rect mMungRect = {0, 0, 480, 640}; -int lower_left_corner_x = 200; -int lower_left_corner_y = 200; -int upper_right_corner_x = 210; -int upper_right_corner_y = 190; - - -static pascal OSErr MiniMungDataProc(SGChannel c, Ptr p, long len, long *offset, long chRefCon, TimeValue time, short writeType, long refCon); -static pascal void SGIdlingTimer(EventLoopTimerRef inTimer, void *inUserData); -static void DetectLobster(GWorldPtr mungDataOffscreen); -int SkinDetect(double Y, double E, double S); -void ScanSkin(PixMapHandle p); -void drawbox(int top, int bottom, int left, int right, int color); -void SkinStats (PixMapHandle p, int top, int bottom, int left, int right); -void SetEyeSearchRegions(void); - - -typedef enum {RED, GREEN, BLUE} color; -color saved_best=-1; - -int filenum=0; - - -OSErr CamProc(struct input_instance *inst, filter_bank *f) -{ - OSStatus error; - OSErr err = noErr; - - BailErr(err = InitializeMungData(mMungRect)); - - bank = f; - - instance=inst; - mMyDataProcPtr = NewSGDataUPP(MiniMungDataProc); - mSeqGrab = OpenDefaultComponent(SeqGrabComponentType, 0); - BailErr((err = CreateNewSGChannelForRecording( mSeqGrab, - mMyDataProcPtr, - GetMungDataOffscreen(), // drawing destination - &mMungRect, - &mSGChanVideo, - NULL))); - -bail: - return err; -} - -void QueryCam (void) -{ - SGIdle(mSeqGrab); -} - -static pascal void SGIdlingTimer(EventLoopTimerRef inTimer, void *inUserData) -{ -#pragma unused(inUserData) - - if (mSeqGrab) - { - SGIdle(mSeqGrab); - } - - // Reschedule the event loop timer - SetEventLoopTimerNextFireTime(inTimer, kMinimumIdleDurationInMillis); -} - -static pascal OSErr MiniMungDataProc(SGChannel c, Ptr p, long len, long *offset, long chRefCon, TimeValue time, short writeType, long refCon) -{ - - -#pragma unused(offset,chRefCon,time,writeType,refCon) - ComponentResult err = noErr; - CodecFlags ignore; - GWorldPtr gWorld; - - - - - if (!myMungData) goto bail; - - gWorld = GetMungDataOffscreen(); - if(gWorld) - { - if (mDecomSeq == 0) // init a decompression sequence - { - Rect bounds; - - GetMungDataBoundsRect(&bounds); - - BailErr( CreateDecompSeqForSGChannelData(c, &bounds, gWorld, &mDecomSeq)); - - if(1) - //if ((!mUseOverlay) && (GetCurrentClamp() == -1) && (!mUseEffect)) - { - ImageSequence drawSeq; - - err = CreateDecompSeqForGWorldData( gWorld, - &bounds, - nil, - GetMungDataWindowPort(), - &drawSeq); - SetMungDataDrawSeq(drawSeq); - } - } - - // decompress data to our offscreen gworld - BailErr(DecompressSequenceFrameS(mDecomSeq,p,len,0,&ignore,nil)); - - // image is now in the GWorld - manipulate it at will! - //if ((mUseOverlay) || (GetCurrentClamp() != -1) || (mUseEffect)) - //{ - // use our custom decompressor to "decompress" the data - // to the screen with overlays or color clamping - // BlitOneMungData(myMungData); - //} - //else - //{ - // we are doing a motion detect grab, so - // search for lobsters in our image data - DetectLobster(gWorld); - //} - - } - -bail: - return err; -} - -void Die() -{ - //RemoveEventLoopTimer(mSGTimerRef); - // mSGTimerRef = nil; - // DisposeEventLoopTimerUPP(mSGTimerUPP); - DoCloseSG(mSeqGrab, mSGChanVideo, mMyDataProcPtr); - -} - - -float Y_mean=-1; -float Y_dev,E_mean,E_dev,S_mean,S_dev; -/* - extern colorBuf[480][640]; -*/ -extern unsigned int (*colorBuf)[644]; -extern struct input_instance input_data; - -static void DetectLobster(GWorldPtr mungDataOffscreen) -{ - CGrafPtr oldPort; - GDHandle oldDevice; - int x, y; - Rect bounds; - PixMapHandle pix = GetGWorldPixMap(mungDataOffscreen); - UInt32 * baseAddr; - UInt32 reds = 0; - Str255 tempString; - int minX = 10000, maxX = -10000; - int minY = 10000, maxY = -10000; - Rect tempRect; - float percent; - OSErr err; - CodecFlags ignore; - color best; - long R_total=0; - long G_total=0; - long B_total=0; - - - - //fprintf(stderr, "Starting to find some lobsters...\n"); - - - GetPortBounds(mungDataOffscreen, &bounds); - OffsetRect(&bounds, -bounds.left, -bounds.top); - - - UInt32 color; - - - int sum_x,sum_y=0; - int count=0; - int k,j; - long R; - long G; - long B; - int search_width=200; - int search_height=200; - - - colorBuf = GetPixBaseAddr(pix); - - switch (detection_mode) { - - case PRE_CALIBRATE_MODE: - //drawbox(CALIB_TOP, CALIB_BOTTOM, CALIB_LEFT, CALIB_RIGHT); - break; - - case CALIBRATE_MODE: - SkinStats(pix, y_click-CALIB_RADIUS, y_click+CALIB_RADIUS, x_click-CALIB_RADIUS, x_click+CALIB_RADIUS); - scan_region_left=x_click-CALIB_RADIUS;//10; - scan_region_right=x_click+CALIB_RADIUS;//630; - scan_region_top=y_click-CALIB_RADIUS;//10; - scan_region_bottom=y_click+CALIB_RADIUS;//470; - ScanSkin(pix); - detection_mode=SCAN_MODE; - //fprintf(stderr, "scan left: %d scan right: %d \n",scan_region_left,scan_region_right); - head_size_old=50; - break; - - case SCAN_MODE: - ScanSkin(pix); - drawbox(face_top, face_bottom, face_left, face_right,1); - //drawbox(scan_region_top, scan_region_bottom, scan_region_left, scan_region_right); - drawbox((left_eye_y-5),(left_eye_y+5),(left_eye_x-5),(left_eye_x+5),0); - drawbox((right_eye_y-5),(right_eye_y+5),(right_eye_x-5),(right_eye_x+5),0); - int face_scale=instance->face.head_size; - int mouth_width=face_scale; - int mouth_height=face_scale; - // if (bozo_bit==1) drawbax((mouth_ctr_y-mouth_height),(mouth_ctr_y+mouth_height),(mouth_ctr_x-mouth_width),(mouth_ctr_x+mouth_width)); - filter(&instance->face, bank); - break; - } - - //fprintf(stderr, "Lobsters found...\n"); - - -} - - - - -void ScanSkin(PixMapHandle p) -{ - int y,x,j,k; - int right_eye_x_sum,right_eye_y_sum,left_eye_x_sum,left_eye_y_sum,right_eye_pt_count,left_eye_pt_count; - right_eye_x_sum=right_eye_y_sum=left_eye_x_sum=left_eye_y_sum=right_eye_pt_count=left_eye_pt_count=0; - long R,G,B,sum_x,sum_y; - int count; - double Y,E,S,lum; - double min_lum_mouth=766; - double min_lum_left=766; - double min_lum_right=766; - UInt32 color; - UInt32 * baseAddr; - int max_horz=0; - int max_vert=0; - sum_x=sum_y=count=0; - int horz_count[480]; - int vert_count[640]; - - - - memset(horz_count,0,480*sizeof(int)); - memset(vert_count,0,640*sizeof(int)); - - if (eye_search_frame_count> 16; - G = (color & 0x0000FF00) >> 8; - B = (color & 0x000000FF) >> 0; - Y=.253*R+.684*G+.063*B; - E=.5*R-.5*G; - S=.25*R+.25*G-.5*B; - lum=R+G+B; - - if (y>left_eye_top && y left_eye_left && xright_eye_top && y right_eye_left && x < right_eye_right) - { - if (lum < lum_thresh) { - right_eye_x_sum+=x; - right_eye_y_sum+=y; - right_eye_pt_count++; - //colorBuf[y][x]=0x0000FF00; - } - } - } - - if(SkinDetect(Y,E,S)) - { - sum_x+=x; - sum_y+=y; - count++; - - ++horz_count[y]; - ++vert_count[x]; - - if (horz_count[y]>max_horz) max_horz=horz_count[y]; - if (vert_count[x]>max_vert) max_vert=vert_count[x]; - - //colorBuf[y][x]=0x00FF0000; - } - - } - } - - - left_eye_x=left_eye_x_sum/left_eye_pt_count; - left_eye_y=left_eye_y_sum/left_eye_pt_count; - right_eye_x=right_eye_x_sum/right_eye_pt_count; - right_eye_y=right_eye_y_sum/right_eye_pt_count; - - - - int width=right_eye_x-left_eye_x; - int height=right_eye_y-left_eye_y; - double face_ang; - if (width!=0) face_ang=atan((double)height/width); - else face_ang=0; - face_ang=face_ang*180/pi; - //fprintf(stderr,"face angle: %f \n",face_ang); - - if ((left_eye_pt_count<5 || right_eye_pt_count<5 || width==0 || face_ang > 30 || face_ang < -30 - || left_eye_y < (face_top+.15*(face_bottom-face_top)) - || right_eye_y < (face_top+.15*(face_bottom-face_top))) - && bozo_bit==1){ - eye_unconfidence++; - left_eye_x=old_left_eye_x; - left_eye_y=old_left_eye_y; - right_eye_x=old_right_eye_x; - right_eye_y=old_right_eye_y; - } - else { - eye_unconfidence=0; - old_left_eye_x=left_eye_x; - old_left_eye_y=left_eye_y; - old_right_eye_x=right_eye_x; - old_right_eye_y=right_eye_y; - } - - - if (eye_unconfidence==EYE_UNCONFIDENCE_LIMIT){ - bozo_bit=0; - eye_search_frame_count=0; - //fprintf(stderr, "Recalibrating eyes\n"); - } - - if ((last_eye_count_left-left_eye_pt_count> BLINK_THRESHOLD) && eye_unconfidence==0) - { - left_eye_blink_count=BLINK_LENGTH; - } - if (left_eye_blink_count>0){ - instance->face.left_eye_open=0; - left_eye_blink_count--; - } - else instance->face.left_eye_open=1; - - if ((last_eye_count_right-right_eye_pt_count> BLINK_THRESHOLD) && eye_unconfidence==0) - { - right_eye_blink_count=BLINK_LENGTH; - } - if (right_eye_blink_count>0){ - instance->face.right_eye_open=0; - right_eye_blink_count--; - } - else instance->face.right_eye_open=1; - - if (instance->face.right_eye_open==0) instance->face.left_eye_open=0; - if (instance->face.left_eye_open==0) instance->face.right_eye_open=0; - - last_eye_count_left=left_eye_pt_count; - last_eye_count_right=right_eye_pt_count; - - float x_shift=0; - if (width!=0) x_shift= (float)height/(float)width; // --> note dependence on earlier data here - - -if (bozo_bit==1){ - int mouth_search_start_y=face_top+(.6*(face_bottom-face_top)); - int mouth_search_end_y=face_bottom; - int mouth_search_start_x=(left_eye_x+right_eye_x)/2 + (-x_shift*(mouth_search_start_y-((right_eye_y+left_eye_y)/2))) ; - -for (y=mouth_search_start_y; y < mouth_search_end_y; y++) -{ - x=mouth_search_start_x+((y - mouth_search_start_y)*(-x_shift)); - baseAddr = (UInt32*)(GetPixBaseAddr(p) + y * GetPixRowBytes(p)); - //colorBuf[y][x] = 0x0000FF00; - color=baseAddr[x]; - R = (color & 0x00FF0000) >> 16; - G = (color & 0x0000FF00) >> 8; - B = (color & 0x000000FF) >> 0; - lum=R+G+B; - - if (lum face_right) mouth_right=face_right; - mouth_top=mouth_ctr_y-mouth_size; - if (mouth_top < face_top) mouth_top=face_top; - mouth_bottom=mouth_ctr_y+mouth_size; - if (mouth_bottom > face_bottom) mouth_bottom=face_bottom; - - white_count=0; - - for (y=mouth_top; y< mouth_bottom; y++){ - baseAddr = (UInt32*)(GetPixBaseAddr(p) + y * GetPixRowBytes(p)); - for (x=mouth_left; x< mouth_right; x++){ - color=baseAddr[x]; - R = (color & 0x00FF0000) >> 16; - G = (color & 0x0000FF00) >> 8; - B = (color & 0x000000FF) >> 0; - if ((abs(R-G) < WHITE_THRESH) && (abs(G-B) < WHITE_THRESH) && (abs(R-B) < WHITE_THRESH)) - { - white_count++; - //colorBuf[y][x]=0x0000FF00; - } - } - } - - } -else white_count=10; - -// This next section finds the face region and sets the face_* parameters. - - int scan; - float thresh=.3; - scan=scan_region_left+1; - if (scan<0) scan=0; - //fprintf(stderr,"threshold value: %d boxtop value: %d \n", (max_horz), horz_count[scan_region_top]); - while(1) - { - if (vert_count[scan]>=(thresh*max_vert)) - { - face_left=scan; - break; - } - scan++; - } - - scan=scan_region_right-1; - if (scan>=640) scan=639; - while(1) - { - if (vert_count[scan]>=(thresh*max_vert)) - { - face_right=scan; - break; - } - scan--; - } - - scan=scan_region_top+1; - if (scan<0) scan=0; - while(1) - { - if (horz_count[scan]>=(thresh*max_horz)) - { - face_top=scan; - break; - } - scan++; - } - - - scan=scan_region_bottom-1; - if (scan>=480) scan=479; - while(1) - { - if (horz_count[scan]>=(thresh*max_horz)) - { - face_bottom=scan; - break; - } - scan--; - } - - // Base scan region on face region here - scan_region_left=face_left-10; - if (scan_region_left <= 0) scan_region_left=1; - scan_region_right=face_right+10; - if (scan_region_right >= 640) scan_region_right=639; - scan_region_top=face_top-10; - if (scan_region_top <= 0) scan_region_top=1; - scan_region_bottom=face_bottom+10; - if (scan_region_bottom >= 480) scan_region_bottom=479; - - - // Calculate some stats - - // face size - width=face_right-face_left; - guint8 temp=width*100/640; - instance->face.head_size=temp; - - // face location - temp=((double)100/(double)640)*(double)(face_right+face_left)/2; - instance->face.x=temp; - temp=((double)100/(double)480)*(double)(face_top+face_bottom)/2; - instance->face.y=temp; - - // face angle-Z - instance->face.head_z_rot=face_ang+50; - - // face angle-Y - int center=(face_right+face_left)/2; - int right_eye_strad=right_eye_x-center; - int left_eye_strad=center-left_eye_x; - double y_ang; - if (right_eye_strad > left_eye_strad) y_ang= (double)right_eye_strad/(double)left_eye_strad; - else y_ang=(double)left_eye_strad/(double)right_eye_strad; - y_ang=y_ang*5; - if (y_ang >= 10) y_ang=30; - if (y_ang <= 1) y_ang=1; - - if (right_eye_strad > left_eye_strad) y_ang=-y_ang; - temp = (guint8) 50 + y_ang; - instance->face.head_y_rot=temp; - - if (abs (temp-50) > 15) instance->face.head_size=head_size_old; - else head_size_old=instance->face.head_size; - - temp = (guint8) 100 * white_count / WHITE_COUNT_MAX; - if (temp > 100) temp=100; - instance->face.mouth_open = temp; - -} - - - - - - - // draw bounding box for either calibration or face - - -void SetEyeSearchRegions(void) -{ - if (bozo_bit==0) - { - left_eye_top=face_top+(.25*(face_bottom-face_top)); - left_eye_bottom=face_top+(.6*(face_bottom-face_top)); - left_eye_right=((face_left+face_right)/2); - left_eye_left=face_left+.15*(face_right-face_left); - - right_eye_top=face_top+(.25*(face_bottom-face_top)); - right_eye_bottom=face_top+(.6*(face_bottom-face_top)); - right_eye_right=face_right-.15*(face_right-face_left); - right_eye_left=((face_left+face_right)/2); - } - - if (bozo_bit==1) - { - left_eye_top=left_eye_y-20; - left_eye_bottom=left_eye_y+20; - left_eye_left=left_eye_x-20; - left_eye_right=left_eye_x+20; - - right_eye_top=right_eye_y-20; - right_eye_bottom=right_eye_y+20; - right_eye_left=right_eye_x-20; - right_eye_right=right_eye_x+20; - } -} - - -void drawbox(int top, int bottom, int left, int right, int color) -{ - int y, x, j; - - unsigned int col; - - - if (color==1) - col=0x00FFFF00; - else - col=0x00FF00FF; - - if (top<0) top =0; - if (top>=480) top=479; - if (bottom<0) bottom =0; - if (bottom>=480) bottom=479; - if (left<0) left =0; - if (left>=640) left=639; - if (right<0) right =0; - if (right>=640) right=639; - - if (color==1){ - - for (y=top; y> 16; - G = (color & 0x0000FF00) >> 8; - B = (color & 0x000000FF) >> 0; - Y=.253*R+.684*G+.063*B; - E=.5*R-.5*G; - S=.25*R+.25*G-.5*B; - Y_sum+=Y; - E_sum+=E; - S_sum+=S; - } - } - - Y_mean=Y_sum/count; - E_mean=E_sum/count; - S_mean=S_sum/count; - - Y_sum=E_sum=S_sum=0; - - for (y=top; y> 16; - G = (color & 0x0000FF00) >> 8; - B = (color & 0x000000FF) >> 0; - Y=.253*R+.684*G+.063*B; - E=.5*R-.5*G; - S=.25*R+.25*G-.5*B; - - Y_sum+=(Y-Y_mean)*(Y-Y_mean); - E_sum+=(E-E_mean)*(E-E_mean); - S_sum+=(S-S_mean)*(S-S_mean); - - } - } - - Y_dev=sqrt(Y_sum/(count-1)); - E_dev=sqrt(E_sum/(count-1)); - S_dev=sqrt(S_sum/(count-1)); - - //fprintf(stderr,"Y: %f, %f\n E: %f, %f\nS: %f, %f\n",Y_mean,E_mean,S_mean,Y_dev,E_dev,S_dev); - -} - -int SkinDetect(double Y, double E, double S) -{ - if (E>(E_mean-(2*E_dev)) && E<(E_mean+(2*E_dev))) return 1; - else return 0; -} -