人脸关键点检测

http://blog.csdn.net/qingnianzhi/article/details/46912383#comments

先上效果图,然后贴代码。依赖库主要有opencv、Lasagne、nolearn

这幅图是训练用的数据库图片。数据库地址https://www.kaggle.com/c/facial-keypoints-detection 图片保存在csv文件里。


这幅图是训练之后检测的结果,效果还不错,不过对于侧脸的检测可以发现效果相对差一些,少部分图像会出现较大偏差。不过这个检测的数据库图片质量真是不怎么好。

[python]  view plain  copy
  1. # coding:utf-8  
  2. import os  
  3. import cv2  
  4. import numpy as np  
  5. from pandas.io.parsers import read_csv  
  6. from sklearn.utils import shuffle  
  7. from lasagne import layers  
  8. from lasagne.updates import nesterov_momentum  
  9. from nolearn.lasagne import NeuralNet  
  10. import theano.tensor as T  
  11.   
  12. def load():  
  13.     df = read_csv(os.path.expanduser(<span style="font-family: Arial, Helvetica, sans-serif;">training.csv</span><span style="font-family: Arial, Helvetica, sans-serif;">))  # load pandas dataframe</span>  
  14.     df['Image'] = df['Image'].apply(lambda im: np.fromstring(im, sep=' '))  
  15.     print(df.count())  # prints the number of values for each column  
  16.     df = df.dropna()  # drop all rows that have missing values in them  
  17.     X = np.vstack(df['Image'].values) / 255.  # scale pixel values to [0, 1]  
  18.     X = X.astype(np.float32)  
  19.     y = df[df.columns[:-1]].values  
  20.     y = ( y - 48 ) / 48.  # scale target coordinates to [-1, 1]  
  21.     X, y = shuffle(X, y, random_state=42)  # shuffle train data  
  22.     y = y.astype(np.float32)  
  23.     return X, y  
  24.   
  25.   
  26. def load_testdata():  
  27.     df = read_csv(os.path.expanduser('test.csv'))  # load pandas dataframe  
  28.     df['Image'] = df['Image'].apply(lambda im: np.fromstring(im, sep=' '))  
  29.     X = np.vstack(df['Image'].values)   
  30.     X = X.astype(np.float32)  
  31.     X = X/255.  
  32.     return X  
  33.     ''''' 
  34.     for i in range(len(X)): 
  35.         img = X[i] 
  36.         img = img.reshape(96,96) 
  37.         add = './test_data/'+str(i)+'.Bmp' 
  38.         cv2.imwrite(add,img) 
  39.     '''  
  40. net1 = NeuralNet(  
  41.     layers=[  # three layers: one hidden layer  
  42.         ('input', layers.InputLayer),  
  43.         ('hidden', layers.DenseLayer),  
  44.         ('output', layers.DenseLayer),  
  45.         ],  
  46.     # layer parameters:  
  47.     input_shape=(None9216),  # 96x96 input pixels per batch  
  48.     hidden_num_units=100,  # number of units in hidden layer  
  49.     output_nonlinearity=None,  # output layer uses identity function  
  50.     output_num_units=30,  # 30 target values  
  51.   
  52.     # optimization method:  
  53.     update=nesterov_momentum,     
  54.     update_learning_rate=0.01,  
  55.     update_momentum=0.9,  
  56.   
  57.     regression=True,  # flag to indicate we're dealing with regression problem 回归问题,而不是分类  
  58.     max_epochs=400,  # we want to train this many epochs  
  59.     verbose=1,  
  60.     )  
  61.   
  62. net2 = NeuralNet(  
  63.     layers=[  
  64.         ('input', layers.InputLayer),  
  65.         ('conv1', layers.Conv2DLayer),  
  66.         ('pool1', layers.MaxPool2DLayer),  
  67.         ('dropout1', layers.DropoutLayer),#  
  68.         ('conv2', layers.Conv2DLayer),  
  69.         ('pool2', layers.MaxPool2DLayer),  
  70.         ('dropout2', layers.DropoutLayer),#  
  71.         ('conv3', layers.Conv2DLayer),  
  72.         ('pool3', layers.MaxPool2DLayer),  
  73.         ('dropout3', layers.DropoutLayer),#  
  74.         ('hidden4', layers.DenseLayer),  
  75.         ('dropout4', layers.DropoutLayer),#  
  76.         ('hidden5', layers.DenseLayer),  
  77.         ('output', layers.DenseLayer),  
  78.         ],  
  79.     input_shape=(None19696),  
  80.     conv1_num_filters=32, conv1_filter_size=(33), pool1_pool_size=(22),  
  81.     conv2_num_filters=64, conv2_filter_size=(33), pool2_pool_size=(22),  
  82.     conv3_num_filters=128, conv3_filter_size=(33), pool3_pool_size=(22),  
  83.     hidden4_num_units=500, hidden5_num_units=500,  
  84.     dropout1_p=0.1,dropout2_p=0.2,dropout3_p=0.2,dropout4_p=0.5,  
  85.     output_num_units=30, output_nonlinearity=None,  
  86.   
  87.     update_learning_rate=0.01,  
  88.     update_momentum=0.9,  
  89.   
  90.     regression=True,  
  91.     max_epochs=200,  
  92.     verbose=1,  
  93.     )  
  94.   
  95. net3 = NeuralNet(  
  96. # three layers: one hidden layer  
  97. layers=[  
  98. ('input', layers.InputLayer),  
  99. ('h1', layers.DenseLayer),  
  100. ('h2', layers.DenseLayer),  
  101. ('output', layers.DenseLayer),  
  102. ],# layer parameters:# variable batch size.  
  103. input_shape=(None9216), # 96x96 input pixels per batch  
  104. h1_num_units = 300# number of units in hidden layer  
  105. h1_nonlinearity = T.tanh,  
  106.   
  107. h2_num_units = 100,  
  108. h2_nonlinearity = None# rectify,  
  109. output_nonlinearity=T.tanh,  
  110. # None if output layer wants to use identity function  
  111. output_num_units=30# 30 target values# optimization method:  
  112. update=nesterov_momentum,  
  113. update_learning_rate=0.01,  
  114. update_momentum=0.9,regression = True# flag to indicate we're dealing with regression problem  
  115. max_epochs = 1000# we want to train this many epochs  
  116. eval_size = 0.1,  
  117. verbose=1  
  118. )  
  119.   
  120.   
  121. def train_mlp():  
  122.     x , y = load()  
  123.     net1.load_params_from('face_weight_mlp')  
  124.     net1.fit(x, y)  
  125.     net1.save_params_to('face_weight_mlp')  
  126.   
  127. def test_mlp():  
  128.     net1.load_params_from('face_weight_mlp')  
  129.     x = load_testdata()  
  130.     y = np.empty(shape = (x.shape[0],30))  
  131.     y = net1.predict(x)  
  132.     #保存图片  
  133.     x = x*255  
  134.     y = y*48+48  
  135.     for i in range(len(x)):  
  136.         tmp = x[i].reshape(96,96)  
  137.         img = cv2.cvtColor(tmp,cv2.COLOR_GRAY2BGR)  
  138.         add = './predict/'+str(i)+'.Bmp'  
  139.         for j in range(15):  
  140.             point = (y[i][2*j],y[i][2*j+1])  
  141.             cv2.circle(img,point,1,(0,255,0))  
  142.         cv2.imwrite(add,img)  
  143.   
  144. def train_ann():  
  145.     x , y = load()  
  146.     net1.load_params_from('face_weight_ann')  
  147.     net3.fit(x, y)  
  148.     net3.save_params_to('face_weight_ann')  
  149.   
  150. def test_ann():  
  151.     net3.load_params_from('face_weight_ann')  
  152.     x = load_testdata()  
  153.     y = np.empty(shape = (x.shape[0],30))  
  154.     y = net3.predict(x)  
  155.     #保存图片  
  156.     x = x*255  
  157.     y = y*48+48  
  158.     for i in range(len(x)):  
  159.         tmp = x[i].reshape(96,96)  
  160.         img = cv2.cvtColor(tmp,cv2.COLOR_GRAY2BGR)  
  161.         add = './predict/'+str(i)+'.Bmp'  
  162.         for j in range(15):  
  163.             point = (y[i][2*j],y[i][2*j+1])  
  164.             cv2.circle(img,point,1,(0,255,0))  
  165.         cv2.imwrite(add,img)  
  166.   
  167. def train_cnn():  
  168.     x , y = load()  
  169.     x = x.reshape(-119696)  
  170.     net2.load_params_from('face_weight_cnn')  
  171.     net2.fit(x, y)  
  172.     net2.save_params_to('face_weight_cnn')  
  173.   
  174. def test_cnn():  
  175.     net2.load_params_from('face_weight_cnn')  
  176.     x = load_testdata()  
  177.     x = x.reshape(-119696)  
  178.     y = np.empty(shape = (x.shape[0],30))  
  179.     y = net2.predict(x)  
  180.     #保存图片  
  181.     x = x*255  
  182.     y = y*48+48  
  183.     for i in range(len(x)):  
  184.         tmp = x[i].reshape(96,96)  
  185.         img = cv2.cvtColor(tmp,cv2.COLOR_GRAY2BGR)  
  186.         add = './predict/'+str(i)+'.Bmp'  
  187.         for j in range(15):  
  188.             point = (y[i][2*j],y[i][2*j+1])  
  189.             cv2.circle(img,point,1,(0,255,0))  
  190.         cv2.imwrite(add,img)  
  191.   
  192. if __name__ == '__main__':  
  193.     #train_ann()  
  194.     #test_ann()  
  195.   
  196.     #train_mlp()  
  197.     #test_mlp()  
  198.       
  199.     #train_cnn()  
  200.     test_cnn()  
  201.   
  202.     print 'OK'  
代码比较简单,但是调试过程中还出了不少问题,本来看了这个算法之后觉得比较简单想自己用keras写,但是发现完全不能收敛,问题非常简单,这里要解决的问题是一个回归问题,而不是分类问题。而之前用到的keras的函数也只提供了分类的接口(如果有知道如何用keras解决回归问题请指教,不胜感激)。

后来没办法只好去用lasagne,谁知道程序出来之后 报错如下:

File "/usr/local/lib/python2.7/dist-packages/theano/gradient.py", line 432, in grad
raise TypeError("cost must be a scalar.")
TypeError: cost must be a scalar.

这里有解决方法https://github.com/dnouri/kfkd-tutorial/issues/16 

主要就是这三句:

pip uninstall Lasagne
pip uninstall nolearn
pip install -r https://raw.githubusercontent.com/dnouri/kfkd-tutorial/master/requirements.txt

当时没有找到解决办法,百度不给力呀,然后就想自己解决,这个报错太坑了,专门跑去看了源码,没多大收货。最后想到的解决方法是自己去用theano写,主要要修改的地方如下:

self.p_y_given_x = T.nnet.softmax(T.dot(input, self.W) + self.b)

        # symbolic description of how to compute prediction as class whose
        # probability is maximal
        self.y_pred = T.argmax(self.p_y_given_x, axis=1)
        # end-snippet-1

        # parameters of the model
        self.params = [self.W, self.b]

        # keep track of model input
        self.input = input

    def negative_log_likelihood(self, y):
        """Return the mean of the negative log-likelihood of the prediction
        of this model under a given target distribution.

        .. math::

            \frac{1}{|\mathcal{D}|} \mathcal{L} (\theta=\{W,b\}, \mathcal{D}) =
            \frac{1}{|\mathcal{D}|} \sum_{i=0}^{|\mathcal{D}|}
                \log(P(Y=y^{(i)}|x^{(i)}, W,b)) \\
            \ell (\theta=\{W,b\}, \mathcal{D})

        :type y: theano.tensor.TensorType
        :param y: corresponds to a vector that gives for each example the
                  correct label

        Note: we use the mean instead of the sum so that
              the learning rate is less dependent on the batch size
        """
        # start-snippet-2
        # y.shape[0] is (symbolically) the number of rows in y, i.e.,
        # number of examples (call it n) in the minibatch
        # T.arange(y.shape[0]) is a symbolic vector which will contain
        # [0,1,2,... n-1] T.log(self.p_y_given_x) is a matrix of
        # Log-Probabilities (call it LP) with one row per example and
        # one column per class LP[T.arange(y.shape[0]),y] is a vector
        # v containing [LP[0,y[0]], LP[1,y[1]], LP[2,y[2]], ...,
        # LP[n-1,y[n-1]]] and T.mean(LP[T.arange(y.shape[0]),y]) is
        # the mean (across minibatch examples) of the elements in v,
        # i.e., the mean log-likelihood across the minibatch.
        return -T.mean(T.log(self.p_y_given_x)[T.arange(y.shape[0]), y])
        # end-snippet-2


这里的cost函数表示的是归类问题的趋近概率,而我们要的cost函数是表示预测值和真实值的差值,感觉用LMS( Least mean square)函数比较合适(学的少,只知道这个- -)。不过因为theano调试比较麻烦,python学的又菜,感觉调试时间太久,放弃了又回去找之前的问题。其实还是有点懒,用了这些库之后就不太想再用theano了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值