2019-06-28 09:46:16 weixin_42614655 阅读数 115

// The “Square Detector” program.
// It loads several images sequentially and tries to find squares in
// each image

#include “opencv2/core/core.hpp”
#include “opencv2/imgproc/imgproc.hpp”
#include “opencv2/highgui/highgui.hpp”

#include
#include <math.h>
#include <string.h>

using namespace cv;
using namespace std;

typedef struct Result
{
float location[10][2];
float totalarea[10];
}Result;

static double angle(Point pt1, Point pt2, Point pt0)
{
double dx1 = pt1.x - pt0.x;
double dy1 = pt1.y - pt0.y;
double dx2 = pt2.x - pt0.x;
double dy2 = pt2.y - pt0.y;
return (dx1dx2 + dy1dy2) / sqrt((dx1dx1 + dy1dy1)(dx2dx2 + dy2*dy2) + 1e-10);
}

static struct Result findSquares(const Mat& image, vector<vector >& squares)
{

``````struct  Result myresult;

int thresh = 100, N = 5;
const char* wndname = "Square Detection Demo";

int count = 0;
squares.clear();
``````

//用于装质心像素坐标的容器，由于能捕捉多个质心，我用的图片中的质心数目为4，所
//以先定义大一点的，再筛选
vector mc1oc(10);
//float totalarea[10];

``````//并进行模糊降噪
Mat timg(image);
medianBlur(image, timg, 9);
Mat gray0(timg.size(), CV_8U), gray;

vector<vector<Point> > contours;

// find squares in every color plane of the image
for (int c = 0; c < 3; c++)
{

int ch[] = { c, 0 };

//三个通道，分别为色相、饱和度、色调通道；
mixChannels(&timg, 1, &gray0, 1, ch, 1);

// try several threshold levels
for (int l = 0; l < N; l++)
{
// hack: use Canny instead of zero threshold level.
if (l == 0)
{
// apply Canny. Take the upper threshold from slider
// and set the lower to 0 (which forces edges merging)
Canny(gray0, gray, 5, thresh, 5);
// dilate canny output to remove potential
// holes between edge segments
dilate(gray, gray, Mat(), Point(-1, -1));
}
else
{
// apply threshold if l!=0:
//     tgray(x,y) = gray(x,y) < (l+1)*255/N ? 255 : 0
gray = gray0 >= (l + 1) * 255 / N;
}

// find contours and store them all as a list
findContours(gray, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);

vector<Point> approx;

//定义轮廓矩
vector<Moments> mu(contours.size());
//定义
vector<Point2f> mc(contours.size());

// 对每一个轮廓进行测试
for (size_t i = 0; i < contours.size(); i++)
{

//多边形拟合
approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*0.02, true);

// 矩形满足有四个顶点，且有足够的像素面
if (approx.size() == 4 &&
fabs(contourArea(Mat(approx))) > 1000 &&
isContourConvex(Mat(approx)))
{
double maxCosine = 0;

for (int j = 2; j < 5; j++)
{
// find the maximum cosine of the angle between joint edges
double cosine = fabs(angle(approx[j % 4], approx[j - 2], approx[j - 1]));
maxCosine = MAX(maxCosine, cosine);
}

// 顶点上角的余弦值都能接近0，即满足均为直角

if (maxCosine < 0.3) {
squares.push_back(approx);
//计算轮廓矩
mu[i] = moments(contours[i], false);
//计算轮廓的质心
mc[i] = Point2d(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);

if (mu[i].m10 > 0 && mu[i].m01 > 0) {
if (count < mc1oc.size()) {
mc1oc[count] = Point2d(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);
//面积
myresult.totalarea[count] = contourArea(Mat(approx));
myresult.location[count][1] = mc1oc[count].x;
myresult.location[count][2] = mc1oc[count].y;
count = count + 1;
}
}
}
}

}
}

}
/*for (int j = 0; j < count; j++) {
cout << myresult.totalarea[j] << endl;
}
cout << "质心坐标分别为： " << count << endl;*/
return myresult;
``````

2018-07-28 11:09:47 smilejiasmile 阅读数 562

《OpenCV编程实例代码》各章重点知识点简述

第一章 OpenCv环境配置

• 主要讲解了 OpenCV 的各种开发环境的配置，其中以Sublime 作为主要的配置环境的介绍，这里我们主要使用 VScode 进行开发。

第二章 图像及视频的基本操作

• 图像基本类库 Mat 的基本操作
• Mat 的基本操作：
``````      - Mat::row 、Mat::col
- Mat::rowRange 、Mat::colRange
- Mat::clone 、Mat::copyTo
- Mat::convertTo
- Mat::zeros 、Mat::ones
- Mat::channels
- Mat::empty 、Mat::at``````

• 图像的读取、显示、保存
• 图像存储
• 视频基本类库 VideoCapture 的基本操作
• 常见函数：
``````     - VideoCapture::open
- VideoCapture::isOpened
- VideoCapture::release
- VideoCapture::grab
- VideoCapture::retrieve 解码并返回视频帧
- VideoCapture::get 返回指定视频的相关参数信息
- VideoCapture::set``````

• 视频写操作 VideoWrite
• 常见函数
• open 、write
• 视频质量评价 ：图像的相似度
• 峰值信噪比 PSNR 用于图像压缩中的信号重建的测量方法
• 结构相似性 SSIM
• 图像的几何变换
• 坐标映射 remap
• 平移
• 缩放
• 等间隔提取图像缩放
• 区域字块提取图像缩放
• 旋转
• 翻转 transpose 、filp
• 仿射变换
• 在空间坐标系中将一个二维坐标转换成另一个二维坐标
• 图像的基本应用操作
• 界面事件
• 程序界面中的鼠标及键盘事件
• 如：setMouseCallback(WinNameString,MouseCallBack,userData)
• 其中回调函数形式为 void Fun(int event,int x,int y,int flags,void *param)
• 其中，上面的 event 是 enum 的数值
``````     -  CV_EVENT_MOUSEMOVE      =0,
-  CV_EVENT_LBUTTONDOWN    =1,
-  CV_EVENT_RBUTTONDOWN    =2,
-  CV_EVENT_MBUTTONDOWN    =3,
-  CV_EVENT_LBUTTONUP      =4,
-  CV_EVENT_RBUTTONUP      =5,
-  CV_EVENT_MBUTTONUP      =6,
-  CV_EVENT_LBUTTONDBLCLK  =7,
-  CV_EVENT_RBUTTONDBLCLK  =8,
-  CV_EVENT_MBUTTONDBLCLK  =9,
-  CV_EVENT_MOUSEWHEEL     =10,
-  CV_EVENT_MOUSEHWHEEL    =11   ``````

• 区域提取，提取出你感兴趣的部分
• 1、使用cv::Rect 选择 + copyTo 复制
• 2、利用鼠标左右键标志位控制选择区域
• 图像元素遍历 — 反色
• 由于对于图像像素比较之多，于是遍历算法就有一定的好坏之分，这里介绍如下几种：
• Mat 提供的函数模板 Mat::at
• 指针遍历 Mat::ptr Mat 的函数模板
• 使用 Mat 数据操作的迭代器MatIterator_
• 使用 Mat 的isContinuous 判断是否连续存储，在讲图像看成一行，按行展开
• LUT (Look Up Table)查表法，可以减少图像映射的时间复杂度(可用于替换、反转、赋值、阈值、二值化、灰度变化)
• 单窗口显示多幅图像
• 图像颜色空间转换 cvtColor
• 图像批量读取
• 文件名连续规则，可用 sptintf 函数
• 文件名不规则，可用 VC 下 WIN32_FIND_DATA 文件的读取方式进行

第三章 图像灰度变换技术

• 阈值化处理
• OTSU 阈值化
• 固定阈值化 threshold
• 双阈值化
• 半阈值化
• 直方图处理
• 灰度直方图
• H-S 直方图
• BGR 直方图
• 自定义直方图
• 灰度直方图均衡
• 彩色直方图均衡
• 直方图变换 — 查找
• 直方图变换 — 累计
• 直方图匹配
• 直方图对比
• 相关系数
• 卡方系数
• 相交系数
• 巴氏系数
• 直方图反向投影
• 距离变换
• 介绍 距离、邻接性、区域 的概念
• 距离变换 — 扫描
• 距离变换 — OpenCV 提供的 distanceTransform
• Gamma 校正： 是一种非线性变换，对输入的图像灰度值进行指数变换，进而校正亮度偏差，常用于扩展暗调的细节。当Gamma校正的值大于 1 时，高光部分被压缩而暗调部分被扩展。小于 1 时，反之。
• 常见的灰度变换技术
• 线性变换
• 对数变换
• 对比度拉伸
• 灰度级分层
• 灰度比特平面
• 实例应用
• 最大熵阈值分割
• 投影峰谷查找

第四章 图像平滑技术

• 图像采样： 上采样是讲图像分辨率扩大，下采样是将图像的分辨率缩小。
• 最邻近插值
• 双线性插值，应用广泛，稳定性高且时间复杂度较优
• 图像金字塔：是一系列图像的集合，所有多个分辨率图像来自同一个原始图像。常用于图像的缩放或图像分割。
• 向下采样 — 高斯金字塔
• 向上采样 — 拉普拉斯金字塔
• 傅里叶变换
• 图像掩码操作：通过掩码核算子重新计算每个像素的值。
• 基于像素邻域遍历
• 基于 filter2D 函数
• 离散傅里叶：将时域信号分解为不同频率的正弦波或余弦信号叠加之和。
• 图像卷积
• 图像噪声
• 椒盐噪声
• 高斯噪声
• 空间平滑
• 盒滤波
• 均值滤波
• 中值滤波
• 高斯滤波
• 双边滤波
• 实际应用
• 导向滤波：不仅能实现双边滤波的边缘平滑，而且在检测到边缘附近有较好的表现，可应用于图像增强、HDR压缩、图像抠图、及图像去雾等场景。
• 图像污点修复：用来解决小区域污染以重构原始图像，如：去除文本和Logo图标等场景中，利用重构去除图像中的划痕和污点。
• 旋转文本图像矫正，由于扫描仪扫描时未按照行列水平垂直扫描的现象。

第五章 边缘检测技术

• 边缘检测目的是检测识别出图像中亮度变化剧烈的像素点构成的集合。图像边缘的正确检测有利于分析目标检测、定位及识别。
• 根据边缘形成的原因，对图像进行求微分或者二阶微分可以检测出灰度变化明显的点。边缘检测大大减少了源图像的数据量，保留了图像的重要特征。常见的边缘检测分如下三种方式：
• 一阶微分为基础的边缘检测，Sobel算子、Prewitt算子、Roberts算子及差分边缘检测
• 二阶微分为基础的边缘检测，拉普拉斯算子、高斯算子、Canny算子边缘检测、
• 结合一阶与二阶微分为基础的边缘检测。
• 图像差分运算
• 非极大值抑制：可以剔除伪边缘信息。
• Sobel 算子
• 效率高。当精度要求不是很高时，可选用。它对于沿x 轴和y 轴的排列表示的较好，但是对于其他角度表示的不够精确。这时可以使用Scharr滤波器。
• 非极大值抑制 Sobel 检测
• 图像直接卷积实现 Sobel
• 图像卷积下非极大值抑制 Sobel
• 基本边缘检测算子 — Laplace：它是最简单的向同性的二阶微分算子，具有旋转不变性。根据函数微分特性可知，该像素点值的二阶微分为零的点为边缘点。
• 基本边缘检测算子 — Roberts 利用局部差分寻找边缘的一种算子，是最为简单的边缘检测算子。Roberts 算子利用对角线方向相邻两像素之差近似梯度幅值来检测边缘，检测垂直边缘效果好于其他方向，定位精度高，但对噪声的抑制能力差。
• 基本边缘检测算子 — Prewitt：它对噪音有抑制作用，原理和 Sobel 相似。都是在图像方向利用两个方向模板与图像进行邻域卷积完成，分别对水平和垂直方向边缘进行检测。准确性不如 Sobel 算子。
• 改进边缘检测算子 — Canny
• 原理是通过图像信号函数的极大值来判定图像的边缘像素点，性能较好。
• 最优边缘检测的评价标准有下面三个：
• 低错误率
• 高定位性
• 最小响应
• Canny 的原理及实现

• 消除噪声：由于导数通常对噪声很敏感。故边缘检测算法常常需要根据图像源数据进行预处理操作。必须利用滤波器来改善与噪音相关的边缘检测性能。常常先对原始数据与高斯模板进行卷积操作，得到的图像与原始图像相比有些轻微的模糊。即使用高斯平滑滤波器卷积降噪。
• 计算梯度幅值与方向。
• 非极大值抑制
• 用滞后阈值算法求解图像边缘
• 改进的边缘检测算子 — Marr–Hildreth

• 用于解决边缘检测的核心问题 — 定位精度与抑制噪声。它以高斯函数作为平滑算子，结合拉普拉斯算子提取二阶导数的零交叉理论进行边缘检测。称为LoG 函数，有被称为墨西哥草帽算子。
• 几何检测

• 霍夫变换：是从图像中识别几何形状的基本图像处理方法之一，应用广泛。经典的霍夫变换用来检测图像中的直线。改进的霍夫变换可以扩展到识别任意形状的物体。它不受图像旋转的影响，易于进行稽核图形的快速变换。
• 线检测技术
• LSD 快速直线检测，OpenCV3.0提供了 cv::LineSegmentDetector
• 形状检测
• 轮廓检测
• 凸包检测：是计算几何图像学中的概念，凸包就是将最外层的点连接起来构成凸多边形，它能包含点集中的所有点。物体的凸包检测常用于物体识别、手势识别及边界检测等领域。
• 轮廓边界框：物体轮廓检测出来后，我们常常会根据物体形态进行边界提取，常用的边界提取有矩形框、圆形框、椭圆形框等。
• OpenCV中提供了大量的轮廓、边缘及边界检测相关函数。
• approxPolyDP() 表示对多边形曲线做近似
• boundingRect() 表示计算并返回保卫轮廓点集中的最小矩阵；
• 函数 minEnclosingCircle()表示计算完全包围以有轮廓最小圆；
• 函数 minAreaRect() 表示计算二维点集形成封闭、倾斜、及最小面积的矩阵
• fitEllipse() 表示符合椭圆点集生成
• 轮廓矩：图像矩是通过对轮廓上所有的点进行积分运算而得到的一个粗略的特征。
• 点多边形测试：它用来判断点集是否在被测试多边形的内部，是轮廓点集判断的重要技术点之一。
• 角点检测
• moravec 角点
• harris 角点
• Shi-Tomasi 角点
• 实例应用
• 颜色圆检测
• 我们遇到的图像一般是真彩色图像，检测圆目标时常带着颜色信息，霍夫变换圆检测在颜色圆检测中主要解决两个问题：
• 检测输入函数集的所有圆，进行形状区分
• 尝试对颜色通道阈值化处理，分离特殊颜色圆
• 车牌区域检测

第六章 形态学技术

• 腐蚀膨胀操作
• 形态学膨胀操作，实现了对目标像素点进行扩展。
• 形态学腐蚀可以看成是膨胀的逆操作，腐蚀对原区域缩小。
• OpenCV 中提供了 erode() 和 dilate() 函数用于形态学腐蚀和膨胀操作。
• 开闭运算操作
• 形态学开操作能去除噪音及平滑目标边界。先对图像进行腐蚀操作，然后再进行膨胀操作。机构元素各向同性的开运算操作主要用于消除图像中小于结构元素的细节部分，物体局部形状不变。
• 形态学闭操作能填充目标区域内的离散小空洞和分散部分，先用结构元素 B 对 A 进行膨胀，然后再进行腐蚀。能够排除小型黑洞，消除低于邻近点的孤立点，达到去噪的作用，可以平滑物体轮廓。
• OpenCV 中提供了 morphologyEx 函数用于形态学开闭操作。
• 形态学梯度
• 梯度主要用于刻画目标边界或边缘位于图像灰度级别剧烈变化的区域，形态学梯度根据膨胀或腐蚀与原图像作差组合来实现增强结构元素邻域中像素的强度，突出高亮区域的外围。
• 形态学 Top-Hat ：指形态学顶帽操作与黑帽操作，前者是计算原图像与开运算结果图之差，后者是计算闭运算结果图与原图像之差，是一种常见的形态学滤波器，具有高通滤波器的某部分特性，可是想在图像中检测出周围背景亮结构或周围背景暗结构。顶帽常用于检测图像中的峰结构，黑猫常用于检测图像中的波谷结构。
• 实例应用：
• 形态学滤波角点提取：利用膨胀与腐蚀变化区域特征来完成边缘检测，膨胀是将目标物体向周围邻域扩展，而腐蚀是收缩，故将膨胀与腐蚀得到的结构图进行作差运算，就可以得到物体的边缘。在进行阈值化处理即可。
• 车牌目标提取

第七章 图像分割技术

• 分水岭分割
• 分水岭分割是基于模拟水流通过地形起伏的现象从而研究总结出的一种分割方法，其基本原理是将图像特征看作地理上的地貌特征，利用像素的灰度值分布特征，对每个符合特征的区域进行划分，形成边界以构成分水岭。
• 对于分水岭算法中的图像像素点，一般关注下面三个特征点：
• 局部最值点。
• 交汇边缘点
• 连接区域点
• 分水岭算法是一种很好的分割相互接触的物体图像的方式，但在边缘分割时精度存在一定问题。实际应用场景中，存在噪声或者其他干扰信息会导致局部极值点过多，就无法实现图像分割。
• 分水岭分割合并：首先计算分割部分的像素归属，利用直方图信息统计相关特征，对每个分割部分统计直方图对比的相似性，然后根据相似性判断分割的两个部分是否需要合并成一个区域。
• FloodFill 分割：泛洪填充算法，通常来说是自动选中与种子像素相关的区域，利用指定的颜色进行区域颜色替换，可用于标记或分离图像的某些部分。如 Windows 的油漆桶和Phottoshope 的魔术棒都是用它来改进和延伸的。
• FloodFill 算法原理很简单，就是从一个点开始遍历附近像素点，填充成新的颜色，直到封闭区域内的所有像素点都被填充成新颜色为止。它常见的有 4 邻域像素填充法、8邻域像素填充法、基于扫描线的像素填充方法。
• 均值漂移 MeanShift: 是一种核密度估计方法，用来分析复杂多模特征空间，其算法本质是最优化理论中的梯度下降法，沿着梯度下降方法寻找目标函数的极值。图像分割是找到每个像素点所属类中心，均值漂移认为类中心是概率密度的极大值点。对于任一像素沿着梯度方向总能找到其极值点。算法实现如下：
• 合并相似小区域
• 图割 Graphcut 是一种基于图论的分割方法，应用于前背景色分割、医学处理、纹理分割及立体视觉等方面。Grabcut是其改进算法。
• Graphcut 的目标和背景模型是灰度直方图，的能量最小化分割是通过一次计算实现的，需要输入前景与背景区域点集。
• Grabcut 采用的是 RGB 三通道混合高斯模型，根据分割模型参数更新完成的学习过程；只需要提供含有背景的区域像素集就可完成分割。
• 实例实践
• 1、奇异区域检测：通常是指与周围邻域有着某些特征(颜色或灰度) 差别的区域。常见的奇异区域如医学领域 X 光照片或 CT 某些特定组织、天空中降落等，奇异区域相对于点区域检测更稳定，在目标分割及检测、图像配准、特征分析等领域有广泛的应用。
• 计算机视觉中我们常常关注的目标特征是颜色和灰度，刻画图像中两个区域的视觉相似性有许多方法，如形状描述子、颜色特征、距特征等。
• 奇异区域检测主要是通过微分检测或局部极值的分水岭算法实现。基于图像中的奇异区域的邻域像素值或大或小的特征，我们可以通过计算图像中的局部极值点来实现相应兴趣区域的检测。一般实现奇异区域检测有如下两种方法：
• 基于微分检测器检测。拉普拉斯算子是检测图像奇异区域常用的方法，二维高斯经过拉普拉斯变换后的到。图像与高斯拉普拉斯函数进行卷积操作实际上求取的是图像与这一函数的相似性，奇异区域表现出来的特征就是图像中呈现比它周围像素灰度值大或小的区域，二维高斯拉普拉斯变换呈现出的就是这种特性。一般用它检测图像局部极值点时，需要先对图像进行低通滤波，去除伪点噪声。
• 基于局部极值的分水岭检测。局部极值的分水岭检测奇异区域是对原图像进行多间隔区域二值化操作，对一个二值化图像提取相应的连通域并计算相应区域的连通中心；根据中心点拟合归类成同一块 group,得到对应的 blob 特征；最后根据得到的中心点集group 估计出 blob 特征和对应的半径。
• 2、肤色检测
• 肤色检测利用了计算机对人体皮肤像素的分析过程，随着人脸检测技术、表情识别、手势识别等技术的快速发展，肤色应用的领域日益增多，它常用的方法有基于颜色空间、光谱特征、及肤色反射模型。这些方法主要步骤是先进行颜色空间变换，然后再建立肤色模型。颜色空间有 RGB、YCrCb、HSV和Lab等。皮肤模型中有单高斯模型、混合模型、贝叶斯模型和椭圆模型等，高斯分布模型用于刻画椭圆高斯概率，对肤色与非肤色采用高斯混合模型在特定的区域内能取得较好的实验效果。
• 其中 YCbCr 颜色空间是一种常见的肤色检测的色彩模型，其中 Y 代表亮度，Cr代表光源中的红色分量，Cb 代表光源中的蓝色分量。

第八章 特征分析

• 尺度空间：当利用计算机系统分析未知场景中的目标时，系统无法得知我们关注的目标物体的尺寸，因此，需要考虑如何描述目标物体的尺寸空间。
• 尺度与旋转不变性
• 对于目标物体，我们希望通过物体存在的一些显著区域的特征来描述它，对车辆进行描述时，读取车牌、轮胎、车标等特征，对人脸进行描述时，我们关注鼻子、眼睛、耳朵等特性。当利用计算机来分析目标物体图像时，我们重点关注的是目标与背景区域的差异性。
• 局部不变形是目标特征分析中重要的性质之一。它包括尺寸不变性和旋转不变性。尺寸不变性描述的是物体视觉上远近与目标的认知分析无关，摄像机相对物体远近呈现出来的物体尺寸不受其大小的影响。高尺度意味着目标物体越小，摄像机放置较远，低尺度反之。高尺度操作通常是利用图像平滑技术的高斯滤波或下采样，低尺度操作通常是利用高斯核核上采样。旋转不变性是物体发生旋转操作与目标认知分析无关，它强调目标特征的多角度信息特征。
• 特征点尺度变换
• 高斯核是唯一可以产生多尺度空间的核，高斯模板具有圆对称性，通过高斯卷积操作对原始像素重新分配权值，距离中心越远的相邻像素权值分配的相对较小。
• OpenCV 中提供了函数 cvSmooth 或 GaussianBlur 专门用于高斯卷积操作，利用这两个函数可进行图像尺寸空间的转换。
• 特征描述子：特征描述是目标分析技术之一，关键点检测与关键点提取是目标特征分析的重要步骤。局部图像特征描述的核心基本问题是不变性和可分性，不变性是基于特征描述对视角变化的不变性、尺度变化的不变性及旋转变化的不变性等，可分性是基于局部图像内容的可区分性。
• OpenCV 中常见的特征描述子有多种，如 SIFT、SURF、及ORB特征描述子。
• SiFT 是最为广泛的关键点检测和描述算法，关键点描述也称特征点描述，SIFT 特征提取充分利用了图像的局部信息。
• 它具有旋转、尺度、平移、视角及亮度的不变性，有利于对目标特征信息进行有效的表达。其外，它对参数调整鲁棒性好。
• SIFT 特征算法局部特征点的提取主要有四个步骤：
• 疑似关键点检测
• 去除伪关键点
• 关键点梯度
• 方向匹配及特征向量生成
• OpenCV 中提供了用于 Sift 特征描述及提取的类 SiftFeatureDetector 它继承于子类DescriptorExtractor
• 该算法实现的基本思路是，首先将源图像转换为灰度图像并归一化处理；接着定义 SIFT 描述子，分别计算两幅图像的特征点向量；然后利用 BruteForceMatcher 进行两幅图像的关键点匹配，对匹配结构的向量进行二分排序，根据排序结果筛选特征向量；最后去除特征点不匹配情况，输出最终特征点检测及匹配情况。
• SURF (Speed up Robust Features) 特征是对 SIFT 特征的改进，SIFT 算法最大的缺点是如果不借助硬件加速或专门的图像处理器很难达到实时。SURF 算法的实现原理借鉴了 SIFT 中的简化思想，把 DOH(高斯差分算子) 中高斯二阶微分的模板简化，是的卷积平滑操作仅需要转换成加减运算，SURF 算法的鲁棒性好且时间复杂度低。SURF 特征不仅能保持 SIFT 的尺寸不变性与旋转不变性，而且对光照变化和仿射变化同样具有很强的鲁棒性。
• SURF 算法使用了矩形盒滤波器来近似模拟高斯函数的二阶偏导数。矩形盒滤波器由简单的矩形模板构成，加快了卷积计算速度。减小了整个过程的时间复杂度。
• 它实现图像尺寸的不变性，同样采取了图像金字塔模型。SURF 特征点的方向取决于以兴趣点伪圆心，半径为 6 σ的圆形区域响应，计算其邻域每个点集的水平与垂直盒滤波器，即 Haar 特征。
• 生成 SURF 特征向量包含如下三个步骤：
• 构建特征点邻域的正方形区域，边长为 20 σ，其中 σ 为兴趣点的尺度，旋转正方形邻域到该特征点主方向。
• 将上一步骤构建的正方形区域划分成 4 * 4 个子区域，在每个子区域里，计算 5 * 5规则网络空间里的 4 维特征向量，该特征包含 Haar 小波对水平与垂直方向的响应和的绝对值。
• 计算每个子区域的 4 维特征并进行累加，将分成的 16 个子区域进行累计得到最终的 64 维特征向量描述子。
• ORB 特征：它是基于 FAST 角点的特征点检测与描述技术，它在运行时间远优于 SIFT 与 SURF,可应用于实时性特征检测。ORB 特征检测也具有尺度与旋转不变性，同时对噪声及仿射也具有不变性。ORB 特征检测主要一下面两个步骤：
• 方向 FAST 特征点检测，FAST 角点检测是一种基于机器学习的快速角点特征检测算法，具有方向的FAST 关键点检测是对兴趣点所在圆周的16个像素点进行判断，若判断后的当前中心像素为暗或者亮，将决定其是否为角点。FAST 角点检测为加速该算法，对圆周上的点集进行排序，使计算过程大大得到了优化。FAST 多尺度特性通过建立图像金字塔获得，引入灰度质心法用于实现特征点方向。
• BRIEF 特征描述：该算子主要通过随机选择兴趣点周围区域的若干点来组成小兴趣区域，将这些小兴趣区域的灰度二值化并解析成二进制码串，将串特征作为该特征点的描述子。由于它所有的编码都是二进制故节省了计算机的存储空间。
• 方向梯度直方图 HOG
• HOG 原理是通过计算和统计图像局部区域的梯度方向直方图来实现特征描述的。图像梯度方向直方图就是对图像中所有像素点 K 维特征的直方图统计，将图像划分成小部分连通域，对细胞单元的各个像素点进行梯度方向直方图描述，最后组合成相应的特征描述器。梯度方向直方图特征提取步骤如下：
• 归一化处理。
• 计算图像梯度
• 统计梯度方向
• 特征向量归一化
• 生成特征向量
• 局部二值模式 LBP
• LBP 是一种描述图像局部纹理的特征算子，该算子具有旋转不变性和灰度不变性等。经典的 LBP 算子定义为以窗口中心像素为阈值，将其相邻 8 邻域灰度图像与中心像素比较，若周围像素值大于中心像素值，该中心像素位置被标记为 1，否则为 0.
• 圆形 LBP 经典的 8-邻域来描述图像的纹理特征，其缺点是难以满足不同尺寸和频率的需求。提出将 3*3 正方形窗口邻域扩展到任意圆形邻域，圆形邻域满足半径为 R 可采样到N 个像素点。
• Haar 特征描述
• Haar 特征由黑白矩阵模板组成，特征值由白色矩阵和与黑色区域像素和相减得到。Haar 特征的计算量较大，一般进行特征描述时是通过计算积分图像来完成的。积分图也称求和表，每个区域只需要访问 4 次，然后进行 3 次求和就可以完成。
• 应用实例：

• 1、最近邻特征点目标提取：
• 快速最近邻逼近搜索函数库用来解决 SURF 高位特征向量空间中的最近邻搜索问题。由于高维空间计算量大，为了提高性能，采用分层 K-均值树和多重随机 KD 树。目前最有效的高维数据特征查找常采用 FLANN 最近邻算法。使用 FlannBasedMatcher 接口可实现目标特征点匹配，通过两幅图像的场景匹配情况就可以提取出感兴趣的目标区域。利用 FLANN 特征点匹配完成目标提取：
• 利用 SURF 特征提取待匹配目标关键点，利用 SurfFeatureDetecotr 实例构建特征点检测器，然后通过SurfDescriptorExtractor 描述器提取目标SURF 特征。
• 利用FlannBasedMatcher 对两幅图像SURF特征描述进行特征匹配检测，利用特征点距离特征进行最佳特征点筛选。
• 根据 drawMatches 实现匹配特征点绘制，然后构造仿射变换矩阵对检测出的特征点进行变换，最后根据变换矩阵实现目标提取。
• 2、最大值稳定区域匹配 MSER
• 它是一种类似分水岭图像分割与匹配算法，它具有SIFT、SURF及ORB 等特征不具备的仿射不变性。它被认为是当前性能最好的仿射不变性区域检测方法。
• 它的提取步骤如下：
• 像素点排序
• 极值区域生成
• 稳定区域判定
• 区域拟合
• 区域归一化
• 利用 MSER 完成候选车牌区域检测主要是通过MSER+ 和MSER- 来提取目标像素的区域点。根据极大值稳定区域形成原理，车牌字符区域存在明显的边缘分布与梯度分布，利用灰度及反值灰度提取出 MSER 特征点，在此基础上进行位与操作，最后检测出候选车牌区域。
• 3、字符特征提取
• 特征字符提取是计算机视觉场景中字符识别的关键技术之一，常应用于在车牌字符识别、OCR字符识别及公路指示牌字符识别等领域。
• 特征字符描述是根据待识别图像产生一组原始特征，在结合计算机视觉算法提取字符区域特有的显著特征，最后生成描述字符特征向量。字符分割经过归一化后，为了克服场景光照变化不同的影响，对单字符图像需先进行直方图均衡化。本节实现采用对单字符特征描述采用120维特征，其中利用简化梯度直方图特征（HOG) 64维，结合字符的水平投影32维与垂直投影16维，同时提取子窗口特征8维实现。
• 4、车牌字符 SVM 训练

第九章 复杂视频处理技术

视频稳像技术原理及实现、图像拼接 Stitcher、高动态范围 HDR 图像生成、背景建模—混合高斯模型、应用实例：车辆运动目标提取、TLD 单目标跟踪及人眼检测与跟踪

• 视频稳像技术：
• 它是解决由于某些原因产生的视频系列中的图像模糊问题，常见的图像模糊问题包括快速移动目标运动模糊、摄像头方向偏离/倾斜/翻转及图像坐标移动等。视频稳像技术是对随机抖动或运动摄像机所获得的动态图像进行重新处理，使其在图像输出时能稳定显示，这种技术能够消除或减弱图像序列之间的不规则移动、旋转及缩放等失真场景，进而提升图像质量。
• openCV3.x 中提供了专门应用于视频稳像技术的模块，该模块包含一系列用于全局运动图像估计的函数和类。如：videostab::RansacParams 等
• 视频稳像系统包含如下模块：运动估计、帧变换技术、运动补偿模块。该系统重点在于运动估计模块，局部或全局运动估计有多种方法，如：投影法、特征法、块匹配法及光流法。
• 运动估计是视频稳像系统的起始步骤，影响着整个系统性能，常通过 RANSAC (随机抽样一致性) 来实现连续帧间运动估计。该算法首先随机选取观察数据子集，通过这些子集来拟合相应的数学参数模型，然后进行观测点数据验证，RANSAC 通过反复选取数据集中的一部分子集来评估模型。
• RANSAC 可应用于图像特征点提取、图像全景拼接、图像匹配及图像搜索目标识别定位等场景。
• 图像拼接
• 图像拼接是利用连续帧图像生成全景图或者更高分辨率的图像，通常图像拼接需要消除图像拼接部分的缝隙间隔，因此需要进行重叠区域匹配修复。全景图像是平面图像映射到一个弯曲表面发生的图像投影。
• 图像拼接分为三个步骤：
• 特征点检测：对序列图像进行特征点检测，可使用OpenCV中提供的角点检测方法来对序列图像进行特征点提取。特征点筛选采用RANSAC 提取有效样本特征点。
• 图像标定
• 图像融合
• OpenCV 中提供了图像拼接库可实现图像间的缝合连接。
• 高动态范围图像 HDR
• HDR 合成技术：高动态范围 HDR 图像合成是利用计算机处理技术，将普通数字图像准换成高质量图像。场景中不同曝光度的图像的视觉效果各异，为了丰富视觉观察效果，HDR 应运而生。图像动态范围是指图像中像素亮度的最大值与最小值的比值，即最亮和最暗的灰度等级划分，动态范围越大，图像细节层次越丰富，表现形态越细腻，高动态范围用来描述最亮和最暗比值达到很高时的等级。它最大的变革就是来自于浮点数据的引入，采用浮点方式来处理和存放亮度数据。
• HDR 高动态范围图像生成，通常是根据图像的不同曝光度结合几何相机响应曲线标定和压缩算法完成 HDR 图像合成。
• OpenCV 中的 photo 模块提供了 HDR 图像生成相关函数及类。
• 背景建模
• 运动检测通常用于分析视频序列中的移动目标，如车辆和行人检测，所解决的问题是在场景中分离前景色与背景。背景建模是实现运动目标检测的基础之一，通过对原始场景的求解背景，利用当前图像帧与背景作差就可以粗略地实现运动目标区域点提取，通常每幅图像中检测到的运动目标是用其最小尺寸(如圆、椭圆、矩形及正方形等)来表示的。
• 背景差分：对两幅图像作差得到差分图像，视频序列中的当前帧视频图像减去背景将得到图像帧中的运动目标。OpenCV 中提供了函数absdiff()用于计算图像差分运算。
• 背景的建立并不是固定不变的，通常需要维护一个动态背景帧，最简单的背景建立是通过对过去 N 帧数据进行像素点统计，并计算像素点的均值或中值。这种背景建立方法简单，但对运动速度较慢。亮度变化小的目标存在统计丢失现象。
• 混合高斯背景建模
• 混合高斯模型既保存滑动平均值，同时也保存滑动方差，即把背景图像中的每个像素点分别用 K 个高斯的混合分布来描述。
• 在 OpenCV 中提供了BackgroundSubtractor 类用于实现背景建模算法。其中派生出的 BackgroundSubstractorMOG 是基于高斯混合模型的背景和前景分割算法。
• KNN 模型背景建模实现
• 该方法应用 K 邻近思想，实现前景目标变换较小场景下背景模型的建立。OpenCV 中实现了类 BackgroundSubtractorKNN
• GMG 模型背景建模
• 该方法基于数学统计背景模型估计，首先统计 RGB 颜色空间下直方图信息并进行量化，然后根据 T 帧图像训练初始化数据像素背景，在利用贝叶斯规则来计算一个像素被分类为前景色的可能性，最后通过背景模型特征更新参数生成前景目标。
• OpenCV 中提供了基于数学统计的背景模型类BackgroundSubtractorGMG 实现。
• 级联分类器 — 人脸检测
• 人脸检测有两大类：
• 基于几何特征，如眼睛、眉毛、鼻子及嘴巴的性对位置特征
• 级联分类器：是将若干个分类器进行连接，从而构成一个多项式级的强分类器方法，单个分类器可以由若干个弱分类器加权组成。
• 应用实例
• 运动目标提取根据实验场景内各个运动目标的情况，通过背景建模技术可实现实时运动目标检测。而就背景建模来说，从算法的时间复杂度来说，混合高斯及其改进方法对分辨率高的图像建立背景模型计算耗时大，因此需要考虑进行图像预处理操作。由于场景尺寸对于后端图像的分析影响较大，故首先考虑的就是对源图像进行缩放，在利用改性混合高斯模型进行背景提取。本节在实现运动目标提取时，首先利用图像下的采样双线性插值对源数据图像进行缩小操作，利用高斯混合模型背景建模得到运动目标区域，然后对区域进行形态学闭操作，填充运动目标区域的间断点，在对目标区域求解其连通域并选取连通域的最大外接矩阵，最后通过对车辆目标的基本形态筛选完成车辆的目标检测。
• TLD (Tracking-Learning-Detection)单目标跟踪可实现单目标长时间跟踪，该算法将检测与跟踪结合起来，它由三个模块构成，追踪器、检测器、及在线学习模块。追踪器完成跟踪连续帧间目标的运动情况，当目标始终可见时，追踪器才能实现其功能，追踪器可以根据上一帧的目标检测结果预测出当前帧目标可能出现的区域，得到正样本轨迹；检测器完成对追踪器的修正，对当前帧图像进行遍历，找到与目标物体相似的所有可能位置，从检测产生的结果中得到正负样本，检测器将所有检测窗口中最可信的位置作为 TLD 输出结果；在线学习模块根据追踪器与检测器得到的正负样本，迭代训练生成相应的分类器，实现检测器相应参数的修正与性能完善。在线学习模块采用了 P-N Learning 算法，是一种半监督机器学习算法。
• 人眼检测与跟踪：使用了用于人脸检测的级联分离器，检测出人脸位置，然后利用人眼级联分类器在人脸区域上检测出人眼目标，最后应用模块匹配技术实现人眼的自适应跟踪。

2018-08-08 14:00:09 qq_41905045 阅读数 112

1距

``````import numpy as np
import cv2 as cv

ret,thresh = cv.threshold(img,127,255,0)
im2,contours,hierarchy = cv.findContours(thresh, 1, 2)

cnt = contours[0]
M = cv.moments(cnt)
print( M )``````
 {'m00': 2.0, 'm10': 912.0, 'm01': 1198.0, 'm20': 415872.3333333333, 'm11': 546288.0, 'm02': 717602.3333333333, 'm30': 189638088.0, 'm21': 249107527.66666666, 'm12': 327226664.0, 'm03': 429844197.0, 'mu20': 0.3333333333139308, 'mu11': 0.0, 'mu02': 0.3333333332557231, 'mu30': 2.9802322387695312e-08, 'mu21': 1.6880221664905548e-09, 'mu12': 3.5390257835388184e-08, 'mu03': 1.1920928955078125e-07, 'nu20': 0.0833333333284827, 'nu11': 0.0, 'nu02': 0.08333333331393078, 'nu30': 5.268356063861754e-09, 'nu21': 2.984029801796697e-10, 'nu12': 6.256172825835833e-09, 'nu03': 2.1073424255447017e-08}

从这一刻起，你就可以提取出有用的数据，比如面积，中心id等等。中心id是由关系给出的，

``````cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])``````

2。轮廓面积

``area = cv.contourArea(cnt)``
``````import numpy as np
import cv2 as cv

ret,thresh = cv.threshold(img,127,255,0)
im2,contours,hierarchy = cv.findContours(thresh, 1, 5)

cnt = contours[0]
M = cv.moments(cnt)

area = cv.contourArea(cnt)
print(area)
cv.imshow("img2",img)

cv.waitKey(0)
``````
``````26514.0
``````

3。轮廓周长

``perimeter = cv.arcLength(cnt,True)``
``````import numpy as np
import cv2 as cv

ret,thresh = cv.threshold(img,127,255,0)
im2,contours,hierarchy = cv.findContours(thresh, 1, 5)

cnt = contours[0]
M = cv.moments(cnt)

perimeter = cv.arcLength(cnt,True)
print(perimeter)
cv.imshow("img2",img)

cv.waitKey(0)
``````
``1289.4329804182053``

``````epsilon = 0.1*cv.arcLength(cnt,True)
approx = cv.approxPolyDP(cnt,epsilon,True)``````

5。凸包

•

``````import numpy as np
import cv2 as cv

ret,thresh = cv.threshold(img,127,255,0)
im2,contours,hierarchy = cv.findContours(thresh, 1, 5)

cnt = contours[0]
M = cv.moments(cnt)
hull = cv.convexHull(cnt)

print(hull )

cv.imshow("img2",img)

cv.waitKey(0)
``````

6。检查凸性

``````import numpy as np
import cv2 as cv

ret,thresh = cv.threshold(img,127,255,0)
im2,contours,hierarchy = cv.findContours(thresh, 1, 5)

cnt = contours[0]
M = cv.moments(cnt)
k = cv.isContourConvex(cnt)

print(k)

cv.imshow("img2",img)

cv.waitKey(0)
``````
``````================= RESTART: C:\Users\ty\Desktop\qwe\teas11.py =================
False
``````

7。边界矩形

7.。直边界矩形

• 9。拟合椭圆

``````ellipse = cv.fitEllipse(cnt)
cv.ellipse(img,ellipse,(0,255,0),2)``````
``````import numpy as np
import cv2 as cv

ret,thresh = cv.threshold(img,127,255,0)
im2,contours,hierarchy = cv.findContours(thresh, 1, 5)

cnt = contours[0]
M = cv.moments(cnt)
ellipse = cv.fitEllipse(cnt)
cv.ellipse(img,ellipse,(0,255,0),2)
cv.imshow("img2",img)

cv.waitKey(0)
``````

• 10。拟合直线

• ``````rows,cols = img.shape[:2]
[vx,vy,x,y] = cv.fitLine(cnt, cv.DIST_L2,0,0.01,0.01)
lefty = int((-x*vy/vx) + y)
righty = int(((cols-x)*vy/vx)+y)
cv.line(img,(cols-1,righty),(0,lefty),(0,255,0),2)``````

2015-03-16 13:12:07 bingtangkafei 阅读数 1243

关键点：

patch半径为r，x、y区间为[r,-r]。

描述子：

1，对图像使用积分平滑处理（31*31像素上选取5*5子窗口）；

2，在特征点附近选取patch，用高斯分布采样方式，选取n对点对（n取256）；

3，比较点对：

4，获得一个n位二进制串，即BRIEF描述子；

BRIEF在平面旋转特性上表现差。改进方法：用关键点方向引导BRIEF。

patch主方向θ及方向矩阵，构建

1，建立一个300 000关键点的训练集，每个关键点选取31*31的patch；

2，选取5*5子窗口，共有N=(31-5+1)*(31-5+1)个字窗口，用5*5的平均强度代替单点强度；

3，选取点对，共有M=N*(N-1)/2种可能性；

4，300 000个关键点全部运行后，形成300 000*M矩阵，计算每一列平均值；

5，M个平均值按到0.5距离排序，将对应的列向量放入到T中；

6，将T中第一个列向量放入R中；

7，取T中下一列，与R中元素比较相关性。高于阀值，丢弃；否则，添加到R中；

8，重复7，直到R中有256列为止；若小于256，提高阀值，再次搜索。

R中的行元素，就是每个patch对用的256个点对。以上结果，我们称为rBRIEF。

2019-11-04 21:55:06 u010018991 阅读数 95