caffe-face特征提取中五点对齐优化

Caffe-Face 特征提取中五点对齐优化

这里写图片描述

这里写图片描述

align.cpp:

#include <iostream>
#include <cmath>
#include <cstdio>
#include <memory.h>

using namespace std;

const double DST_5POINTS[10] = {30.2946, 65.5318, 48.0252, 33.5493, 62.7299, 51.6963, 51.5014, 71.7366, 92.3655, 92.2041};
double src[10] = {105.8306, 147.9323, 121.3533, 106.1169, 144.3622, 109.8005, 112.5533, 139.1172, 155.6359, 156.3451};

void printMat(double* M, int row, int col=0)
{
    if (col == 0) {
        for (int j = 0; j < row; ++j) {
            printf("%10.4f ", M[j]);
        }
        printf("\n[ Vector with size %d ]\n\n", row);       
    }
    else {
        for (int i = 0; i < row; ++i) {
            for (int j = 0; j < col; ++j) {
                printf("%10.4f ", M[i*col+j]);
            }
            printf("\n");
        }
        printf("[ Mat with size %dx%d ]\n\n", row, col);
    }


}

// src: source points: size=10 vector with shape (2, 5) 
// dst: dest points: size=10 vector with shape (2, 5)
// M: rotation matrix with shape (2, 3)
void getAffineMatrix(double* src_5pts, const double* dst_5pts, double* M)
{
    double src[10], dst[10];
    memcpy(src, src_5pts, sizeof(double)*10);
    memcpy(dst, dst_5pts, sizeof(double)*10);
    // initialization
    double ptmp[2];
    ptmp[0] = ptmp[1] = 0;
    for (int i = 0; i < 5; ++i) {
        ptmp[0] += src[i];
        ptmp[1] += src[5+i];
    }
    ptmp[0] /= 5;
    ptmp[1] /= 5;
    for (int i = 0; i < 5; ++i) {
        src[i] -= ptmp[0];
        src[5+i] -= ptmp[1];
        dst[i] -= ptmp[0];
        dst[5+i] -= ptmp[1];
    }
    // determine init angle
    double dst_x = (dst[3]+dst[4]-dst[0]-dst[1])/2, dst_y = (dst[8]+dst[9]-dst[5]-dst[6])/2;
    double src_x = (src[3]+src[4]-src[0]-src[1])/2, src_y = (src[8]+src[9]-src[5]-src[6])/2;
    double theta = atan2(dst_x, dst_y) - atan2(src_x, src_y);
    // determine init scale
    double scale = sqrt(pow(dst_x, 2) + pow(dst_y, 2)) / sqrt(pow(src_x, 2) + pow(src_y, 2));
    double pts1[10];
    double pts0[2];
    double _a = sin(theta), _b = cos(theta);
    pts0[0] = pts0[1] = 0;
    for (int i = 0; i < 5; ++i) {
        pts1[i] = scale*(src[i]*_b + src[i+5]*_a);
        pts1[i+5] = scale*(-src[i]*_a + src[i+5]*_b);
        pts0[0] += (dst[i] - pts1[i]);
        pts0[1] += (dst[i+5] - pts1[i+5]);
    }
    pts0[0] /= 5;
    pts0[1] /= 5;

    double sqloss = 0;
    for (int i = 0; i < 5; ++i) {
        sqloss += ((pts0[0]+pts1[i]-dst[i])*(pts0[0]+pts1[i]-dst[i])
                + (pts0[1]+pts1[i+5]-dst[i+5])*(pts0[1]+pts1[i+5]-dst[i+5]));
    }
    // optimization
    double square_sum = 0;
    for (int i = 0; i < 10; ++i) {
        square_sum += src[i]*src[i];
    }
    for (int t = 0; t < 200; ++t) {
        //cout << sqloss << endl;
        // determine angle
        _a = 0;
        _b = 0;
        for (int i = 0; i < 5; ++i) {
            _a += ((pts0[0]-dst[i])*src[i+5] - (pts0[1]-dst[i+5])*src[i]);
            _b += ((pts0[0]-dst[i])*src[i] + (pts0[1]-dst[i+5])*src[i+5]);
        }
        if (_b < 0) {
            _b = -_b;
            _a = -_a;
        }
        double _s = sqrt(_a*_a + _b*_b);
        _b /= _s;
        _a /= _s;

        for (int i = 0; i < 5; ++i) {
            pts1[i] = scale*(src[i]*_b + src[i+5]*_a);
            pts1[i+5] = scale*(-src[i]*_a + src[i+5]*_b);
        }

        // determine scale
        double _scale = 0;
        for (int i = 0; i < 5; ++i) {
            _scale += ((dst[i]-pts0[0])*pts1[i] + (dst[i+5]-pts0[1])*pts1[i+5]);
        }
        _scale /= (square_sum*scale);
        for (int i = 0; i < 10; ++i) {
            pts1[i] *= (_scale / scale);
        }
        scale = _scale;

        // determine pts0
        pts0[0] = pts0[1] = 0;
        for (int i = 0; i < 5; ++i) {
            pts0[0] += (dst[i] - pts1[i]);
            pts0[1] += (dst[i+5] - pts1[i+5]);
        }
        pts0[0] /= 5;
        pts0[1] /= 5;

        double _sqloss = 0;
        for (int i = 0; i < 5; ++i) {
            _sqloss += ((pts0[0]+pts1[i]-dst[i])*(pts0[0]+pts1[i]-dst[i])
                    + (pts0[1]+pts1[i+5]-dst[i+5])*(pts0[1]+pts1[i+5]-dst[i+5]));
        }
        if (abs(_sqloss - sqloss) < 1e-2) {
            break;
        }
        sqloss = _sqloss;
    }
    // generate affine matrix
    for (int i = 0; i < 5; ++i) {
        pts1[i] += (pts0[0] + ptmp[0]);
        pts1[i+5] += (pts0[1] + ptmp[1]);
    }
    // printMat(pts1, 2, 5);
    M[0] = _b*scale;
    M[1] = _a*scale;
    M[3] = -_a*scale;
    M[4] = _b*scale;
    M[2] = pts0[0] + ptmp[0] - scale*(ptmp[0]*_b + ptmp[1]*_a);
    M[5] = pts0[1] + ptmp[1] - scale*(-ptmp[0]*_a + ptmp[1]*_b);
}

int main()
{
    double M[6];
    for (int i = 0; i < 10000; ++i)
        getAffineMatrix(src, DST_5POINTS, M);
    printMat(M, 2, 3);
    return 0;
}

align.py:

import numpy as np
import time


def getAffineMatrix(src, dst):
    # initialization
    # determine init rotmat
    ptmp = np.mean(src, axis=0)
    src = src - ptmp
    dst = dst - ptmp
    theta = np.arctan2(*((dst[3]+dst[4])/2-(dst[0]+dst[1])/2)) - np.arctan2(*((src[3]+src[4])/2-(src[0]+src[1])/2))
    # determine scale
    scale = np.linalg.norm((dst[3]+dst[4])/2-(dst[0]+dst[1])/2) / np.linalg.norm((src[3]+src[4])/2-(src[0]+src[1])/2)
    pts1 = np.dot(src, scale*np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]]))
    pts0 = np.mean(dst-pts1, axis=0)
    sqloss = np.sum((pts1+pts0-dst)**2)
    # optimization
    square_sum = np.sum(src*src)
    for i in range(200):
        print sqloss
        # determine angle
        _a = np.sum((pts0-dst)*(src[:,::-1]*np.array([1.,-1.])))
        _b = np.sum((pts0-dst)*src)
        print _a, _b
        pts1 = np.dot(src, np.sign(_b)*scale/np.sqrt(_a**2+_b**2)*np.array([[_b,-_a],[_a,_b]]))
        # determine scale
        print pts1
        _scale = np.sum((dst-pts0)*pts1) / (square_sum*scale)
        pts1 = _scale / scale * pts1
        scale = _scale
        pts0 = np.mean(dst-pts1, axis=0)

        _sqloss = np.sum((pts1+pts0-dst)**2)
        if np.abs(_sqloss-sqloss) < 1e-2:
            break
        sqloss = _sqloss
    print 
    print pts1+pts0+ptmp
    rotmat = np.sign(_b)*scale/np.sqrt(_a**2+_b**2)*np.array([[_b,-_a],[_a,_b]])
    spts = pts0 - np.dot(ptmp, rotmat) + ptmp
    M = np.hstack([rotmat.T, spts.reshape((2,1))])
    return M


DST_5POINTS = np.array([30.2946, 65.5318, 48.0252, 33.5493, 62.7299, 51.6963, 51.5014, 71.7366, 92.3655, 92.2041]).reshape(2,5).T
src = np.array([105.8306, 147.9323, 121.3533, 106.1169, 144.3622, 109.8005, 112.5533, 139.1172, 155.6359, 156.3451]).reshape(2,5).T

tic = time.time()
M = getAffineMatrix(src, DST_5POINTS)
toc = time.time()
print toc - tic
print M
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sun-Eve

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值