-
Notifications
You must be signed in to change notification settings - Fork 0
/
faceweightedpixelsumfitness.cpp
65 lines (55 loc) · 1.95 KB
/
faceweightedpixelsumfitness.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include "faceweightedpixelsumfitness.h"
#include "facedetect.h"
#include <QPainter>
FaceWeightedPixelSumFitness::FaceWeightedPixelSumFitness(const QImage &image, int faceWeight)
: AbstractFitness( image )
, m_faceWeight( faceWeight )
{
doFaceDetection();
}
void FaceWeightedPixelSumFitness::doFaceDetection()
{
m_faces = detectFaces( target() );
m_faceMask = QImage( target().size(), QImage::Format_RGB32 );
m_faceMask.fill( 0 );
QPainter pm( &m_faceMask );
pm.setPen( Qt::NoPen );
pm.setBrush( QColor( 255, 255, 255 ) );
for( int i = 0; i < m_faces.count(); ++ i )
pm.drawEllipse( m_faces.at( i ) );
m_pixelWeights.resize( m_faceMask.height() );
for( int y = 0; y < m_faceMask.height(); ++ y )
{
m_pixelWeights[y] = new unsigned char[m_faceMask.width()];
for( int x = 0; x < m_faceMask.width(); ++ x )
{
m_pixelWeights[y][x] = qRed(m_faceMask.pixel(x, y)) > 0 ? 1 : 0;
}
}
}
float FaceWeightedPixelSumFitness::getFitness( const QImage &candidate ) const
{
float f = 0;
int w = target().width();
int h = target().height();
for( int y = 0; y < h; ++ y )
{
const uchar *targetLine = target().scanLine( y );
const uchar *candidateLine = candidate.scanLine( y );
const uchar *weights = m_pixelWeights[y];
// calculates the difference between pixels on the two images
for( int x = 0; x < w; ++ x )
{
float dB = (float)(*(targetLine++) - *(candidateLine++));
float dG = (float)(*(targetLine++) - *(candidateLine++));
float dR = (float)(*(targetLine++) - *(candidateLine++));
++targetLine; ++candidateLine;
// larger number is better. multiplies pixels detected as part of a face by faceWeight
// this gives a better weighting to face pixels and will accept candidates that have a better
// match for those areas
float pixelFitness = (dR * dR + dG * dG + dB * dB) * (float)(m_faceWeight * weights[x] + 1 );
f += pixelFitness;
}
}
return f;
}