计算机视觉中的机器学习:SVM、HOG与深度学习
1. 支持向量机(SVM)基础
支持向量机(SVM)在简单分类问题上计算较为简单,但对于更具挑战性的分类问题,核函数是非常有效的工具。OpenCV提供了多种标准核函数,如径向基函数、Sigmoid函数等,其目的是将样本映射到更大的非线性空间,使类别能够通过超平面分离。
SVM有多种变体,最常见的是C - SVM,它会对每个不在超平面正确一侧的异常样本添加惩罚项。由于SVM具有强大的数学基础,它在处理高维特征时表现出色,尤其是当特征空间的维度大于样本数量时,性能最佳。此外,SVM还具有内存效率高的优点,因为它只需要存储支持向量,而不像最近邻方法那样需要在内存中保存所有样本点。
2. HOG与SVM的结合
方向梯度直方图(HOG)和SVM是构建优秀分类器的良好组合。HOG可以被视为一种强大的高维描述符,能够捕捉对象类别的本质特征。HOG - SVM分类器已成功应用于许多领域,行人检测就是其中之一。
2.1 HOG可视化
HOG由重叠块中的单元格组成,因此很难直接可视化这个描述符。通常,通过显示每个单元格关联的直方图来表示HOG。在这种情况下,方向直方图可以更直观地绘制为星形,其中每条线的方向与它所代表的区间相关,线的长度与该区间的计数成正比。
以下是绘制单个单元格HOG的代码:
//draw one HOG over one cell
void drawHOG(std::vector<float>::const_iterator hog,
// iterator to the HOG
int numberOfBins, // number of bins inHOG
cv::Mat &image, // image of the cell
float scale=1.0) { // length multiplier
const float PI = 3.1415927;
float binStep = PI / numberOfBins;
float maxLength = image.rows;
float cx = image.cols / 2.;
float cy = image.rows / 2.;
// for each bin
for (int bin = 0; bin < numberOfBins; bin++) {
// bin orientation
float angle = bin*binStep;
float dirX = cos(angle);
float dirY = sin(angle);
// length of line proportion to bin size
float length = 0.5*maxLength* *(hog+bin);
// drawing the line
float x1 = cx - dirX * length * scale;
float y1 = cy - dirY * length * scale;
float x2 = cx + dirX * length * scale;
float y2 = cy + dirY * length * scale;
cv::line(image, cv::Point(x1, y1), cv::Point(x2, y2),
CV_RGB(255, 255, 255), 1);
}
}
以下是在图像上绘制HOG描述符的代码:
// Draw HOG over an image
void drawHOGDescriptors(const cv::Mat &image, // the input image
cv::Mat &hogImage, // the resulting HOG image
cv::Size cellSize, // size of each cell (blocks are ignored)
int nBins) { // number of bins
// block size is image size
cv::HOGDescriptor hog(
cv::Size((image.cols / cellSize.width) * cellSize.width,
(image.rows / cellSize.height) * cellSize.height),
cv::Size((image.cols / cellSize.width) * cellSize.width,
(image.rows / cellSize.height) * cellSize.height),
cellSize, // block stride (ony 1 block here)
cellSize, // cell size
nBins); // number of bins
//compute HOG
std::vector<float> descriptors;
hog.compute(image, descriptors);
...
float scale= 2.0 / * std::max_element(descriptors.begin(),descriptors.end());
hogImage.create(image.rows, image.cols, CV_8U);
std::vector<float>::const_iterator itDesc= descriptors.begin();
for (int i = 0; i < image.rows / cellSize.height; i++) {
for (int j = 0; j < image.cols / cellSize.width; j++) {
//draw each cell
hogImage(cv::Rect(j*cellSize.width, i*cellSize.height,
cellSize.width, cellSize.height));
drawHOG(itDesc, nBins,
hogImage(cv::Rect(j*cellSize.width,
i*cellSize.height,
cellSize.width, cellSize.height)),
scale);
itDesc += nBins;
}
}
}
这个函数计算具有指定单元格大小但仅由一个大的块(即块的大小等于图像大小)组成的HOG描述符,因此忽略了每个块级别的归一化效果。
2.2 行人检测
OpenCV提供了基于HOG和SVM的预训练行人检测器。与之前的分类器级联一样,这个SVM分类器可以通过在图像上以多个尺度扫描窗口来检测整幅图像中的实例。以下是使用该检测器的代码:
// create the detector
std::vector<cv::Rect> peoples;
cv::HOGDescriptor peopleHog;
peopleHog.setSVMDetector(
cv::HOGDescriptor::getDefaultPeopleDetector());
// detect peoples oin an image
peopleHog.detectMultiScale(myImage, // input image
peoples, // ouput list of bounding boxes
0, // threshold to consider a detection to be positive
cv::Size(4, 4), // window stride
cv::Size(32, 32), // image padding
1.1, // scale factor
2); // grouping threshold
窗口步长定义了128×64模板在图像上的移动方式(在我们的示例中,水平和垂直方向每4个像素移动一次)。较长的步长会使检测速度更快,但可能会错过一些位于测试窗口之间的行人。图像填充参数会在图像边界添加像素,以便检测图像边缘的行人。
SVM分类器的标准阈值为0(因为正实例赋值为1,负实例赋值为 - 1)。如果要确保检测到的是行人,可以提高阈值,但这可能会错过一些行人;反之,如果要确保检测到所有行人,可以降低阈值,但会增加误检的可能性。
当分类器应用于整幅图像时,在连续位置应用的多个窗口通常会在正样本周围产生多个检测结果。当两个或更多边界框在大致相同的位置重叠时,最好只保留其中一个。
cv::groupRectangles
函数可以将相似大小、相似位置的矩形合并,
detectMultiScale
方法会自动调用该函数。
3. 深度学习与卷积神经网络
在机器学习领域,不能不提及深度卷积神经网络(CNN)。将其应用于计算机视觉分类问题已经取得了令人瞩目的成果,其在实际问题中的出色表现为以前无法想象的新应用领域打开了大门。
3.1 深度学习兴起的原因
深度学习基于20世纪50年代末引入的神经网络理论,如今之所以受到广泛关注,主要有两个原因:
- 计算能力的提升:如今可用的计算能力使得部署能够解决挑战性问题的大型神经网络成为可能。早期的神经网络(如感知机)只有一层,需要调整的权重参数很少,而现在的网络可以有数百层和数百万个需要优化的参数,因此被称为深度网络。
- 大量数据的可用性:深度学习网络需要数千甚至数百万个带注释的样本进行训练,因为需要优化的参数数量非常大。如今大量的数据使得深度学习网络的训练成为可能。
3.2 卷积神经网络(CNN)
最流行的深度网络是卷积神经网络(CNN),顾名思义,它基于卷积操作。在这种情况下,需要学习的参数是组成网络的所有滤波器内核中的值。这些滤波器按层组织,早期层提取基本形状,如线条和角点,而较高层则逐渐检测更复杂的模式,例如在人体检测器中检测眼睛、嘴巴、头发的存在。
OpenCV 3有一个深度神经网络模块,但主要用于导入使用其他工具(如TensorFlow、Caffe或Torch)训练的深度网络。在构建未来的计算机视觉应用时,需要了解深度学习理论及其相关工具。
3.3 相关操作参数说明
| 参数 | 说明 |
|---|---|
| 窗口步长 | 定义模板在图像上的移动方式,较长步长检测快但可能漏检 |
| 图像填充 | 在图像边界添加像素,便于检测边缘行人 |
| 阈值 | 标准为0,提高阈值精度高但可能漏检,降低阈值召回率高但误检多 |
| 分组阈值 |
detectMultiScale
的最后一个参数,用于合并重叠检测框
|
3.4 行人检测流程
graph TD;
A[创建HOG描述符] --> B[设置SVM检测器];
B --> C[进行多尺度检测];
C --> D[输出检测结果];
综上所述,HOG与SVM的结合在目标检测领域有着重要的应用,而深度学习和卷积神经网络则为计算机视觉带来了新的发展方向。在实际应用中,可以根据具体需求选择合适的方法和工具。
4. 总结与应用建议
4.1 不同方法的优势总结
- SVM :具有强大的数学基础,在处理高维特征时表现出色,尤其是特征空间维度大于样本数量的情况。内存效率高,只存储支持向量。对于一些复杂的分类问题,通过核函数可以将样本映射到高维空间,使类别可分。
- HOG - SVM :HOG能够捕捉对象类别的本质特征,与SVM结合后在行人检测等应用中取得了很好的效果。HOG可视化可以帮助我们更好地理解其特征表示。
- 深度学习与CNN :在计算机视觉分类问题上取得了令人瞩目的成果,能够处理复杂的模式和大规模数据。随着计算能力的提升和数据的丰富,CNN的应用前景非常广阔。
4.2 应用场景选择建议
| 应用场景 | 建议方法 | 原因 |
|---|---|---|
| 高维特征且样本数量相对较少 | SVM | SVM在这种情况下性能最佳,内存效率高 |
| 行人检测等目标检测任务 | HOG - SVM | HOG能捕捉目标本质特征,结合SVM可有效检测目标 |
| 复杂的图像分类、识别任务 | 深度学习与CNN | CNN能够自动学习复杂的模式,处理大规模数据 |
4.3 操作步骤总结
4.3.1 HOG可视化操作步骤
-
定义绘制单个单元格HOG的函数
drawHOG,根据方向和区间计数绘制星形直方图。 -
定义在图像上绘制HOG描述符的函数
drawHOGDescriptors,计算HOG描述符并调用drawHOG函数绘制每个单元格。
4.3.2 行人检测操作步骤
-
创建HOG描述符
cv::HOGDescriptor。 -
设置SVM检测器为默认行人检测器
setSVMDetector(cv::HOGDescriptor::getDefaultPeopleDetector())。 -
调用
detectMultiScale方法进行多尺度检测,设置窗口步长、图像填充、阈值、缩放因子和分组阈值等参数。 -
处理检测结果,可使用
cv::groupRectangles函数合并重叠的检测框。
4.4 未来发展趋势
随着技术的不断发展,深度学习和卷积神经网络将在计算机视觉领域发挥越来越重要的作用。一方面,网络结构会不断优化,以提高性能和效率;另一方面,数据的规模和质量也将不断提升,为模型的训练提供更好的支持。同时,HOG - SVM等传统方法也将在一些特定场景中继续发挥作用,与深度学习方法相互补充。
4.5 注意事项
- 在使用HOG - SVM进行行人检测时,需要根据实际情况调整窗口步长、阈值等参数,以平衡检测速度和准确性。
- 深度学习模型的训练需要大量的计算资源和数据,在实际应用中需要考虑成本和可行性。
- 在使用OpenCV的深度神经网络模块时,要注意导入的模型与工具的兼容性。
总之,计算机视觉中的机器学习方法各有优劣,在实际应用中需要根据具体问题和需求选择合适的方法,并不断探索和优化,以取得更好的效果。无论是传统的SVM和HOG方法,还是新兴的深度学习和CNN技术,都为我们解决计算机视觉问题提供了有力的工具。
超级会员免费看

被折叠的 条评论
为什么被折叠?



