pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
Less delay for XMPP file transfer using streamhosts. Ignore 0.0.0.0.
release-2.x.y
2019-11-05, Evert Mouw
771af5c28038
Less delay for XMPP file transfer using streamhosts. Ignore 0.0.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
<gtk/gtk.h>
#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
<
NUM_FRAMES_EYE_SEARCH
)
eye_search_frame_count
++
;
else
if
(
eye_search_frame_count
==
NUM_FRAMES_EYE_SEARCH
&&
bozo_bit
==
0
)
{
bozo_bit
=
1
;
//fprintf(stderr, "GOOD You flipped the bozo bit (to good)\n");
}
SetEyeSearchRegions
();
for
(
y
=
scan_region_top
;
y
<
scan_region_bottom
;
y
++
)
// change this to only calculate in bounding box
{
baseAddr
=
(
UInt32
*
)(
GetPixBaseAddr
(
p
)
+
y
*
GetPixRowBytes
(
p
));
for
(
x
=
scan_region_left
;
x
<
scan_region_right
;
x
++
)
{
color
=
baseAddr
[
x
];
R
=
(
color
&
0x00FF0000
)
>>
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_bottom
)
{
if
(
x
>
left_eye_left
&&
x
<
left_eye_right
)
{
if
(
lum
<
lum_thresh
)
{
left_eye_x_sum
+=
x
;
left_eye_y_sum
+=
y
;
left_eye_pt_count
++
;
//colorBuf[y][x]=0x0000FF00;
}
}
}
if
(
y
>
right_eye_top
&&
y
<
right_eye_bottom
)
{
if
(
x
>
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
<
min_lum_mouth
)
{
min_lum_mouth
=
lum
;
mouth_ctr_x
=
x
;
mouth_ctr_y
=
y
;
}
}
mouth_size
=
(
face_right
-
face_left
)
*
100
/
640
;
mouth_left
=
mouth_ctr_x
-
mouth_size
;
if
(
mouth_left
<
face_left
)
mouth_left
=
face_left
;
mouth_right
=
mouth_ctr_x
+
mouth_size
;
if
(
mouth_right
>
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
<
bottom
;
y
++
)
{
for
(
j
=
0
;
j
<
5
;
j
++
){
colorBuf
[
y
][
left
+
j
]
=
col
;
colorBuf
[
y
][
right
-
j
]
=
col
;
}
}
for
(
x
=
left
;
x
<
right
;
x
++
)
{
for
(
j
=
0
;
j
<
5
;
j
++
){
colorBuf
[
bottom
-
j
][
x
]
=
col
;
colorBuf
[
top
+
j
][
x
]
=
col
;
}
}
}
else
{
for
(
y
=
top
;
y
<
bottom
;
y
++
)
{
for
(
x
=
left
;
x
<
right
;
x
++
){
colorBuf
[
y
][
x
]
=
col
;
colorBuf
[
y
][
x
]
=
col
;
}
}
}
}
void
SkinStats
(
PixMapHandle
p
,
int
top
,
int
bottom
,
int
left
,
int
right
)
{
double
Y_sum
,
E_sum
,
S_sum
;
int
R
,
G
,
B
;
int
count
=
0
;
Y_sum
=
E_sum
=
S_sum
=
0
;
double
Y
,
E
,
S
;
UInt32
color
;
int
x
,
y
;
UInt32
*
baseAddr
;
for
(
y
=
top
;
y
<
bottom
;
y
++
)
{
baseAddr
=
(
UInt32
*
)(
GetPixBaseAddr
(
p
)
+
y
*
GetPixRowBytes
(
p
));
for
(
x
=
left
;
x
<
right
;
x
++
)
{
count
++
;
color
=
baseAddr
[
x
];
R
=
(
color
&
0x00FF0000
)
>>
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
<
bottom
;
y
++
)
{
baseAddr
=
(
UInt32
*
)(
GetPixBaseAddr
(
p
)
+
y
*
GetPixRowBytes
(
p
));
for
(
x
=
left
;
x
<
right
;
x
++
)
{
color
=
baseAddr
[
x
];
R
=
(
color
&
0x00FF0000
)
>>
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
;
}