精华内容
下载资源
问答
  • 人脸检测(一)

    万次阅读 2017-05-06 17:34:16
    例如,FDDB数据库就提交了很多出色的人脸检测算法,例如采用级联CNN网络的人脸检测方法:A Convolutioanal Neural Network Cascade,改进的faster rcnn做人脸检测:Face Detection using Deep Learning:An Improved...

    有天导师突然找我,让我搞一些关于人脸的应用,比如换个脸什么的……没办法那就先把人脸自动检测出来吧。人脸检测,即检测出图像中存在的人脸,并把它的位置准确地框出来。是人脸特征点检测、人脸识别的基础。可以谷歌Face Detection Benchmark寻找数据集和优秀论文,上thinkface论坛,搜集人脸检测数据集和方法。常用的人脸检测数据集,包括FDDB、AFLW、WIDER FACE等。随着近年来随着深度学习的快速发展,涌现出来很多优秀的人脸检测算法。
    例如,FDDB数据库就提交了很多出色的人脸检测算法,例如采用级联CNN网络的人脸检测方法:A Convolutioanal Neural Network Cascade,改进的faster rcnn做人脸检测:Face Detection using Deep Learning:An Improved Faster RCNN Approach,还有对小脸检测非常成功的Finding tiny faces等等,建议找个三篇左右认真研读就行了,也不需要去一一实现,没有太大意义。
    另外,像opencv、dlib、libfacedetect等也提供了人脸检测的接口。因为人脸检测是很基本的任务,所以很多公司都做了人脸检测的工作,而且做得很牛,例如face++。
    这里写图片描述

    下面仅介绍本人尝试并实现了的几种常见的人脸检测方法:

    1.单个CNN人脸检测方法
    2.级联CNN人脸检测方法
    3.OpenCV人脸检测方法
    4.Dlib人脸检测方法
    5.libfacedetect人脸检测方法
    6.Seetaface人脸检测方法


    1.单个CNN人脸检测方法

    该人脸检测方法的有点在于,思路简单,实现简单;缺点是速度较慢(在一块普通的gpu上对一副1000x600的图像进行多尺度检测也可能花上一两秒),检测效果还可以,但得到的人脸框不够准确。
    首先训练一个判断人脸非人脸的二分类器。例如采用卷积神经网络caffenet进行二分类,可以在imagenet数据集训练过的模型,利用自己的人脸数据集,进行微调。也可以自定义卷积网络进行训练,为了能检测到更小的人脸目标,我们一般采用小一点的卷积神经网络作为二分类模型,减小图像输入尺寸,加快预测速度。
    然后将训练好的人脸判断分类网络的全连接层改为卷积层,这样网络变成了全卷积网络,可以接受任意输入图像大小,图像经过全卷积网络将得到特征图,特征图上每一个“点”对应该位置映射到原图上的感受野区域属于人脸的概率,将属于人脸概率大于设定阈值的视为人脸候选框。
    图像上人脸的大小是变化的,为了适应这种变化,最暴力的办法就是使用图像金字塔的方式,将待检测的图像缩放到不同大小,以进行多尺度人脸检测。对多个尺度下检测出来的所有人脸候选框,做非极大值抑制NMS,得到最后人脸检测的结果。

    这里写图片描述

    这里提供用caffe实现该方法的数据集、模型文件和代码打包的 下载链接

    下面介绍用caffe实现该方法的具体过程。因为需要训练判断是否为人脸的CNN分类器,准备好正负训练样本,然后得到caffe训练所需的的数据集文件(由于采用的是48x48的网络,原始数据集归一化到了48x48)。
    这里写图片描述
    这里CNN采用的是DeepID卷积神经网络,网络结构如下,它的输入只有48x48大小,而采用AlexNet或CaffeNet网络会增加时间开销。
    这里写图片描述
    准备好网络模型文件train_val.prototxt和超参数配置文件solver.prototxt之后(下载链接中都有),开始训练,迭代10w次得到caffemodel。对测试集face_test文件夹中的图像进行测试,准备好测试用的deploy.prototxt。
    测试单张图像的python脚本face_test.py如下:

    # -*- coding: utf-8 -*-
    """
    Created on Fri Mar 10 23:02:06 2017
    @author: Administrator
    """
    import numpy as np
    import caffe
    size = 48
    image_file = 'C:/Users/Administrator/Desktop/caffe/data/face/face_test/0/253_faceimage07068.jpg'#测试图片路径
    model_def = 'C:/Users/Administrator/Desktop/caffe/models/face/deploy.prototxt'
    model_weights = 'C:/Users/Administrator/Desktop/caffe/models/face/_iter_10000.caffemodel'
    net = caffe.Net(model_def, model_weights, caffe.TEST)    
    
    # 加载均值文件  也可指定数值做相应的操作
    #mu = np.load('C:/Users/Administrator/Desktop/caffe/python/caffe/imagenet/ilsvrc_2012_mean.npy')  ###caffe 自带的文件
    #mu = mu.mean(1).mean(1)  # average over pixels to obtain the mean (BGR) pixel values
    
    transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) ##设定图片的shape格式(1,3,48,48),大小由deploy 文件指定
    #transformer.set_mean('data', mu)            # 每个通道减去均值
    # python读取的图片文件格式为H×W×K,需转化为K×H×W
    transformer.set_transpose('data', (2,0,1))  #改变维度的顺序,由原始图片(48,48,3)变为(3,48,48) 
    # python中将图片存储为[0, 1],而caffe中将图片存储为[0, 255],所以需要一个转换
    transformer.set_raw_scale('data', 255)      # 缩放到【0,255】之间
    transformer.set_channel_swap('data', (2,1,0))   #交换通道,将图片由RGB变为BGR
    #net.blobs['data'].reshape(1,3,size, size)  # 将输入图片格式转化为合适格式(与deploy文件相同)
    #上面这句,第一参数:图片数量 第二个参数 :通道数 第三个参数:图片高度 第四个参数:图片宽度
    
    image = caffe.io.load_image(image_file) #加载图片,始终是得到一副(h,w,3),rgb,0~1,float32的图像
    net.blobs['data'].data[...]  = transformer.preprocess('data', image) #用上面的transformer.preprocess来处理刚刚加载图片
    
    caffe.set_device(0)
    caffe.set_mode_gpu()
    output = net.forward()
    output_prob = output['prob'][0].argmax()  # 给出概率最高的是第几类,需要自己对应到我们约定的类别去
    print output_prob
    print output['prob'][0][0] #或print output['prob'][0,1]

    批量测试计算准确度的matlab脚本face_test.m如下:

    %注意:caffe中维度顺序为(N,C,H,W),而matcaffe中Blob维度顺序为(W,H,C,N),即完全相反
    %matlab加载图像为(h,w,c),得到的是rgb,而caffe使用的是bgr
    
    function test_face()
    clear;
    addpath('..');%添加上级目录搜索路径
    addpath('.');%添加当前目录搜索路径
    caffe.set_mode_gpu(); %设置gpu模式
    caffe.set_device(0); %gpu的id为0
    %caffe.set_mode_cpu();
    net_model = 'C:\Users\Administrator\Desktop\caffe\models\face\deploy.prototxt'; %网络模型deploy.prototxt
    net_weights = 'C:\Users\Administrator\Desktop\caffe\models\face\_iter_10000.caffemodel'; %训练好的模型文件
    %net_model = 'C:\Users\Administrator\Desktop\caffe\models\face2\deploy.prototxt'; %网络模型deploy.prototxt
    %net_weights = 'C:\Users\Administrator\Desktop\caffe\models\face2\_iter_100000.caffemodel'; %训练好的模型文件
    phase = 'test'; %不做训练,而是测试
    net = caffe.Net(net_model, net_weights, phase); %获取网络
    
    tic;
    error = 0;
    total = 0;
    %批量读取图像进行测试
    datadir = 'C:\Users\Administrator\Desktop\caffe\data\face\face_test\0';
    imagefiles = dir(datadir);
    for i = 3:length(imagefiles)
        im = imread(fullfile(datadir,imagefiles(i).name));
        [input_data,flag] = prepare_image(im); %图像数据预处理
        if flag ~= 1
            continue;
        end
        input_data ={input_data};
        net.forward(input_data); %做前向传播
    
        scores = net.blobs('prob').get_data();
    
        [best_score,best] = max(scores);
    %     fprintf('*****%.3f %d %d\n',best_score,best - 1,classid(i-2));
        best = best - 1; %matlab中从1开始,减1变成从0开始
        if best ~= 0
            error = error + 1;
            fprintf('-----error: %d\n',error);
            errorfile = ['error\' imagefiles(i).name];
            %imwrite(im,errorfile);
        end
        total = total + 1;
    end
    datadir_1 = 'C:\Users\Administrator\Desktop\caffe\data\face\face_test\1';
    imagefiles_1 = dir(datadir_1);
    for i = 3:length(imagefiles_1)
        im_1 = imread(fullfile(datadir_1,imagefiles_1(i).name));
        [input_data_1,flag] = prepare_image(im_1); %图像数据预处理
        if flag ~= 1
            continue;
        end
        input_data_1 = {input_data_1};
        net.forward(input_data_1); %做前向传播
    
        scores_1 = net.blobs('prob').get_data();
    
        [best_score_1,best_1] = max(scores_1);
    %     fprintf('*****%.3f %d %d\n',best_score,best - 1,classid(i-2));
        best_1 = best_1 - 1; %matlab中从1开始,减1变成从0开始
        if best_1 ~= 1
            error = error + 1;
            fprintf('error: %d-----\n',error);
            errorfile = ['face_error\' imagefiles_1(i).name];
            %imwrite(im,errorfile);
        end
        total = total + 1;
    end
    total_time = toc;
    %打印到屏幕上
    fprintf('total_time: %.3f s\n',total_time);
    fprintf('aver_time: %.3f s\n',total_time/total);
    fprintf('error/total: %d/%d\n',error,total);
    fprintf('accurary: %.4f\n',1.0 - (error*1.0)/total);
    %disp(['error/total: ',num2str(error),'/',num2str(length(imagefiles)-2)]);
    end
    
    function [im_data,flag] = prepare_image(im)
    %d = load('../+caffe/imagenet/ilsvrc_2012_mean.mat');
    %mean_data = d.mean_data;
    
    %resize to 227 x 227
    im_data = [];
    im = imresize(im,[227 227],'bilinear');
    %im = imresize(im,[48 48],'bilinear');
    [h,w,c] = size(im);
    if c ~= 3
        flag = 0;
        return;
    end
    flag = 1;
    %caffe的blob顺序是[w h c num]
    %matlab:[h w c] rgb -> caffe:[w h c] bgr
    im_data = im(:,:,[3,2,1]); %rgb -> bgr
    im_data = permute(im_data,[2,1,3]); %[h w c] -> [w h c]
    [w,h,~] = size(im_data);
    %ImageNet数据集的均值具有统计规律,这里可以直接拿来使用
    mean_data(:,:,1) = ones(w,h) .* 104; %b
    mean_data(:,:,2) = ones(w,h) .* 117; %g
    mean_data(:,:,3) = ones(w,h) .* 123; %r
    
    im_data = single(im_data);
    %im_data = im_data - single(mean_data); %因为训练集和测试集都没有做去均值,所以这里也不做(如果只是这里做了去均值效果会变差)
    end

    在测试集上进行批量测试,准确率达到了98%。
    这里写图片描述
    为了利用CNN分类器来检测人脸,需要将CNN网络中的全连接层替换为卷积层得到全卷积网络,修改好的全卷积网络deploy_full_conv.prototxt内容如下:

    name: "face_full_conv_net"
    layer {
      name: "data"
      type: "Input"
      top: "data"
      input_param { shape: { dim: 1 dim: 3 dim: 48 dim: 48 } }
    }
    layer {
      name: "conv1"
      type: "Convolution"
      bottom: "data"
      top: "conv1"
      convolution_param {
        num_output: 20
        kernel_size: 3
        stride: 1
        pad: 1
      }
    }
    layer {
      name: "relu1"
      type: "ReLU"
      bottom: "conv1"
      top: "conv1"
    }
    layer {
      name: "norm1"
      type: "LRN"
      bottom: "conv1"
      top: "conv1"
      lrn_param {
        local_size: 5
        alpha: 0.0001
        beta: 0.75
      }
    }
    layer {
      name: "pool1"
      type:  "Pooling"
      bottom: "conv1"
      top: "pool1"
      pooling_param {
        pool: MAX
        kernel_size: 2
        stride: 2
      }
    }
    layer {
      name: "conv2"
      type: "Convolution"
      bottom: "pool1"
      top: "conv2"
      convolution_param {
        num_output: 40
        kernel_size: 3
        pad: 1
      }
    }
    layer {
      name: "relu2"
      type: "ReLU"
      bottom: "conv2"
      top: "conv2"
    }
    layer {
      name: "norm2"
      type: "LRN"
      bottom: "conv2"
      top: "conv2"
      lrn_param {
        local_size: 5
        alpha: 0.0001
        beta: 0.75
      }
    }
    layer {
      name: "pool2"
      type: "Pooling"
      bottom: "conv2"
      top: "pool2"
      pooling_param {
        pool: MAX
        kernel_size: 2
        stride: 2
      }
    }
    layer {
      name: "conv3"
      type: "Convolution"
      bottom: "pool2"
      top: "conv3"
      convolution_param {
        num_output: 60
        kernel_size: 3
        pad: 1
      }
    }
    layer {
      name: "relu3"
      type: "ReLU"
      bottom: "conv3"
      top: "conv3"
    }
    layer {
      name: "norm3"
      type: "LRN"
      bottom: "conv3"
      top: "conv3"
      lrn_param {
        local_size: 5
        alpha: 0.0001
        beta: 0.75
      }
    }
    layer {
      name: "pool3"
      type: "Pooling"
      bottom: "conv3"
      top: "pool3"
      pooling_param {
        pool: MAX
        kernel_size: 2
        stride: 2
      }
    }
    layer {
      name: "conv4"
      type: "Convolution"
      bottom: "pool3"
      top: "conv4"
      convolution_param {
        num_output: 80
        kernel_size: 3
        pad: 1
      }
    }
    layer {
      name: "relu4"
      type: "ReLU"
      bottom: "conv4"
      top: "conv4"
    }
    layer {
      name: "norm4"
      type: "LRN"
      bottom: "conv4"
      top: "conv4"
      lrn_param {
        local_size: 5
        alpha: 0.0001
        beta: 0.75
      }
    }
    layer {
      name: "pool4"
      type: "Pooling"
      bottom: "conv4"
      top: "pool4"
      pooling_param {
        pool: MAX
        kernel_size: 2
        stride: 2
      }
    }
    #修改为卷积层
    layer {
      name: "fc5-conv" ### fc5
      type: "Convolution" ### InnerProduct
      bottom: "pool4"
      top: "fc5-conv" ### fc5
      #inner_product_param {
       # num_output: 160
      #}
      convolution_param {
        num_output: 160
        kernel_size: 3
      }
    }
    layer {
      name: "relu5"
      type: "ReLU"
      bottom: "fc5-conv"
      top: "fc5-conv"
    }
    layer {
      name: "drop5"
      type:  "Dropout"
      bottom: "fc5-conv"
      top: "fc5-conv"
      dropout_param {
        dropout_ratio: 0.5
      }
    }
    #修改为卷积层
    layer {
      name: "fc6-conv" ### fc6
      type:  "Convolution" ### InnerProduct
      bottom: "fc5-conv"
      top: "fc6-conv"
      #inner_product_param {
       # num_output: 2
      #}
      convolution_param {
        num_output: 2
        kernel_size: 1
      }
    }
    layer {
      name: "prob"
      type: "Softmax"
      bottom: "fc6-conv"
      top: "prob"
    }

    还需要将训练好的_iter_100000.caffemodel模型文件也转化为全卷积的,得到的_iter_100000_full_conv.caffemodel,转换脚本convert_full_conv.py如下:

    # -*- coding: utf-8 -*-
    """
    Created on Fri Mar 10 21:14:09 2017
    @author: Administrator
    """
    ###首先需要手动将deploy.prototxt修改成全卷积的deploy_full_conv.prorotxt,特别要注意全连接层修改成卷积层的细节
    ###将训练好的分类模型caffemodel转换成可以接受任意输入大小,最后输出特征图的全卷积模型caffemodel
    
    import numpy as np
    import caffe
    
    model_def = 'C:/Users/Administrator/Desktop/caffe/models/face/deploy.prototxt'
    model_weights = 'C:/Users/Administrator/Desktop/caffe/models/face/_iter_100000.caffemodel'
    net = caffe.Net(model_def,
                    model_weights,
                    caffe.TEST)
    params = ['fc5', 'fc6']
    # fc_params = {name: (weights, biases)}
    fc_params = {pr: (net.params[pr][0].data, net.params[pr][1].data) for pr in params}
    for fc in params:
        print '{} weights are {} dimensional and biases are {} dimensional'.format(fc, fc_params[fc][0].shape, fc_params[fc][1].shape)
    
    # Load the fully convolutional network to transplant the parameters.
    net_full_conv = caffe.Net('./deploy_full_conv.prototxt', 
                              './_iter_100000.caffemodel',
                              caffe.TEST)
    params_full_conv = ['fc5-conv', 'fc6-conv']
    # conv_params = {name: (weights, biases)}
    conv_params = {pr: (net_full_conv.params[pr][0].data, net_full_conv.params[pr][1].data) for pr in params_full_conv}
    for conv in params_full_conv:
        print '{} weights are {} dimensional and biases are {} dimensional'.format(conv, conv_params[conv][0].shape, conv_params[conv][1].shape)
    
    for pr, pr_conv in zip(params, params_full_conv):
        conv_params[pr_conv][0].flat = fc_params[pr][0].flat  # flat unrolls the arrays
        conv_params[pr_conv][1][...] = fc_params[pr][1]
    
    net_full_conv.save('./_iter_100000_full_conv.caffemodel')
    print 'success'

    最后,就可以用deploy_full_conv.prototxt和_iter_100000_full_conv.caffemodel对任意输入尺寸的图像进行人脸检测了。对单张图像进行人脸检测的python脚本face_detect如下:

    # -*- coding: utf-8 -*-
    import numpy as np
    import cv2 #需要安装opencv,然后将opencv安装目录下build\python\2.7\x64\cv2.pyd拷贝到python的安装目录下Anaconda2\Lib\site-packages文件夹下
    from operator import itemgetter
    import time
    import caffe
    caffe.set_device(0)
    caffe.set_mode_gpu()
    
    def IoU(rect_1, rect_2):
        '''
        :param rect_1: list in format [x11, y11, x12, y12, confidence]
        :param rect_2:  list in format [x21, y21, x22, y22, confidence]
        :return:    returns IoU ratio (intersection over union) of two rectangles
        '''
        x11 = rect_1[0]    # first rectangle top left x
        y11 = rect_1[1]    # first rectangle top left y
        x12 = rect_1[2]    # first rectangle bottom right x
        y12 = rect_1[3]    # first rectangle bottom right y
        x21 = rect_2[0]    # second rectangle top left x
        y21 = rect_2[1]    # second rectangle top left y
        x22 = rect_2[2]    # second rectangle bottom right x
        y22 = rect_2[3]    # second rectangle bottom right y
        x_overlap = max(0, min(x12,x22) -max(x11,x21))
        y_overlap = max(0, min(y12,y22) -max(y11,y21))
        intersection = x_overlap * y_overlap
        union = (x12-x11) * (y12-y11) + (x22-x21) * (y22-y21) - intersection
        return float(intersection) / union
    
    def IoM(rect_1, rect_2):
        '''
        :param rect_1: list in format [x11, y11, x12, y12, confidence]
        :param rect_2:  list in format [x21, y21, x22, y22, confidence]
        :return:    returns IoM ratio (intersection over min-area) of two rectangles
        '''
        x11 = rect_1[0]    # first rectangle top left x
        y11 = rect_1[1]    # first rectangle top left y
        x12 = rect_1[2]    # first rectangle bottom right x
        y12 = rect_1[3]    # first rectangle bottom right y
        x21 = rect_2[0]    # second rectangle top left x
        y21 = rect_2[1]    # second rectangle top left y
        x22 = rect_2[2]    # second rectangle bottom right x
        y22 = rect_2[3]    # second rectangle bottom right y
        x_overlap = max(0, min(x12,x22) -max(x11,x21))
        y_overlap = max(0, min(y12,y22) -max(y11,y21))
        intersection = x_overlap * y_overlap
        rect1_area = (y12 - y11) * (x12 - x11)
        rect2_area = (y22 - y21) * (x22 - x21)
        min_area = min(rect1_area, rect2_area)
        return float(intersection) / min_area
    
    def NMS(rectangles,threshold=0.3):
        '''
        :param rectangles:  list of rectangles, which are lists in format [x11, y11, x12, y12, confidence]
        :return:    list of rectangles after local NMS
        '''
        rectangles = sorted(rectangles, key=itemgetter(4), reverse=True) #按照confidence降序排列
        result_rectangles = rectangles[:]  # list to return
    
        '''
        while not result_rectangles == []:
            rect = result_rectangles[0]
            for index in range(1,len(result_rectangles)):
                iou = IoU(rect,result_rectangles[index])
                if
        '''
        number_of_rects = len(result_rectangles)
        #threshold = 0.3     # threshold of IoU of two rectangles
        cur_rect = 0
        while cur_rect < number_of_rects - 1:     # start from first element to second last element
            rects_to_compare = number_of_rects - cur_rect - 1      # elements after current element to compare
            cur_rect_to_compare = cur_rect + 1    # start comparing with element after current
            while rects_to_compare > 0:      # while there is at least one element after current to compare
                if (IoU(result_rectangles[cur_rect], result_rectangles[cur_rect_to_compare]) >= threshold or IoM(result_rectangles[cur_rect], result_rectangles[cur_rect_to_compare]) >= 0.3):
                    del result_rectangles[cur_rect_to_compare]      # delete the rectangle
                    number_of_rects -= 1
                else:
                    cur_rect_to_compare += 1    # skip to next rectangle
                rects_to_compare -= 1
            cur_rect += 1   # finished comparing for current rectangle
    
        return result_rectangles
    
    def face_detection(imgFile) :
        #model_def = 'C:/Users/Administrator/Desktop/caffe/models/face/deploy_full_conv.prototxt' 
        #model_weights = 'C:/Users/Administrator/Desktop/caffe/models/face/_iter_10000_full_conv.caffemodel'
        model_def = 'C:/Users/Administrator/Desktop/caffe/models/face2/deploy_full_conv.prototxt' 
        model_weights = 'C:/Users/Administrator/Desktop/caffe/models/face2/_iter_100000_full_conv.caffemodel'
        net_full_conv = caffe.Net(model_def,
                                  model_weights,
                                  caffe.TEST)
    
        mu = np.load('C:/Users/Administrator/Desktop/caffe/python/caffe/imagenet/ilsvrc_2012_mean.npy')
        mu = mu.mean(1).mean(1)  # average over pixels to obtain the mean (BGR) pixel values
        #print 'mean-subtracted values:' , zip('BGR', mu)
    
        start_time = time.time()
        scales = [] #尺度变换和尺度变换因子
        factor = 0.793700526
    
        img = cv2.imread(imgFile) #opencv读取的图像为(h,w,c),bgr,caffe的blob维度为(n,c,h,w),使用的也是rgb
        print img.shape
    
        largest = min(2, 4000/max(img.shape[0:2])) #4000是人脸检测的经验值
        scale = largest
        minD = largest*min(img.shape[0:2])
        while minD >= 48:  #网络的输入是227x227??? #多尺度变换 
            scales.append(scale) #添加当前尺度
            scale *= factor #乘以尺度变换因子
            minD *= factor #得到新的尺度
    
        true_boxes = []
    
        for scale in scales:
            scale_img = cv2.resize(img,((int(img.shape[1] * scale), int(img.shape[0] * scale)))) #将图像缩放到各尺度
            cv2.imwrite('C:/Users/Administrator/Desktop/caffe/scale_img.jpg',scale_img)
            im = caffe.io.load_image('C:/Users/Administrator/Desktop/caffe/scale_img.jpg') #利用caffe的io接口加载图像,始终是得到一副(h,w,3),rgb,0~1,float32的图像
    
            net_full_conv.blobs['data'].reshape(1,3,scale_img.shape[0],scale_img.shape[1]) #重新设置网络data层Blob维度为:1,3,height,width            
            transformer = caffe.io.Transformer({'data': net_full_conv.blobs['data'].data.shape}) #为data层创建transformer
            transformer.set_transpose('data', (2,0,1)) #(h,w,3)->(3,h,w)
            #transformer.set_mean('data', mu) #设置均值,由于训练集没有去均值,这里也不去均值
            transformer.set_raw_scale('data', 255.0) #rescale from [0,1] to [0,255]
            transformer.set_channel_swap('data', (2,1,0)) #RGB -> BGR
    
            net_full_conv.blobs['data'].data[...] = transformer.preprocess('data', im)
            out = net_full_conv.forward()
    
            print out['prob'][0,0].shape #输出层prob结果,行x列
            #print out['prob'][0].argmax(axis=0)
            featureMap = out['prob'][0,0] #out['prob'][0][0]属于人脸的概率特征图
            stride = 16 #特征图感受野大小
            cellSize = 48 #网络输入尺寸
            thresh = 0.95
            for (y,x),prob in np.ndenumerate(featureMap):
                if prob > thresh :
                    true_boxes.append([float(x*stride)/scale,
                                        float(y*stride)/scale,
                                        float(x*stride + cellSize - 1)/scale,
                                        float(y*stride + cellSize - 1)/scale,
                                        prob])
    
        true_boxes = NMS(true_boxes,0.2) #非极大值抑制
        for true_box in true_boxes:
            (x1, y1, x2, y2) = true_box[0:4] #取出人脸框的坐标
            cv2.rectangle(img, (int(x1),int(y1)), (int(x2),int(y2)), (0,255,0)) #画人脸框
    
        end_time = time.time()
        print (end_time-start_time)*1000,'ms'
    
        cv2.imwrite('output.jpg',img)
        cv2.namedWindow('test win')  
        cv2.imshow('test win', img)          
        cv2.waitKey(0)  
        cv2.destroyWindow('test win')
    
    if __name__ == "__main__":
        imgFile = 'C:/Users/Administrator/Desktop/caffe/matlab/demo/1.jpg'
        face_detection(imgFile)
    展开全文
  • 还是有点城府的好。

    人还是要有点城府的好。

    展开全文
  • 做人的道理

    2015-06-01 23:42:00
    刚刚回来,喝酒喝的有点多,不过我仍然打开电脑,想写点什么。 我和团队的所有成员在一家农家饭庄吃饭,庆祝我们的项目第一阶段通过验收。其实这已经不是我第一次带团队了,已经没有了第一次带团队时的担心和...

    刚刚回来,喝酒喝的有点多,不过我仍然打开电脑,想写点什么。

    我和团队的所有成员在一家农家饭庄吃饭,庆祝我们的项目第一阶段通过验收。其实这已经不是我第一次带团队了,已经没有了第一次带团队时的担心和种种。虽然始终要承担一些风险,不过经过所有人的共同努力,我们的目标比较准时的实现了,实际上比预期的时间还要早一点完成预期的任务。我们第一次大规模的使用D语言完成功能仿真,虽然只是一种工具的选择,但是在没有任何选项项目使用经验的情况下,这已经是一种“创举”,不仅如此,我们还对原本使用C++和Ada完成的中间层做了大量的重构,整个代码基更干净,核心由Ada运行时来支持,中间层尽可能重构,上面仿真完全使用D语言,整个栈结构更清晰。

    仿真的结果和实际上芯片差距相比以前做的项目大大的缩短了,这也是为什么比预期早完成的原因。

    我代项目和我做人是相比规则。我始终记得我爸和我说过的那句话:“你自己不愿意的做的事情就不要强求别人去做,否则就算别人做了,最终的结果也不是你想要的”。所以坚持做到以下三点:

    1。不加班,因为每个人除了工作,还有工作之外的空间才能生活。生活中只有工作,在我看来是一种残废。

    2。如果真的加班,按工资的3倍付加班费。

    3。我对于人员的薪资安排计算的是时薪。

    4。我不是老板,我也是一个打工的,所以我和队员之间首先谈钱,其实再谈个人之间的友谊和情义。因为我知道每一个工作的首要目标是为了生活。我极看不起那些以其它理由变向压榨队员的老板。什么学习的机会,什么结识高手的机会,我认为人都是平等的。因为每一个拿着不一样的工资,剩下的就是平等。工资本就不一样,还要压榨简直是没有良心。

    好了,带团队和做人是一个道理。

    转载于:https://my.oschina.net/SevenxAda/blog/423660

    展开全文
  • 重新做人

    2021-10-13 18:43:40
    鸽了好多天没写 对GUI编程 有点抵触 直接进入下一章吧 纪念一下再次开始 2021.10.13 自律的痛苦轻如鸿毛 悔恨的痛苦重于泰山 即使再小的帆也能远航

    鸽了好多天没写 对GUI编程 有点抵触  直接进入下一章吧 纪念一下再次开始 2021.10.13

    自律的痛苦轻如鸿毛 悔恨的痛苦重于泰山 即使再小的帆也能远航

    展开全文
  • 读书笔记—做事坚定,做人柔软

    千次阅读 2018-11-05 12:18:29
    做事坚定,做人柔软作者:丁菱娟自序:做事坚定,做人柔软这一路走来,我非常清楚,女性要在男性为主的职场中脱颖而出,无论在专业与态度上都必须要更努力才能得到他人的认同。既要坚守立场,又要不得罪人;既要会...
  • 翻看以前的博客,莫名的嫌弃,感觉有点low,不知道是成长了还是以前写的确实很糟糕,心里明白两种原因都有。从开始着手web到现在,16年的7月到现在,其实算起来勉勉强强可以说是两年了吧。嗯,现在日常开发是没有啥...
  • 这几天连续发了几篇关于历史的闲聊台湾原住民的由来-历史隐藏的枭雄关于做人的闲聊 没兴趣的可以忽略,和本文继承关系不大。 有人反馈说不太喜欢这几天的风格,离现实有点远,而且...
  • 你有什么理由不努力 ...最近在健身房中健身发现一个现象,去健身房的人可以分为两种。...所以做人要做一个有梦想的人,并且是向这梦想去努力的人!虽然梦想不一定实现,但是万一梦想实现了呢?
  • 然后会输出一个结果告诉我们这张图片是数字几,这样就做到了物体的识别 同样地,我们可以把0~9的数字图片换成其他,例如猫狗,那我们就可以训练得到区分猫还是狗的神经网络。 import tensorflow as tf (train_...
  • 做人

    2008-10-14 23:15:00
    在生活中常听说这么一句话:做人难,难做人,做男人更难! 由于这学期的课不怎么的多,碰巧学校里面有个部门招兼职,我去应聘。可能是报的人太多,老师告诉我们说先试用一个月。这也是在我意料中的事,自己刚开始干的...
  • 低调做人,踏实做事

    千次阅读 热门讨论 2014-10-28 13:29:11
    第二,辛星教程的制作还是有点麻烦,因为这种独特的写作风格,就注定了我在写之前要整合大量的资料,这需要浪费不少的时间和精力,而它要追求更加系统更加完善,就更需要在这方面投入了,究竟这点值不值呢?...
  • 做人做事系列必读

    万次阅读 2017-06-25 17:24:56
    做人做事系列必读     做人做事——好方法 前言 这是一本可以改变你人生命运的书。如果你的人生事业屡遭挫折,自己又不知道障碍在哪里,你将从本书中获得答案;如果你目前正值春风得意,好运连连,那么书中的方法...
  • 低调做人,是不要太招摇,不要有点小本事就拿出来显摆,不要有事没事就往领导跟前凑然后做出一副领导面前红人的模样,什么事情自己心中都要有数,要清楚,自己有本事慢慢拿出来用,在别人最需要的时候拿出来用,乐于...
  • 题记:这一段把大部分时间用在了修身养性上,做人是做事的前提,真正的大家也必是做人的典范,纵观历史上能流传千古的人,无不是做人的成功者。这几天在看《低调做人、高调做事》一书,摘抄了其中的一些精彩语句,与...
  • 做站要先做人

    2011-11-21 11:36:19
    ​想到这些,心里有点久违的喜悦甚至毫不夸张的说有点眼眶湿润!的确,如果你真的默默的付出了,而突然某天得到回报了,这种喜悦我想别人无法与你分享!​​  回到家中迅速打开电脑,帮客户制作了广告图片,放到...
  • 但亦有释典说:人本是人,不需要用尽心思去做人;世本是世,无庸专心去在社会上处世。世界上翻天覆地本与我们非亲非故,届时也是惹个“世界上本无事,庸人自扰之”的名字别号罢。  闲磕牙柳林莫论风声,闲磕牙...
  • 做人、做事、做学问

    千次阅读 热门讨论 2009-07-26 14:37:00
    做人、做事、做学问——再谈裘老名言给我们的启迪
  • 这个暑假给自己立的小目标之一就是用树莓派做下人脸检测和识别,就是想看看效果咋样,可惜没有录屏,然后就简单的拍了几张人眼识别和微笑识别的照片,感觉这后期做的有点糙啊,有些惭愧,以后做事还是要做全面的。...
  • 1. 前言前些日子看到厦门大学教授举报校长一事,并没有想到此事会和我有什么关系,所以,也没有仔细去看到底是谁在做这个事情,是什么样的关联。...2. 抄袭还是造假这个事件从开始到现在已经将近一个月了,期间,谢博
  • 大公司里学做人,小公司里学做事

    千次阅读 2013-09-27 13:27:56
    以前,公司都愿意找能力强、资格老的人来做研发,有点个人英雄主义在里面。一个优秀能干的员工能给公司带来很大的利益。 但是,凡事都有双面性。 现在这个社会,人才流动很快。能力强的、聪明的人,虽说给公司...
  • 3,做任何一件事情都要有点规划或者计划,比如做一个任务前,不能随便给评估时间,而是说要思考下给答复,思考差不多时可以在纸上写出来具体步骤,  每个步骤需要理清 思路,并考虑好技术轮廓,等列清楚后再看...
  • 1.不知道自己不知道 假自信、过度承诺、满口我能行没问题、看不起其他...有点心虚、虚心学习、偷偷努力、羡慕牛人 3.知道自己知道 自信、比较客官、真正承诺、有点自我 4.不知道自己知道 开放、主动、好学、谦虚
  • 作为一个程序员,一直就是写代码改bug,但是最近发现做人方面也需要提高,难道要当一辈子程序员? 最近感觉到自己情商与那些情商高的人相比实在是低的可怜,好像属于那种边缘形人格? 但是我知道我自己性格向善的...
  • 1、这段时间我是不是有点太张扬了,其实幸福感来源于自身的感觉,自己的幸福没有必要去表现出来,很多时候自己知道就可以了,做人做事还是应该低调的,这样不容易受到别人的嫉妒。 2、正如曾仕强老师所说的,中国人...
  • 做人的道理(有图)

    千次阅读 2009-12-02 13:45:00
    ★最好能够有点男欢女爱,呵呵… ★要保持高度的自信心 ★要记住女士优先 ★偶尔放纵自己一下 ] ★不做违法犯罪的事 ★不要狗拿耗子多管闲事 ...
  • 做人实用心理学

    千次阅读 2012-10-22 23:06:49
    14、【心理技巧:你先说好消息还是坏消息?】你有一个大的好消息和一个小的坏消息,应该一起说。这样坏消息带来的痛苦会被好消息带来的快乐所冲淡,负面效应小得多。你有一个大的坏消息和一个小的好消息,应该分开说...
  •  2011.7.14——2012.3.9虽然只有短短的八个月,但是这毕竟是我人生呆的第一家公司,在这里我学会了很多东西,怎么样做事,怎么样做人,认识了我的很优秀的导师和领导,还认识了N多一起走进这家公司的兄弟姐妹。...
  • 原文地址:《做人最大的无知,是错把平台当本事(深度好文)》 原博主博客地址:https://blog.csdn.net/qq21497936 原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062 本文章博客地址:...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,240
精华内容 4,496
关键字:

做人还是有点