【图像特征提取1】方向梯度直方图HOG---从理论到实践------附带积分图像的解析
(一)特征检测算法的综述
(二)方向梯度直方图HOG的简介
(三)方向梯度直方图HOG算法的大致步骤如下所示:
1)归一化处理
2)分割图像
3)计算每个Cell的方向梯度直方图
4)特征向量归一化
为了克服光照不均匀的变化以及前景和背景测对比差异,需要对每个小区域计算出来的特征向量进行归一化处理。在程序中,我们直接使用OpenCV中的normalize函数中的CV_L2范数进行归一化处理。
5)HOG特征向量的生成
(四)积分图像
1)为什么要用积分图像
2)积分图像的概念
3)OpenCv中计算积分图像的C++接口
- //! computes the integral image
- CV_EXPORTS_W void integral( InputArray src, OutputArray sum, int sdepth=-1 );
- //! computes the integral image and integral for the squared image
- CV_EXPORTS_AS(integral2) void integral( InputArray src, OutputArray sum,OutputArray sqsum, int sdepth=-1 );
- //! computes the integral image, integral for the squared image and the tilted integral image
- CV_EXPORTS_AS(integral3) void integral( InputArray src, OutputArray sum,OutputArray sqsum, int sdepth=-1 );
这样的话,如果我们需要计算图像中任意的某一特定区域的像素强度的话,我们只需要进行加减运算,而不需要变量图像。例如现在我们需要计算像素点P0,P1,P2,P3围城的矩形区域的像素强度累加,只需要按照下面的这个公式计算就可以了:
矩形区域的像素强度值 = P3 -P1 - P2 + P0
另外,由于网上关于积分图的概念和定义不是那么的一致,现在我们给出OpenCv官方文档的参考资料,关于积分图的计算介绍如下所示:
(五)基于OpenCv和C++方向梯度直方图HOG特征向量描述符的实现
- /********************************************************************************************************
- 文件说明:
- HOG特征描述符的实现
- 算法思路:
- 1)将图片加载入内存,并且利用cvtColor将图像转换为grayImg
- 2)利用一阶微分算子Sobel函数,分别计算出grayImg图像X方向和Y方向上的一阶微分/梯度图像
- 3)根据得到的两幅梯度图像(X方向上的梯度图像和Y方向上的梯度图像),然后利用cartToPolar函数,计算出这
- 两幅梯度图像所对应的角度矩阵图像angleMat和梯度幅值矩阵图像magnMat
- 4)将角度矩阵图像angleMat里面的像素强度值归一化为强度范围在[0,9)这9个范围,每一个范围就代表HOG中
- 的一个bins
- 5)以角度为为索引,将梯度幅值图像矩阵magnMat按照九个方向的梯度角度拆分为9幅梯度幅值图像矩阵
- 6)根据这9个角度,每个角度所对应的梯度幅值图像矩阵,并且利用OpenCv中的积分函数integral分别计算出这9
- 幅图像所对应的积分图像
- ==============至此,我们9个梯度方向上,分别对应的的9幅梯度幅值积分图已经计算完毕==================
- 7)计算整幅图像的梯度方向直方图HOG:要计算整幅图像的,需要先计算每个Block的HOG;要计算每个Block的HOG
- 要先计算每个Cell的HOG
- 8)计算单个Cell的HOG:由于9个梯度方向上的9张梯度幅值积分图像已经计算出来,所以这一步的计算很简单,只需
- 要记性加减计算,具体的函数为cacHOGinCell
- 9)计算单个Block的HOG:将计算出来的4个Cell的HOG组成一个Block的HOG
- 10)计算整幅图像的HOG:将计算出来的所有的Block的HOG梯度方向直方图的特征向量首尾相接组成一个维度很大的
- 整幅图像的梯度方向直方图的HOG特征向量,这个特征向量就是整幅图像的梯度方向直方图特征,这个特征
- 向量也可以被用于SVM的分类
- 算法难点:
- 1)积分图像的概念:网上有关积分图像的Blog一大推,但是很多讲的都不准确,最好的办法是看OpenCv的官方文档
- 关乎积分函数的讲解,可以结合网上的资料看
- 2)笛卡尔空间坐标和极坐标的转换(关键是理解一些它们之间相互转换的前提条件)
- 3)L1范数和L2范数:在使用归一化normalize函数时,考虑一些CV_L2到底是向量的L2范数还是矩阵的L2范数,自己
- 可以推到一下公式
- 4)关于HOG的论文,没有使用到积分图的概念,其实在HOG中使用积分图像加速了HOG的计算速度,如果使用先计算
- 梯度,在计算各个区域的梯度方向和梯度幅值的话,这样计算了太大,会导致HOG的性能有所下降
- 5)还有,这里的每个Cell的大小是20p*20p,每个Block的大小为4个Cell;当然如果用于行人检测的话,也可以使用
- 其他的3*3或者5*5组合
- 开发环境:
- Win7 + OpenCv2.4.8 + VS2012
- 时间地点:
- 陕西师范大学 2017.3.14
- 作 者:
- 九 月
- *********************************************************************************************************/
- #include <opencv2/opencv.hpp>
- #include <opencv2/highgui/highgui.hpp>
- #include <opencv2/nonfree/features2d.hpp>
- #include <iostream>
- using namespace cv;
- using namespace std;
- #define NBINS 9
- #define THETA 180 / NBINS
- #define CELLSIZE 20
- #define BLOCKSIZE 2
- #define R (CELLSIZE * (BLOCKSIZE) * 0.5)
- /********************************************************************************************************
- 函数功能:
- 计算积分图像
- 参数说明:
- Mat& srcMat-----------------------存储每个cellHOG特征的行特征向量
- 2)cv::Rect roi--------------------单个cell的矩形位置
- 3)std::vector<Mat>& integrals-----存储的9幅积分图像,每一幅积分图像代表一个角度范围或者一个bins
- *********************************************************************************************************/
- // 计算积分图
- std::vector<Mat> CalculateIntegralHOG(Mat& srcMat)
- {
- //【1】计算一阶微分的梯度图像
- cv::Mat sobelMatX;
- cv::Mat sobelMatY;
- cv::Sobel(srcMat, sobelMatX, CV_32F, 1, 0);
- cv::Sobel(srcMat, sobelMatY, CV_32F, 0, 1);
- std::vector<Mat> bins(NBINS);
- for (int i = 0; i < NBINS; i++)
- {
- bins[i] = Mat::zeros(srcMat.size(), CV_32F);
- }
- cv::Mat magnMat;
- cv::Mat angleMat;
- //【2】坐标转换,根据每一个点X方向和Y方向上的梯度,实现笛卡尔坐标和极坐标的转换
- cartToPolar(sobelMatX, sobelMatY, magnMat, angleMat, true);
- //【3】下面这这两行代码起始是做安全处理的,因为在将笛卡尔坐标转换为极坐标之后,角度的范围在[0,360]
- // 下面这两行代码让所有的角度收缩在[0,180]这个返回
- add(angleMat, Scalar(180), angleMat, angleMat<0); //如果angleMat<0,则加180
- add(angleMat, Scalar(-180), angleMat, angleMat >= 180); //如果angleMat>=180,则减180
- //【4】下面这行代码将角度矩阵转换为一个灰度值范围在[0,9]之间的图像
- angleMat /= THETA;
- //【5】下面这个循环,其实是将图像的梯度幅值矩阵按九个不同方向的梯度角度,将每个角度范围内相应点的梯度幅值
- // 存储在相应的矩阵图像之上,其实就是将梯度幅值矩阵图像按照不同的梯度幅值角度分为9幅梯度幅值的图像
- for (int y = 0; y < srcMat.rows; y++)
- {
- for (int x = 0; x < srcMat.cols; x++)
- {
- int ind = angleMat.at<float>(y, x);
- bins[ind].at<float>(y, x) += magnMat.at<float>(y, x);
- }
- }
- //【6】根据上面生成的9张不同角度的梯度幅值矩阵生成9张不同的梯度幅值的积分图像,至此以后,
- // 积分图像的每一点就代表,这一点左上角,所有梯度幅值之和;生成的9幅积分图也就是9个
- // bins,不同bins上的HOG强度
- std::vector<Mat> integrals(NBINS);
- for (int i = 0; i < NBINS; i++)
- {
- integral(bins[i], integrals[i]);
- }
- return integrals;
- }
- /********************************************************************************************************
- 函数功能:
- 计算单个cell HOG特征
- 参数说明:
- 1)cv::Mat& HOGCellMat-------------存储每个cellHOG特征的行特征向量
- 2)cv::Rect roi--------------------单个cell的矩形位置
- 3)std::vector<Mat>& integrals-----存储的9幅积分图像,每一幅积分图像代表一个角度范围或者一个bins
- *********************************************************************************************************/
- void cacHOGinCell(cv::Mat& HOGCellMat,cv::Rect roi,std::vector<Mat>& integrals)
- {
- //【1】通过9幅积分图像快速实现HOG的计算,HOG这个直方图有9个bins,每个bins就对应一张积分图像
- int x0 = roi.x; //确定单个矩形cell的左上角点坐标
- int y0 = roi.y;
- int x1 = x0 + roi.width;
- int y1 = y0 + roi.height; //确定单个矩形cell的右下角点坐标
- for(int i = 0;i <NBINS; i++)
- {
- //【2】根据矩形的左上角点和右下角点的坐标
- cv::Mat integral = integrals[i];
- float a = integral.at<double>(y0,x0);
- float b = integral.at<double>(y1,x1);
- float c = integral.at<double>(y0,x1);
- float d = integral.at<double>(y1,x0);
- HOGCellMat.at<float>(0,i) = b - c - d +a;//每循环一次,计算一个梯度方向上的HOG特征,其实就是
- //每循环一次,就计算梯度方向直方图上的一个bins
- }
- }
- /********************************************************************************************************
- 函数功能:
- 获取当前窗口的HOG直方图----此块其实就是在计算单个Block的HOG梯度方向直方图
- 参数说明:
- 1)cv::Point pt--------------------单个Block的中心点坐标
- 2)std::vector<cv::Mat>& integrals-----存储的9幅积分图像,每一幅积分图像代表一个角度范围或者一个bins
- *********************************************************************************************************/
- cv::Mat getHog(cv::Point pt,std::vector<cv::Mat>& integrals)
- {
- if(pt.x - R<0||pt.y-R<0||pt.x+R>=integrals[0].cols||pt.y+R>=integrals[0].rows)
- {
- return cv::Mat();
- }
- //【1】BLOCK的HOG直方图---具体的来说,BLOCKSIZE*BLOCKSIZE即4个cell的HOG特征直方图特征向量
- // 组成一个BLOCK的HOG特征直方图的特征向量
- cv::Mat hist(cv::Size(NBINS*BLOCKSIZE*BLOCKSIZE,1),CV_32F);
- cv::Point t1(0,pt.y-R);
- int c = 0;
- //【2】遍历块:通过下面这两个循环,就遍历了4个cell,并且将4个cell的HOG特征向量组成了一个
- // 维数比较大的BLOCK的HOG特征向量
- for(int i=0;i<BLOCKSIZE;i++)
- {
- t1.x = pt.x - R;
- for(int j=0;j<BLOCKSIZE;j++)
- {
- //【3】获取当前窗口,进行局部HOG直方图计算
- cv::Rect roi(t1,t1+cv::Point(CELLSIZE,CELLSIZE));
- cv::Mat hist_temp = hist.colRange(c,c+NBINS);
- //【4】根据roi确定的矩形区域,计算单个cell的HOG直方图(其本质就是一个行特征向量)
- cacHOGinCell(hist_temp,roi,integrals);
- t1.x += CELLSIZE;
- c += NBINS;
- }
- t1.y = CELLSIZE;
- }//for i
- //【3】利用范数2进行归一化
- cv::normalize(hist,hist,1,0,NORM_L2);
- return hist;
- }
- /********************************************************************************************************
- 函数功能:
- 计算整幅图像的HOG梯度方向直方图---HOG特征
- 参数说明:
- cv::Mat srcImage------原始的输入彩色图像
- *********************************************************************************************************/
- std::vector<Mat> cacHOGFeature(cv::Mat srcImage)
- {
- cv::Mat grayImage;
- std::vector<Mat> HOGMatVector;
- cv::cvtColor(srcImage, grayImage, CV_RGB2GRAY);
- grayImage.convertTo(grayImage, CV_8UC1);
- //【1】9个不同梯度方向上的9张梯度幅值的积分图像的生成
- std::vector<Mat> integrals = CalculateIntegralHOG(grayImage);
- Mat image = grayImage.clone();
- image *= 0.5;
- //【2】变量全图像,计算最终的梯度方向直方图HOG
- cv::Mat HOGBlockMat(Size(NBINS, 1), CV_32F);
- for (int y = CELLSIZE / 2; y < grayImage.rows; y += CELLSIZE)
- {
- for (int x = CELLSIZE / 2; x < grayImage.cols; x += CELLSIZE)
- {
- //【3】获取当前窗口HOG,其实当前的窗口就是一个Block,每个Block由四个cell组成,每个Cell为20*20
- // 此块,计算的就是单个Block的梯度方向直方图HOG
- cv::Mat hist = getHog(Point(x, y), integrals);
- if (hist.empty())continue;
- HOGBlockMat = Scalar(0);
- for (int i = 0; i < NBINS; i++)
- {
- for (int j = 0; j < BLOCKSIZE; j++)
- {
- HOGBlockMat.at<float>(0, i) += hist.at<float>(0, i + j*NBINS);
- }
- }
- //【4】L2范数归一化:对其得到的每个Block的的矩阵进行L2范数归一化,使其转变为一个Block的HOG特征向量
- normalize(HOGBlockMat, HOGBlockMat, 1, 0, CV_L2);
- //【5】最后,每得到一个Block的HOG特征向量就存入HOGMatVector,这个HOGMatVector其实就是整个图像的HOG特征向量,
- // 当然,现在这个HOGMatVector还是个二维数组的形式,如果想要利用SVM对其进行分类的话,还需要将其拉伸为一
- // 维特征向量
- HOGMatVector.push_back(HOGBlockMat);
- Point center(x, y);
- //【6】绘制HOG特征图
- for (int i = 0; i < NBINS; i++)
- {
- double theta = (i * THETA ) * CV_PI / 180.0;
- Point rd(CELLSIZE*0.5*cos(theta), CELLSIZE*0.5*sin(theta));
- Point rp = center - rd;
- Point lp = center + rd;
- line(image, rp, lp, Scalar(255 * HOGBlockMat.at<float>(0, i), 255, 255));
- }
- }
- }
- imshow("out", image);
- return HOGMatVector;
- }
- /********************************************************************************************************
- 模块功能:
- 控制台应用程序的入口:Main函数
- *********************************************************************************************************/
- int main()
- {
- cv::Mat srcImage = cv::imread(".\\images\\hand1.jpg");
- if (srcImage.empty())
- return -1;
- cv::imshow("srcImage ", srcImage);
- std::vector<Mat> HOGFeatureMat = cacHOGFeature(srcImage);
- cv::waitKey(0);
- return 0;
- }
【图像特征提取1】方向梯度直方图HOG---从理论到实践------附带积分图像的解析相关推荐
- 图像特征:方向梯度直方图 HOG
文章目录 参考资料 简介 算法流程 灰度化和gamma校正 计算梯度 统计cell的梯度方向直方图 Block 块内归一化(重点) 组合为HOG特征 HOG特征与可视化 OpenCV 算法实现 参考资 ...
- 图像学习之如何理解方向梯度直方图HOG(Histogram Of Gradient)
本文转自:雷锋网,作者:思颖.连接:https://yq.aliyun.com/articles/176607,https://www.leiphone.com/news/201708/ZKsGd2J ...
- OpenCV方向梯度直方图HOG的实例(附完整代码)
OpenCV方向梯度直方图HOG的实例 OpenCV方向梯度直方图HOG的实例 OpenCV方向梯度直方图HOG的实例 #include <iostream> #include <f ...
- 图像特征提取算法:方向梯度直方图HOG
1.基本介绍 HOG,全称是方向梯度直方图(Histogram Of Gradient),是目前计算机视觉.模式识别领域很常用的一种描述图像局部纹理的特征.这个特征名字起的也很直白,就是说先计算图片某 ...
- opencv打卡66: 方向梯度直方图(HOG)第一步:梯度幅值・梯度方向
1.介绍 2.代码 import cv2 import numpy as np import matplotlib.pyplot as plt# get HOG step1 def HOG_step1 ...
- 深度学习----CNN的图像学习之HOG(方向梯度直方图)详解
一.原理 二.参数的理解 2.1.灰度值 2.2.归一化 2.3.细胞 2.4.窗口 2.5.类型 2.6.Gamma标准化 2.7.图像梯度及梯度算子 2.8.直方图 2.9.高斯空域加窗 三.步骤 ...
- 图像学习之如何理解方向梯度直方图(Histogram Of Gradient)
特征描述子(Feature Descriptor) 特征描述子就是图像的表示,抽取了有用的信息,丢掉了不相关的信息.通常特征描述子会把一个w*h*3(宽高3,3个channel)的图像转换成一个长度为 ...
- 方向梯度直方图(Histogram Of Gradient)详解
特征描述子(Feature Descriptor) 特征描述子就是图像的表示,抽取了有用的信息,丢掉了不相关的信息.通常特征描述子会把一个w*h*3(宽高3,3个channel)的图像转换成一个长度为 ...
- HOG特征提取原理and计算步骤,方向梯度直方图
HOG简介 方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子.它通过计算和统计图像局部区域的梯度方 ...
最新文章
- java thread参数传递_将参数传递给Java Thread
- Http Chunked Transfer Coding
- .net平台下C#socket通信(中)
- 使用Eclipse trace Application的启动
- 关于SAP Spartacus重载(override)UserAuthenticationTokenService的问题
- win32 禁用缩放功能_Firefox 73 将引入全局缩放功能,在所有网站都可适用
- python写日志文件_Python logging日志模块 配置文件方式
- OO_2019_第一单元总结——表达式求导
- python类属性用法总结
- 使用Easy CHM工具对文件生成API文档
- java老九_【老九】【Java】小议转义字符
- Redis和MongoDB的区别(面试受用)
- 昔人已乘黄鹤去 此地空余黄鹤楼-崔颢
- 计算机中的负数的表示
- Golang日志框架lumberjack包源码分析
- JSP基础知识总结一
- 计算机科学与技术导论ppt,计算机科学与技术专业导论.ppt
- 利率为0.8%,求需要多少个月才能还清?
- 阿里前CEO卫哲:我特别反对无人便利店 凤凰新闻 08-24 10:55 原标题:阿里前CEO卫哲:我特别反对无人便利店 卫哲,32岁就成长为史上最年轻的世界500强中国区总裁,36岁成为阿里巴巴CE
- windows server2012无法安装IIS,提示:安装一个或多个角色、角色服务或功能失败
热门文章
- qt android刘海屏状态栏,华为Mate30 Pro设计曝光:仍配刘海屏+3D结构光
- api arx autocad_AutoCAD ObjectARX(VC)开发基础与实例教程 此书是利用ObjectARX对AutoCAD二次开发的教程 - 下载 - 搜珍网...
- java实时读取文件内容,java实时读取和写入文件
- php的类有全局变量吗_解析在PHP中使用全局变量的几种方法
- SpringCloud微框架系列整体模块梳理
- android自定义View学习(二)----自定义绘图
- 基于JAVA+Swing+MYSQL的研究生科研信息管理系统
- Android 面试题总结
- linux 命令笔记
- 站立会议中发现的一些新问题