OPENCV C++(八)HOG的实现

hog适合做行人的识别和车辆识别 对一定区域的形状描述方法

可以表示较大的形状 把图像分成一个一个小的区域的直方图

用cell做单位做直方图 

计算各个像素的梯度强度和方向

用3*3的像素组成一个cell 3*3的cell组成一个block来归一化 提高亮度不变性

常用SVM分类器一起使用 进行行人分类

代码思路:

将图像分成cell为单位 例如把图像分成9*9像素的cell为单位。用sobel计算梯度大小和方向。

遍历每一个cell,一个cell可以分8类,用角度当作数组的下标,也就是分类的依据,数组的大小也就是分类的一个类的大小就是梯度的大小相加。

计算两个图的直方图的直方图距离的大小累加值


计算hog直方图函数:

int calcHOG(cv::Mat src, float* hist, int nAngle, int cellSize)
{int nX = src.cols / cellSize;int nY = src.rows / cellSize;int binAngle = 360 / nAngle;Mat gx, gy;Mat mag, angle;Sobel(src, gx, CV_32F, 1, 0, 1);Sobel(src, gy, CV_32F, 0, 1, 1);cartToPolar(gx, gy, mag, angle, true);Rect roi;roi.x = 0;roi.y = 0;roi.width = cellSize;roi.height = cellSize;for (int i = 0; i < nY; i++) {for (int j = 0; j < nX; j++) {Mat roiMat;Mat roiMag;Mat roiAgl;roi.x = j * cellSize;roi.y = i * cellSize;//赋值图像roiMat = src(roi);roiMag = mag(roi);roiAgl = angle(roi);//当前cell第一个元素在数组中的位置int head = (i * nX + j) * nAngle;for (int n = 0; n < roiMat.rows; n++) {for (int m = 0; m < roiMat.cols; m++) {//计算角度在哪个bin,通过int自动取整实现int pos = (int)(roiAgl.at<float>(n, m) / binAngle);//以像素点的值为权重hist[head + pos] += roiMag.at<float>(n, m);}}}}return 0;}

mag梯度大小强度  angle是角度的mat

传入的参数就是:图像,直方图数组,分成几个angle类型(一般是8个),cell的大小。

计算两个直方图的距离 

float normL2(float* Hist1, float* Hist2, int size)
{float sum = 0;for (int i = 0; i < size; i++) {sum += (Hist1[i] - Hist2[i]) * (Hist1[i] - Hist2[i]);}sum = sqrt(sum);return sum;
}

第一种是自己申明数组 然后做hog

	Mat temple = imread("hogTemplate.jpg",0);Mat img1 = imread("img1.jpg",0);Mat img2 = imread("img2.jpg",0);float his[3000] = { 0 };float his1[3000] = { 0 };float his2[3000] = { 0 };printf("%d %d\r\n",temple.cols,temple.rows);calcHOG(temple, his, 8, 9);calcHOG(img1, his1, 8, 9);calcHOG(img2, his2, 8, 9);float summ = normL2(his, his1, 3000);float summ2 = normL2(his, his2, 3000);cout << summ <<"\r\n" << endl;cout << "------" << endl;cout << summ2 <<"\r\n" << endl;

用动态开辟内存数组来进行hog

	int nX = refMat.cols / blockSize;int nY = refMat.rows / blockSize;int bins = nX * nY * nAngle;float* ref_hist = new float[bins];memset(ref_hist, 0, sizeof(float) * bins);float* pl_hist = new float[bins];memset(pl_hist, 0, sizeof(float) * bins);float* bg_hist = new float[bins];memset(bg_hist, 0, sizeof(float) * bins);

 这是比较关键的代码 就是动态开辟一个内存

	delete[] ref_hist;delete[] pl_hist;delete[] bg_hist;destroyAllWindows();

记得要释放内存!

完整代码:

	cv::Mat refMat = imread("hogTemplate.jpg");cv::Mat plMat = imread("img1.jpg");cv::Mat bgMat = imread("img2.jpg");int nAngle = 8;int blockSize = 9;int nX = refMat.cols / blockSize;int nY = refMat.rows / blockSize;int bins = nX * nY * nAngle;float* ref_hist = new float[bins];memset(ref_hist, 0, sizeof(float) * bins);float* pl_hist = new float[bins];memset(pl_hist, 0, sizeof(float) * bins);float* bg_hist = new float[bins];memset(bg_hist, 0, sizeof(float) * bins);int reCode = 0;reCode = calcHOG(refMat, ref_hist, nAngle, blockSize);reCode = calcHOG(plMat, pl_hist, nAngle, blockSize);reCode = calcHOG(bgMat, bg_hist, nAngle, blockSize);float dis1 = normL2(ref_hist, pl_hist, bins);float dis2 = normL2(ref_hist, bg_hist, bins);std::cout << "distance between reference and img1:" << dis1 << std::endl;std::cout << "distance between reference and img2:" << dis2 << std::endl;(dis1 <= dis2) ? (std::cout << "img1 is similar" << std::endl) : (std::cout << "img2 is similar" << std::endl);delete[] ref_hist;delete[] pl_hist;delete[] bg_hist;destroyAllWindows();return 0;
}

 

有没有很疑惑 为啥两种计算的方式 他们hog值不一样?

因为第一种我把他灰度化了 所以值偏低,我们现在把第二种方法的也灰度化

 ok 简直一摸一样 结束实验

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/57769.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字图像处理 --- 相机的内参与外参(CV学习笔记)

Pinhole Camera Model&#xff08;针孔相机模型&#xff09; 针孔相机是一种没有镜头、只有一个小光圈的简单相机。 光线穿过光圈并在相机的另一侧呈现倒立的图像。为了建模方便&#xff0c;我们可以把物理成像平面(image plane)上的图像移到实际场景(3D object)和焦点(focal p…

代码分析Java中的BIO与NIO

开发环境 OS&#xff1a;Win10&#xff08;需要开启telnet服务&#xff0c;或使用第三方远程工具&#xff09; Java版本&#xff1a;8 BIO 概念 BIO(Block IO)&#xff0c;即同步阻塞IO&#xff0c;特点为当客户端发起请求后&#xff0c;在服务端未处理完该请求之前&#xff…

UE中低延时播放RTSP监控视频解决方案

第1章 方案简介 1.1 行业痛点 在各种智慧城市、智慧社区、智慧水利、智慧矿山等数字孪生项目中&#xff0c;经常使用通UE来开发三维可视化场景。在这些场景中通常都需要把现场的各种监控视频在UE的可视化场景中接入&#xff0c;主要包含海康威视、大华、宇视、华为等众多监控…

网络编程——数据包的组装和拆解

数据包的组装和拆解 一、数据包在各个层之间的传输 二、各个层的封包格式 1、链路层封包格式 -------------------------------------------------------------------------------------------------------------------------------------- | 目标MAC地址&#xff08;6字节&a…

WebView2对比CefSharp的超强优势

第一次使用了CefSharp组件&#xff0c;集成开发结束后&#xff0c;测试及使用过程中遇到了一些无法处理的bug及严重的性能问题。然后又测试对比了其他多种组件&#xff0c;具体情况可以阅读我的博客​ ​《.NET桌面程序集成Web网页开发的十种解决方案》​​。最终选用了微软新出…

Ubuntu 22.04安装和使用ROS1可行吗

可行。 测试结果 ROS1可以一直使用下去的&#xff0c;这一点不用担心。Ubuntu会一直维护的。 简要介绍 Debian发行版^_^ AI&#xff1a;在Ubuntu 22.04上安装ROS1是可行的&#xff0c;但需要注意ROS1对Ubuntu的支持只到20.04。因此&#xff0c;如果要在22.04上安装ROS1&am…

中间件多版本冲突的4种解决方案和我们的选择

背景 在小小的公司里面&#xff0c;挖呀挖呀挖。最近又挖到坑里去了。一个稳定运行多年的应用&#xff0c;需要在里面支持多个版本的中间件客户端&#xff1b;而多个版本的客户端在一个应用里运行时会有同名类冲突的矛盾。在经过询问chatGPT&#xff0c;百度&#xff0c;googl…

linux下.run安装脚本制作

1、安装文件(install.sh) PS: .run安装包内部执行脚本文件 2、资源文件(test.zip) PS: 待安装程序源文件 3、制作.run脚本(install.run) cat install.sh test.zip > install.run chmod ax install.run

【软件工程】3 ATM系统的设计

目录 3 ATM系统的设计 3.1体系结构设计 3.2 设计模式选择 3.3 补充、完善类图 3.4 数据库设计 3.4.1 类与表的映射关系 3.4.2 数据库设计规范 3.4.3 数据库表 3.5 界面设计 3.5.1 界面结构设计 3.5.2 界面设计 3.5.2.1 功能界面设计 3.5.2.2 交互界面 总博客&…

基于Python++PyQt5马尔科夫模型的智能AI即兴作曲—深度学习算法应用(含全部工程源码+测试数据)

目录 前言总体设计系统整体结构图系统流程图 运行环境Python 环境PC环境配置 模块实现1. 钢琴伴奏制作1&#xff09;和弦的实现2&#xff09;和弦级数转为当前调式音阶3&#xff09;根据预置节奏生成伴奏 2. 乐句生成1&#xff09;添加音符2&#xff09;旋律生成3&#xff09;节…

SpringBoot + Docker 实现一次构建到处运行~

一、容器化部署的好处 图片 Docker 作为一种新兴的虚拟化方式&#xff0c;它可以更高效的利用系统资源&#xff0c;不需要进行硬件虚拟以及运行完整操作系统等额外开销。 传统的虚拟机技术启动应用服务往往需要数分钟&#xff0c;而 Docker 容器应用&#xff0c;由于直接运行…

linuxARM裸机学习笔记(7)----RTC实时时钟实验

基础概念&#xff1a; I.MX6U 内部也有个RTC 模块&#xff0c;但是不叫作“ RTC ”&#xff0c;而是叫做“ SNVS ”。 SNVS 直译过来就是安全的非易性存储&#xff0c; SNVS 里面主要是一些低功耗的外设&#xff0c;包括一个 安全的实时计数器 (RTC) 、一个单调计数器 (mo…