2017-01-15 13:07:00 linolzhang 阅读数 4710
  • 机器学习实战训练--业务实践之

    本系列课程为您讲述如何使用机器学习算法解决业务问题,会以实际业务作为出发点,所有实验都提供实验流程以及实验数据,帮您用短的时间学习机器学习的原理与使用方法。充分理解如何在业务问题上是同数据挖掘。

    10610 人正在学习 去看看 李博

        Dlib 是一个机器学习库,采用C++编写(提供C++和python接口),里面包含 许多常用机器学习算法。

        Dlib 目前已更新到 V19.2。下载及文档可以参见 官网地址: http://www.dlib.net/ml.html

一. 编译

        下载的dlib库解压后,需要通过CMake进行编译,在windows下作者采用的是 CMake3.5.1。

        选择 源码位置(source code)和 编译位置(binaries)后 依次选择configure->Generate进行编译和生成(编译后生成一个文件 dlib.lib)。

        

        注:V19.2版本需要C++11支持,对应VS2015以上版本


二. 测试例

        dlib 提供了丰富的算法例子,包含 3D点云、SURF特征、贝叶斯分类、SVM、深度学习、多种回归 等算法,也包含Thread、Timer、XML、Socket、Sqlite 等 底层基本工具,有时间的话大家可以仔细跑一遍例子看看。

        

        作为入门级实例,作者采用 Face LandmarkDetection人脸对齐的例子进行说明(当然有很多人喜欢 上面的Face Detection或者GUI)。

        人脸对齐的代码比较简单,通过注释也能够看到其采用的是 HOG+线性分类器人脸对齐 采用了 2014年的一篇CVPR:

        One Millisecond Face Alignment with an Ensemble of Regression Trees by Vahid Kazemi and Josephine Sullivan, CVPR 2014

        PS:这篇文章号称速度极快(单人脸关键点耗时约为1ms),简称 1MS

        还有一篇文章 LBF(Face Alignment at 3000 FPS via Regressing Local Binary Features),也是基于回归的方法,简称 3000FPS

        程序中直接加载了训练好的模型,当然 你也可以训练自己的模型(参考 train_shape_predictor_ex.cpp),先上代码:

// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt
/*
    This example program shows how to find frontal human faces in an image and
    estimate their pose.  The pose takes the form of 68 landmarks.  These are
    points on the face such as the corners of the mouth, along the eyebrows, on
    the eyes, and so forth.  

    This face detector is made using the classic Histogram of Oriented
    Gradients (HOG) feature combined with a linear classifier, an image pyramid,
    and sliding window detection scheme.  The pose estimator was created by
    using dlib's implementation of the paper:
        One Millisecond Face Alignment with an Ensemble of Regression Trees by
        Vahid Kazemi and Josephine Sullivan, CVPR 2014
    and was trained on the iBUG 300-W face landmark dataset.  

    Also, note that you can train your own models using dlib's machine learning
    tools.  See train_shape_predictor_ex.cpp to see an example.

    Finally, note that the face detector is fastest when compiled with at least
    SSE2 instructions enabled.  So if you are using a PC with an Intel or AMD
    chip then you should enable at least SSE2 instructions.  If you are using
    cmake to compile this program you can enable them by using one of the
    following commands when you create the build project:
        cmake path_to_dlib_root/examples -DUSE_SSE2_INSTRUCTIONS=ON
        cmake path_to_dlib_root/examples -DUSE_SSE4_INSTRUCTIONS=ON
        cmake path_to_dlib_root/examples -DUSE_AVX_INSTRUCTIONS=ON
    This will set the appropriate compiler options for GCC, clang, Visual
    Studio, or the Intel compiler.  If you are using another compiler then you
    need to consult your compiler's manual to determine how to enable these
    instructions.  Note that AVX is the fastest but requires a CPU from at least
    2011.  SSE4 is the next fastest and is supported by most current machines.  
*/

#include <dlib/image_processing/frontal_face_detector.h>
#include <dlib/image_processing/render_face_detections.h>
#include <dlib/image_processing.h>
#include <dlib/gui_widgets.h>
#include <dlib/image_io.h>
#include <iostream>

using namespace dlib;
using namespace std;

// ----------------------------------------------------------------------------------------

int main(int argc, char** argv)
{  
    try
    {
        // 需要一个形状模型文件(标记68个点) 和一系列的图片(examples/faces文件夹下)
        if (argc == 1)
        {
            cout << "命令行调用方法:" << endl;
            cout << "./face_landmark_detection_ex shape_predictor_68_face_landmarks.dat faces/*.jpg" << endl;
            cout << "模型下载地址:" << "http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2" << endl;
            return 0;
        }

        // 需要一个人脸检测器,获取人脸外框
        frontal_face_detector detector = get_frontal_face_detector();

        // 然后需要一个形状预测器,用来预测已知的脸部外框的标记点位置
        // 我们仅仅从shape_predictor_68_face_landmarks.dat文件加载模型  
        shape_predictor sp;
        deserialize(argv[1]) >> sp;

        image_window win, win_faces;
        // 加载所有图像
        for (int i = 2; i < argc; ++i)
        {
            cout << "处理图像 " << argv[i] << endl;
            array2d<rgb_pixel> img;
            load_image(img, argv[i]);
            // 放大图片,确保能检测到尺寸较小的人脸
            pyramid_up(img);

            // 检测图像中的所有人脸
            std::vector<rectangle> dets = detector(img);
            cout << "检测到的人脸数量: " << dets.size() << endl;

            // 调用形状预测器,获取每个人脸的姿态
            std::vector<full_object_detection> shapes;
            for (unsigned long j = 0; j < dets.size(); ++j)
            {
                full_object_detection shape = sp(img, dets[j]);
                cout << "Parts个数:"<< shape.num_parts() << endl;
                cout << "pixel position of first part:  "<< shape.part(0) << endl;
                cout << "pixel position of second part: "<< shape.part(1) << endl;
                // 你可以得到所有的Face Part,这里我们把它保存到shapes里,用于后面的绘制
                shapes.push_back(shape);
            }

            // 绘制姿态检测结果
            win.clear_overlay();
            win.set_image(img);
            win.add_overlay(render_face_detections(shapes));

            // 我们也能提取每张剪裁后的人脸的副本,旋转到恰当位置,然后缩放到一个标准尺寸
            dlib::array<array2d<rgb_pixel> > face_chips;
            extract_image_chips(img, get_face_chip_details(shapes), face_chips);
            win_faces.set_image(tile_images(face_chips));

            cout << "回车处理下一张图片..." << endl;
            cin.get();
        }
    }
    catch (exception& e)
    {
        cout << "\n 异常!" << endl;
        cout << e.what() << endl;
    }
}

        编译成功后下载训练好的 模型文件(61M):shape_predictor_68_face_landmarks.dat.bz2

        文件解压后放在生成的exe根目录下,将 dlib-19.2\examples\faces 文件夹也放在exe目录下,修改工作目录为:$(SolutionDir)$(Platform)\$(Configuration)\

        添加命令参数(shape_predictor_68_face_landmarks.dat faces/2007_007763.jpg),运行程序(右键-属性-调试-命令参数),看一下检测效果:


2018-01-23 21:28:37 FLORIDA_tang 阅读数 148
  • 机器学习实战训练--业务实践之

    本系列课程为您讲述如何使用机器学习算法解决业务问题,会以实际业务作为出发点,所有实验都提供实验流程以及实验数据,帮您用短的时间学习机器学习的原理与使用方法。充分理解如何在业务问题上是同数据挖掘。

    10610 人正在学习 去看看 李博

机器学习实践系列(一)普通线性回归

This blog is based on sklearn dataset,i.e.,diabetes.build a linear regression model.

import numpy as np
from sklearn.utils import shuffle
import matplotlib.pyplot as plt
from sklearn import linear_model,datasets
from sklearn.metrics import mean_squared_error,r2_score

#加载我们的训练数据
#使用sklearn提供的diabetes数据集

diabetes = datasets.load_diabetes()

#仅选择一列数据作为训练数据
diabetes_X = diabetes.data[:, np.newaxis, 2]
#y是标签
y = diabetes.target

#这里我们使用sklearn里的shuffle函数把数据顺序打乱
X,y = shuffle(diabetes_X,y,random_state=7)

#分割训练集和数据集
num_training = int(0.7*len(X))
X_train = X[:num_training]
y_train = y[:num_training]
X_test = X[num_training:]
y_test = y[num_training:]

#构建模型
reg = linear_model.LinearRegression()
#训练模型
reg.fit(X_train,y_train)
#预测模型
y_pred = reg.predict(X_test)

#输出模型参数
print("模型参数",reg.coef_)

#计算均方误差
print("均方误差",mean_squared_error(y_test,y_pred))

#计算r2值
print("r2值",r2_score(y_test,y_pred))
plt.figure()
plt.subplot(1,2,1)
plt.title('rew data')
plt.scatter(X_test,y_test,color='blue')
plt.subplot(1,2,2)
plt.title('linear model')
plt.scatter(X_test,y_test,color='blue')
plt.plot(X_test,y_pred,color='black',linewidth=4)
plt.show()

输出结果:

模型参数 [ 1003.04891533]
均方误差 4039.46847212
r2值 0.258925986194
``````
输出结果:





<div class="se-preview-section-delimiter"></div>

模型参数 [ 1003.04891533]
均方误差 4039.46847212
r2值 0.258925986194
“`
这里写图片描述

这里写图片描述

模型参数 [ 1003.04891533]
均方误差 4039.46847212
r2值 0.258925986194

这里写图片描述

2017-10-12 16:36:40 hhhparty 阅读数 776
  • 机器学习实战训练--业务实践之

    本系列课程为您讲述如何使用机器学习算法解决业务问题,会以实际业务作为出发点,所有实验都提供实验流程以及实验数据,帮您用短的时间学习机器学习的原理与使用方法。充分理解如何在业务问题上是同数据挖掘。

    10610 人正在学习 去看看 李博

在深入学习机器学习,开启人工智能算法设计之前,有许多需要事先掌握的知识,最重要的是数学知识和编程能力,而且要把这两者有机结合起来,以备今后实现各类算法做好准备。
python是如今广为传颂的科学计算程序开发语言,有优势或缺点在这里不想追溯,毕竟没有一种万能工具能解决所有问题,我们只把它当成一种工具就好了。我想把自己学习、实践机器学习知识的体会通过这个博客记录下来,分享出去,其中的问题和错误希望看到的朋友给予批评指正。
先把之前整理过的,使用python numpy库完成线性代数常用计算的部分记录一下。

一、环境准备

1. 编码工具

执行下面程序前,需要安装python 和numpy库,推荐使用anaconda 3或更高版本。安装过程请参看anaconda官网文档

2.编程环境

每个人都有自己偏爱的python编程环境,或繁或简都是可以的。在这里推荐使用anaconda 3集成的jupyter notebook,能够在浏览器上编写和调试代码,简单方便。

二、线性代数中常用计算的实现

线性代数里的主要内容包括:

  • 行列式
  • 矩阵
  • 向量
  • 线性方程
  • 线性空间
  • 二次型等

    由于行列式可以认为是方阵的一种特殊计算表达方式,所以下面从矩阵的创建开始。

1.矩阵的创建

如果仅使用于python+numpy,那么创建矩阵有如下方法:

import numpy as np
#下列矩阵均由numpy ndarray对象存放

'''构造矩阵方法1  得到一个3*3矩阵'''
a = np.array([[1,2,-4],[-2,2,1],[-3,4,-2]],dtype=np.float64)
'''构造矩阵方法2,得到一个3*3矩阵'''
b = b = np.arange(11,20).reshape(3,3)
'''构造矩阵方法3,得到一个3*3的全0矩阵'''
c = np.zeros((3,3))
'''构造矩阵方法4,得到一个3*3的全1矩阵'''
d = np.ones((3,3))
'''构造矩阵方法5,得到一个3*3的从1到9线性均匀分布的3*3的矩阵'''
e = np.linspace(1,9,9).reshape(3,3)
'''构造矩阵方法6,得到一个3*3的单位矩阵'''
f = np.eye(3,dtype=int)

print(a)
print(b)
print(c)
print(d)
print(e)
print(f)

运行后结果如下:

[[ 1.  2. -4.]
 [-2.  2.  1.]
 [-3.  4. -2.]]
[[11 12 13]
 [14 15 16]
 [17 18 19]]
[[ 0.  0.  0.]
 [ 0.  0.  0.]
 [ 0.  0.  0.]]
[[ 1.  1.  1.]
 [ 1.  1.  1.]
 [ 1.  1.  1.]]
[[ 1.  2.  3.]
 [ 4.  5.  6.]
 [ 7.  8.  9.]]
[[1 0 0]
 [0 1 0]
 [0 0 1]]

如果要建立随机数矩阵,可以用numpy中的random模块,有下列方法:

import numpy as np

a = np.random.rand(4,3)
b = np.random.randint(1,100,(4,4))
print(a)
print(b)
输出结果为:
[[ 0.82181056  0.90892419  0.7925167 ]
 [ 0.78454205  0.53208353  0.50467863]
 [ 0.41581293  0.32967551  0.13403763]
 [ 0.68428216  0.38660852  0.65485223]]
[[ 5 81 69 48]
 [71 67 37 63]
 [99 64 94  8]
 [97  9  9 61]]
#还可以自定义设立随机数种子,RandomState里的数字可以是32位二进制的任意整数、None或一个数组
my=np.random.RandomState([123,123,333])
c = my.rand(3,4)
d = my.randint(1,20,(3,4))
print(c)
print(d)
结果为:
[[ 0.5047555   0.24418547  0.8384022   0.67247537]
 [ 0.68275279  0.83532539  0.92314775  0.38936819]
 [ 0.80516984  0.78074428  0.69678646  0.10246203]]
[[ 6 15  7 13]
 [ 5 15  6 19]
 [15  2 14 12]]

2. 行列式的计算

如果要计算某个行列式,首先你要先把对应的矩阵先创建出来,然后运用numpy库中的linalg.det()来计算。例如:

import numpy as np
#计算矩阵行列式
a = np.array([[1,2,-4],[-2,2,1],[-3,4,-2]],dtype=np.int32)
det_value = np.linalg.det(a)
print(det_value)

运行后,结果为-14

3. 矩阵中元素的获取

3.1 返回方阵的对角线

import numpy as np

a = np.array([[1,2,-4],[-2,2,1],[-3,4,-2]],dtype=np.int32)
'''返回方阵的对角线'''
adiag = np.diag(a)
print(adiag)
print(np.diag(a,1))#住对角线上面的一条部分对角线
print(np.diag(a,-1))#住对角线下面的一条部分对角线)

运行后输出为:

[ 1.  2. -2.]
[ 2.  1.]
[-2.  4.]

4. 矩阵相关计算

4.1 矩阵加/减

import numpy as np

a = np.linspace(1,16,16).reshape(4,4)
b = np.linspace(11,26,16).reshape(4,4)
print(a+b)
print(b-a)
结果为:
array([[ 12.,  14.,  16.,  18.],
       [ 20.,  22.,  24.,  26.],
       [ 28.,  30.,  32.,  34.],
       [ 36.,  38.,  40.,  42.]])
array([[ 10.,  10.,  10.,  10.],
       [ 10.,  10.,  10.,  10.],
       [ 10.,  10.,  10.,  10.],
       [ 10.,  10.,  10.,  10.]])

4.2 矩阵与数相乘

import numpy as np

a = np.linspace(1,16,16).reshape(4,4)
c = 5*a
print(c)
结果为:
array([[  5.,  10.,  15.,  20.],
       [ 25.,  30.,  35.,  40.],
       [ 45.,  50.,  55.,  60.],
       [ 65.,  70.,  75.,  80.]])

4.3 计算对角线上元素之和,主对角元素之和也称为迹

import numpy as np

a = np.array([[1,2,-4],[-2,2,1],[-3,4,-2]],dtype=np.float64)
'''计算对角线上元素之和'''
diagsum = np.trace(a)
print(diagsum)

结果为1.0
4.4 计算矩阵与矩阵的乘积

import numpy as np

a = np.array([[1,2,-4],[-2,2,1],[-3,4,-2]],dtype=np.float64)
'''矩阵dot乘积'''
adot = np.dot(a,a)
print(adot)
运行结果为:
[[  9. -10.   6.]
 [ -9.   4.   8.]
 [ -5.  -6.  20.]]

4.5 计算矩阵的转置

import numpy as np

a = np.array([[1,2,-4],[-2,2,1],[-3,4,-2]],dtype=np.float64)
'''计算矩阵的转置'''
a_T = np.linalg.inv(a)
print(a_T)

4.6 求矩阵的秩(rank)

import numpy as np

a = np.array([[1,2,-4],[-2,2,1],[-3,4,-2]],dtype=np.float64)
'''求矩阵的秩rank'''
rankofa = np.linalg.matrix_rank(a)
print(rankofa)

4.7 计算矩阵的逆矩阵、伴随矩阵

#计算某个方阵的逆矩阵
import numpy as np
d = np.random.randint(1,100,(4,4))
e = np.linalg.inv(d)
print(d)
print(e)
运行结果为:
[[26 70 25 33]
 [77 65 97 34]
 [45 56 36 52]
 [36 26 67 47]]
[[-0.03586354  0.01596751  0.04105832 -0.03179641]
 [ 0.02552074  0.0010049  -0.01347506 -0.00373719]
 [ 0.01336591  0.00288302 -0.0302851   0.02203676]
 [-0.00570144 -0.01689618  0.01917774  0.01628457]]
#求伴随矩阵可以用公式: A的逆矩阵 = 1/|A| * A的伴随矩阵
f = np.linalg.det(d)*np.linalg.inv(d)

4.8 计算方阵的特征值和特征向量

import numpy as np

a = np.array([[1,2,-4],[-2,2,1],[-3,4,-2]],dtype=np.float64)
'''计算方阵的特征值和特征向量'''
r1,r2 = np.linalg.eig(a)
print(r1)
print(r2)

(还差1万字,明天继续)

2017-02-16 22:14:32 linolzhang 阅读数 8623
  • 机器学习实战训练--业务实践之

    本系列课程为您讲述如何使用机器学习算法解决业务问题,会以实际业务作为出发点,所有实验都提供实验流程以及实验数据,帮您用短的时间学习机器学习的原理与使用方法。充分理解如何在业务问题上是同数据挖掘。

    10610 人正在学习 去看看 李博

       提到 目标跟踪(Object Tracking),很多专业人士都不陌生,它是计算机视觉里面 用于视频分析的一个很大的分类,就像目标检测一样,是视频分析算法的底层支撑。

       目标跟踪的算法有很多,像 Mean-Shift、光流法、粒子滤波、卡尔曼滤波等 传统方法,也有 TLD、CT、Struct、KCF 等掺杂了某些 “外力”,不那么纯粹的方法。但不管怎样,Tracking这项工作有着很大的研究群体,也不乏有人为之奋斗终生!


• CamShift

       CamShift 连续自适应的Mean-Shift算法(Continuously Adaptive Mean-SHIFT),作为入门级的目标跟踪,包括两部分:

1. 对视频中的每一帧做 Mean-Shift;

2. 将上一帧的 Mean-Shift 结果 作为下一帧的输入,反复迭代;

       算法步骤非常简单,问题可以演化为: Mean-Shift 是什么?其输入输出又是什么?

       Mean-Shift 就是大名鼎鼎的 均值漂移,这里面有两层含义:

       1)均值 

             空间R中有N个样本点,任选一点x0,假定有k个点落在x的邻域范围(半径h)内,那么MeanShift向量可以定义为:

            

            其中Sk是一个半径为h的高维球区域,满足公式:

              

       说的再通俗一点,分两步:

A) 任选空间内的一点x0,以该点为圆心做一个半径h的球(可能扩展到高维),统计球内的所有点,为x0的邻域点;

B) 圆心到邻域点连线作为向量,所有向量和求均值,即得到 Mean-Shift 向量

       

       通过均值计算,我们得到一个(x0, x'0)的向量,如图橘色箭头。

       2)漂移

            将圆心 x0 移动到 Mean-Shift 向量 的终点 x'0 ,就是 漂移(比平移好听)。以x'0 为新的中心,重复上面的过程,迭代计算,直到收敛。

       Mean-Shift 这种特征使得其在 目标跟踪、聚类、图像平滑等问题上都有应用。

       核心思想是 利用概率密度的梯度爬升 来寻找局部最优。输入一个图像的区域范围,逐步迭代,对应区域朝 质心(重心)漂移。

      

概率密度函数 与 反向投影

       事实上,我们需要将 待跟踪的目标 ROI进行提取 直方图,计算输入图像对应直方图的 反向投影,得到输入图像在已知目标颜色直方图的条件下的颜色概率密度分布图,包含了目标在当前帧中的相干信息。 

       对于目标区域内的像素,可得到该像素属于目标像素的概率,而对于非目标区域内的像素,该概率为0。

       参考下面代码进行理解:

/* linolzhang 2013.11
   CamShift跟踪
*/
#include "opencv/cv.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/video/tracking.hpp"
#include "opencv2/highgui/highgui.hpp"

#pragma comment(lib,"opencv_core2410.lib")
#pragma comment(lib,"opencv_imgproc2410.lib")
#pragma comment(lib,"opencv_video2410.lib")
#pragma comment(lib,"opencv_highgui2410.lib")

#define SAT_MIN 65 // 定义最小饱和度,低于该饱和度的色调不稳定
#define V_MIN 10

using namespace cv;

IplImage* getHSV(const IplImage *img,IplImage **img_h,IplImage **img_s,IplImage **img_v)
{
	IplImage *img_hsv = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3);
	cvCvtColor(img,img_hsv,CV_BGR2HSV);
	cvSplit(img_hsv, *img_h, img_s==NULL?NULL:*img_s,img_v==NULL?NULL:*img_v, NULL);

	// 定义掩码,只处理像素值为H:0~180,S:SAT_MIN~255的部分
	IplImage *img_msk = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
	cvInRangeS(img_hsv, cvScalar(0,SAT_MIN,V_MIN,0),cvScalar(180,255,255,0), img_msk);

	cvReleaseImage(&img_hsv);
	return img_msk;
}

int main(int argc, char** argv)
{
	IplImage *src = cvLoadImage("1.jpg", -1); // 加载源图像 - 包含待跟踪目标
	CvRect rcROI = cvRect(132,296,132,176);    // 待跟踪目标位置

	// 1.将目标转换到HSV空间,提取Hue分量
	IplImage *src_h = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
	IplImage *src_s = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
	IplImage *hsv_mask = getHSV(src,&src_h,&src_s,NULL);

	// 2.计算分量直方图 - 1维
	int hist_size = 256; // 64 | 128 | 256
	float range[] = {0,180};
	float *ranges[] ={ range };
	CvHistogram *hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges);

	cvSetImageROI(src,rcROI); // 设置源图像ROI
	cvCalcHist(&src_h, hist,0,hsv_mask);
	cvReleaseImage(&hsv_mask);
	cvResetImageROI(src);     // 清空ROI

	// 3.计算反向投影,得到概率密度图 img_prob
	IplImage *dest = cvLoadImage("2.jpg", -1); // 从这幅图搜索
	IplImage *dest_h = cvCreateImage(cvGetSize(dest), IPL_DEPTH_8U, 1);
	IplImage *dest_s = cvCreateImage(cvGetSize(dest), IPL_DEPTH_8U, 1);
	hsv_mask = getHSV(dest,&dest_h,&dest_s,NULL);
	IplImage *img_prob = cvCreateImage(cvGetSize(dest),IPL_DEPTH_8U,1);

	cvCalcBackProject(&dest_h,img_prob,hist);
	cvAnd(img_prob, hsv_mask, img_prob, 0);
	cvReleaseImage(&hsv_mask);

	// 4.调用MeanShift函数计算
	// int cvMeanShift(IplImage* imgprob,CvRect windowIn,CvTermCriteria criteria,CvConnectedComp* out);
    // 参数说明:imgprob: 2D概率密度图  windowIn:初始窗口  criteria:迭代终止条件  out:输出结果
	CvConnectedComp conn_comp;
	cvMeanShift(img_prob,rcROI, cvTermCriteria(CV_TERMCRIT_ITER,10,0.1), &conn_comp);
	//CvBox2D track_box;
	//cvCamShift(img_prob,rcROI,cvTermCriteria(CV_TERMCRIT_ITER, 100, 0.01 ),&conn_comp, &track_box );

	// 5.绘制结果
	cvRectangle( src,cvPoint(rcROI.x,rcROI.y),cvPoint(rcROI.x+rcROI.width,rcROI.y+rcROI.height),cvScalar(0,255,0) );
	cvShowImage("源图像",src);

	cvShowImage("概率密度图",img_prob);
	
	cvRectangle( dest,cvPoint(rcROI.x,rcROI.y),cvPoint(rcROI.x+rcROI.width,rcROI.y+rcROI.height),cvScalar(0,255,0) );
	CvRect& rc = conn_comp.rect;
	cvRectangle( dest,cvPoint(rc.x,rc.y),cvPoint(rc.x+rc.width, rc.y+rc.height),cvScalar(255,255,0) );
	cvShowImage("Track结果",dest);
	cvWaitKey(0);

	// 释放资源
	cvReleaseImage(&src);
	cvReleaseImage(&dest);
	cvReleaseImage(&img_prob);
	return 0;
}

       CamShift 算法在 Mean-Shift 算法基础上进行了改进:

       连续自适应:利用前一帧的目标尺寸调节搜索窗口大小,对有尺寸变化的目标可准确定位;

       不过,CamShift 算法在计算目标模板直方图分布时,没有使用核函数进行加权处理,也就是说目标区域内的每个像素点在目标模型中有着相同的权重,故算法的抗噪能力低于Mean-Shift 算法。

       另外,CamShift 算法仍然采用目标的色彩信息来进行跟踪(Hue in HSV),很难处理目标与背景颜色(或其他对象)相近的情况,跟踪结果的鲁棒性仍然较差。

       Cam Shift 通常用于单目标跟踪,虽然也有人进行过多目标跟踪扩展,不过效果并不好。


• TLD

       纯粹的跟踪已经out了,Tracking by Detecting 才是主流。

       TLD(Tracking-Learning-Detection)是一种新的单目标长时间跟踪算法。该算法的贡献在于 将传统的跟踪算法检测算法 相结合解决 目标在跟踪过程中发生的形变、部分遮挡等问题。

       原作者网站:http://personal.ee.surrey.ac.uk/Personal/Z.Kalal/

       C++ 封装代码:https://github.com/arthurv/OpenTLD   

       Ubuntu下编译过程,进入OpenTLD-master目录:

1)$mkdir build

2)$cd build

3)$cmake ../src

4)make

       可能会提示错误 PatchGenerator不是cv的一个成员,这是OpenCV版本过高导致的兼容问题(原版本是2.3),可以在TLD.h文件头文件添加:

        #include <opencv2/legacy/legacy.hpp>

       调试运行:

           5)cd ..                     # 进入程序根目录

           6)sudo bin/run_tld -p parameters.yml -s datasets/06_car/car.mpg

              能够看到,TLD的跟踪效果还是很不错的。

        

       TLD算法原理:

       1)通过 跟踪器 对目标进行跟踪,作者采用的是 光流法(Lucas-Kanade),这里作者引用了一个FB误差,可以描述为:

             a)在 t 时刻,目标框随机初始化跟踪点,通过正向追踪得到 t+1 时刻的目标位置;

             b)反向追踪到 t 时刻,计算误差,选择其中误差最小的一半点作为最佳跟踪点;

                  类似 RanSac,找一些对结果贡献大的点。

             示意如下图所示:

        

       2)通过 检测器 对目标进行检测,作者使用了一个 级联分类器 作为Detector,其中用到了随机蕨(Random Ferns),这里不再多说;

       3)通过 学习器 在线学习目标特征,根据上面 跟踪器和检测器 获得的正负样本进行在线训练,学习目标特征,并将训练特征更新到检测器

             话说Online 真是个好思路,都在用,由于光线、遮挡、观测角度等原因,在运动过程中目标特征会有所变化。


       算法不算复杂,这里面有个关键,就是作者提出的 P-N学习(P-N Learning)方法

       P-N学习 针对 检测器 对样本分类时产生的两种错误提供了两种“专家”进行纠正: 

P专家(P-expert):检出漏检(false negative,正样本误分为负样本)的正样本;

N专家(N-expert):改正误检(false positive,负样本误分为正样本)的正样本。

       说的通俗点就是,将检测结果和跟踪结果进行整合,哪个好用哪个,P-N学习 是一个裁判员。

       TLD 方法思想是非常值得借鉴的,当然这里面的 检测、跟踪、特征学习 环节都可以基于你的需要进行修改和替换,毕竟TLD也已经不新了,你可以用深度学习的方法,也可以用效率更高的方法,Whatever。


• CT

       压缩跟踪(Compressive Tracking) 是一种基于压缩感知的跟踪算法,来看作者(Kaihua Zhang,香港理工大学) 对该算法的简介:

       首先利用符合压缩感知 RIP条件的随机感知矩对多尺度图像特征进行降维,然后在降维后的特征上采用简单的朴素贝叶斯分类器进行分类。

       论文参考:Real-time compressive tracking. Kaihua Zhang, Lei Zhang, Ming-Hsuan Yang. ECCV 2012. (有代码可参考)

       核心点:

1. 在 t 时刻,进行图像采样(Patch),得到若干 正样本(目标)和 负样本(背景),通过金字塔变换得到多尺度特征;

2. 通过 稀疏测量矩阵M 对多尺度图像特征降维,然后利用降维后的特征 训练 分类器C(作者用了朴素贝叶斯);

3. 在 t+1 时刻,在目标位置周围采样N个Candidate(邻域原则),同样通过 稀疏测量矩阵M 对其降维,提取特征;

4. 用 t 时刻用 分类器C 进行分类,Score最大的窗口就是目标窗口。

       可以看到,压缩跟踪 方法是一种 Tracking by Detecting 的思路,实际就是在 目标邻域进行检测。

       压缩跟踪 的关键在于压缩,也就是降维,压缩感知有很多 Blog进行了介绍,可以自己学习一下(给个参考):

• Struct

       来自一篇2011年的ICCV:

       Struck:Structured Output Tracking with Kernels

       这里面用到了 高斯核函数,具体方法作者并没有详细研究,请自行脑补吧。


• KCF

       KCF是一个非常经典的算法(kernelized correlation filters),速度快、效果好,来自论文:

       High-speed tracking with kernelized correlation filters(ECCV 2012, TPAMI 2015)

       Paper及源码下载参考作者主页:http://www.robots.ox.ac.uk/~joao/#

       KCF算法的主要贡献:

1. 使用目标周围区域的循环矩阵采集正负样本,利用岭回归训练目标检测器;

    算法利用 循环矩阵在傅里叶空间可对角化的性质将矩阵的运算转化为向量的Hadamad积,即元素的点乘,大大降低了运算量。

2. 将线性空间的岭回归通过核函数映射到非线性空间,在非线性空间通过求解一个对偶问题和某些常见的约束,同样的可以使用循环矩阵傅里叶空间对角化简化计算。

3. 给出了一种将多通道数据融入该算法的途径。

       OpenCV3.1.0 在 contrib里提供了KCF的实现,需要用CMake重新编译,这里作者用的是VS2013(对应vc12)。

       配置编译步骤:

           1. 下载及项目配置

               下载contrib库:https://github.com/opencv/opencv_contrib

               选择Source及binaries(生成位置),指定generator,Finish完成配置,如下图所示:

               

           2. 添加编译选项

               找到OPENCV_EXTRA_MODULES_PATH,加入opencv_contrib目录。

               例如:作者的opencv_contrib 路径为D:/opencv3.1/opencv_contrib-master/modules

               编译并生成,configure & generate

           3. 配置VS2013

               配置头文件 和 库文件,设置环境dll,调试运行程序


参考代码:

#include <opencv2/core/utility.hpp>
#include <opencv2/tracking.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main() 
{
	Rect2d roi;
	Mat frame;

	// create a tracker object  
	Ptr<Tracker> tracker = Tracker::create("KCF");

	VideoCapture cap("1.avi");
	cap >> frame;

	// [selectroi]选择目标roi以GUI的形式  
	roi = selectROI("tracker", frame);
	if (roi.width == 0 || roi.height == 0)	// Invalid ROI 
		return 0;

	// init
	tracker->init(frame, roi);

	// perform the tracking process  
	printf("Start the tracking process\n");
	while(true)
	{
		cap >> frame;
		if (frame.rows == 0 || frame.cols == 0)
			break;

		tracker->update(frame, roi);
		rectangle(frame, roi, Scalar(255, 0, 0), 2, 1); // draw roi

		imshow("tracker", frame); // show image
		if(waitKey(1) == 27)
			break;
	}

	return 0;
}

2013-08-14 00:42:49 PhanYoung 阅读数 2228
  • 机器学习实战训练--业务实践之

    本系列课程为您讲述如何使用机器学习算法解决业务问题,会以实际业务作为出发点,所有实验都提供实验流程以及实验数据,帮您用短的时间学习机器学习的原理与使用方法。充分理解如何在业务问题上是同数据挖掘。

    10610 人正在学习 去看看 李博

机器学习实践这一系列文章,是作者参考一些有价值的机器学习实践实例后的总结。

和网上最多的机器学习文章的最大区别是:这一系列文章,都立足于代码实现和实际效果展现。

大部分文章会使用python实现算法。欢迎转载,转载时请注明出处:转自 “Miner帆的博客《数据火花》:http://blog.csdn.net/dataspark "

为什么选择python?

作为一种看似简洁却内涵丰富的语言,python本身在机器学习/数据挖掘方面并没有什么优势。python虽然形式简单,但繁琐的语法细节让我觉得它的学习成本并不低。

但scipy(http://www.scipy.org/)等强大的第三方库,让python在机器学习方面得心应手。

坦白而言,我对python没有什么特别的好感,甚至在相当长时间里,我排斥学习python(毕竟已经用了10多年的C/C++,加上一些轻量级脚本语言,几乎完全够用了)。但由于scipy系列库,让python成为我眼中最强大的(至少比R更强大)免费科学计算工具。做数据挖掘调研时,python几乎是不二选择。

但使用这些科学计算相关的库,可能会带来一些不适:

1. 科学计算的编程风格,可能会与纯正的面向对象相悖,在实际使用中,为了利用强大的计算工具,我们可能会把一些数据结构封装得比较简陋;

2. 增加了额外的学习成本,这些科学计算库里大量的数据结构和方法(相当一部分方法还比较晦涩),需要花更多时间去掌握。

尽管这样,python的学习成本也不会比matlab高,对于新的matlab工具箱,你不还是需要额外的学习成本么?

为什么选择python?

1. 因为scipy、numpy、matplot……这些,让它在数据分析时,非常强大;

2. python vs matlab: ptyhon免费

3. python vs R:  python是一门真正的计算机语言。R更适合统计学家玩, python更适合程序员用(比如字符串处理等基本操作,还是交给真正的计算机语言处理吧)。

此外,在版本上,选择了使用更广泛的python2.x(目前是2.7.5)而不是3.x。


选择工作环境

在【机器学习实践】系列文章中,我们都使用windows系统、eclipse编辑器(PyDEV插件)、winpython集成环境。

我本身更倾向于linux环境下写程序,但由于在调研阶段,需要有不少可视化分析,windows比linux更适合可视化。

eclipse,因为它的通用性,还因为它免费。pydev插件使能自由地处理python编程。

感谢一些集成发布出来的工具,像winpython ,它集成 了scipy、numpy、matplot等我们需要的科学计算库。这让我们不必安装python后,再一个一个地安装需要的库,还可能会遇到库的依赖和版本兼容问题。


配置工作环境

1. 安装winpython

winpython的官方网址:https://code.google.com/p/winpython/
考虑到国内网速情况,我在百度盘放了个32bit的版本:http://pan.baidu.com/share/link?shareid=4012255606&uk=939810364
双击安装,不再冗述。
假设安装的位置为:D:\software\develop\WinPython-32bit-2.7.5.2

2. 安装eclipse + pydev

安装方法:

1). 到 http://www.eclipse.org/ 下载eclipse最新版本的压缩包,如果下载速度过慢,你可以到我的网盘来获取:http://pan.baidu.com/share/link?shareid=1468424775&uk=939810364

2). 解压eclipse压缩包,即可使用;

3). 在http://marketplace.eclipse.org/ 中搜索PyDev插件,点击绿色的向下箭头,获取插件所在站点,当前最新的是http://pydev.org/updates/。运行eclipse,利用 Eclipse Update Manager 安装 PyDev。在 Eclipse 菜单栏中找到 Help栏,选择 Help > Install New Software

3'). 在 Eclipse 菜单栏中找到 Help栏,选择 Help > eclipse marketplace, 搜索PyDev,在结果中点击Install

当有许可条款出现时,记得点“同意”。



3. 配置eclipse集成编译环境
在装好winpython和eclipse后。打开eclipse,选择file->new->project,在打开的对话框中选择PyDev Project,如下图:


点 ”next“进入下一步设置:


点击:Please configure an interpreter .... 这行字,配置解释器。
点击 ”New" ->"Browse" 找到刚才安装的winpython的位置,选择python.exe文件


然后,eclispe会自动加载相同目录下的python库

点击OK,等eclipse自动设置。完成后,我们的python环境就搭好了。


没有更多推荐了,返回首页