方向梯度直方图HOG(理解与c++代码实现)

本文介绍了方向梯度直方图(HOG)的概念,并提供了C++代码实现,包括提取细胞中梯度方向直方图、每个块的特征以及整个图像的HOG特征。代码可供学习参考,适用于视觉跟踪中的HOG特征理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方向梯度直方图HOG(理解与c++代码实现)

菜鸟一个,学习视觉跟踪要用到HOG特征,想要深入了解一下HOG特征,但是找了半天很多人的介绍都没有代码,还有的有部分代码,想要全部的代码,还要花钱下载,很不爽,我这里练习写了一个,不怎么好,但是可以加深对于特征的理解,有兴趣的可以参考一下。

首先,对于HOG的理解可以参考这篇博客
https://blog.youkuaiyun.com/u013066730/article/details/83015490
也是一篇转载的,但是没找到原链接。
后面的我写的代码就是参考这里面的步骤。
开发环境:

Ubuntu16.04 + QT5 + CMake3.11.3 + OpenCV3.4.7 

先把CMakeLists.txt文件列在这里:


cmake_minimum_required(VERSION 2.8)
add_compile_options(-std=c++11)
project(getHOG)
aux_source_directory(. SRC_LIST)

find_package(OpenCV REQUIRED)
include_directories(${
   OpenCV_INCLUDE_DIRS} ${
   SOURCE_DIR} )
add_executable(${
   PROJECT_NAME}  "main.cpp")
target_link_libraries(${
   PROJECT_NAME} ${
   OpenCV_LIBS})

用于测试的图像
在这里插入图片描述

1.提取cell中的梯度方向直方图并且显示出来

main.cpp


#include <iostream>
#include <math.h>
#include <string.h>
#include <opencv2/opencv.hpp>

#define PI (3.1415927)
#define CELL_SIZE  (8)  //8*8大小cell
#define BLOCK_SIZE  (2) //2*2个cell
#define BIN_NUMBER (9)  
#define BIN_WIDTH (180/BIN_NUMBER)

using namespace std;

//函数声明
float* calCellFeature(cv::Point) ;
void drawHist(float* );

float cell_bin[BIN_NUMBER]; //每个cell中分配一个数组,用于存放每个cell的梯度方向直方图

cv::Mat img = cv::imread("/home/mk90/Pictures/nvpai.jpeg", cv::IMREAD_GRAYSCALE);

int main()
{
   
    img.convertTo(img, CV_32F, 1/255.0);  // 归一化
    cv::Point p(200, 50); //随便选择的一个点,用来测试
    calCellFeature(p);
    drawHist(cell_bin);

    cv::imshow("image", img);
    cv::waitKey(0);
    return 0;
}

// 根据cell左上角点来计算该cell的梯度方向直方图
// 这里bin的划分, 0-20 20-40 40-60 60-80 80-100 100-120 120-140 140-160 160-0 每个bin不含右边界角度
float*  calCellFeature(cv::Point leftTop){
   
    cv::Mat cell_img(img, cv::Rect(leftTop.x, leftTop.y, CELL_SIZE, CELL_SIZE));//每个cell图像
    cv::Mat gx, gy;//用来存放x和y方向梯度
    // CV_32F 后面的1,0表示x方向梯度,0,1表示y方向梯度,最后的1代表ksize,表示采用模板为3*1或者1*3
    cv::Sobel(cell_img, gx, CV_32F, 1, 0, 1);
    cv::Sobel(cell_img, gy, CV_32F, 0, 1, 1);
    // C++ Calculate gradient magnitude and direction (in degrees)
    cv::Mat mag, angle;//存放计算得到的幅值和角度
    cv::cartToPolar(gx, gy, mag, angle, 1); //参数1表示得到的是角度而不是弧度

    int iWhichBin; // 索引号,用于判断每个角度应该在的bin
    memset(cell_bin, 0, BIN_NUMBER*sizeof (float)); //每次使用cell_bin先赋值为0
    for (int i =0; i< cell_img.cols; i++){
   
        for (int j = 0; j < cell_img.rows; j++){
   
            // 把角度转化为0—180之间
            if (angle.at<float>(i, j) < 0)
                angle.at<float>(i, j) += 180.0f;
            if (angle.at<float>(i, j) > 180.0f)
                angle.at<float>(i, j) -= 180.0f;
            iWhichBin = angle.at<float>(i, j) / BIN_WIDTH ;  // 该角度所处的bin位置, bin序号从0开始
            cell_bin[iWhichBin] += mag.at<float>(i, j); // 相应的bin的值加上相应的幅值
        }
    }
    //查看数据
//    for (int n=0; n< BIN_NUMBER; n++) {
   
//        printf("cell_bin[%d]: %f\n", n, cell_bin[n]);
//    }
    return cell_bin;
}

//取数组的最大值, drawHist函数中调用
float getMax(float* array){
   
    float max;
    for (int i =0; i< sizeof (array); i++) {
   
        if (array[i] > max)
            max =array[i];
    }
    cout<< "max: " << max << endl;
    return max;
}

// 绘制直方图
void drawHist(float* bin_data){
   
    int histRows = 200; //直方图的高
    int histCols = 500; //直方图的宽
    float maxValue = getMax(bin_data);
    cv::Scalar backGroundColor = cv::Scalar(150, 150, 150); //背景颜色
    cv::Scalar graphColor = cv::Scalar(0, 100, 200); //图像颜色
    cv::LineTypes lineType = cv::LINE_AA; //线条类型

    cv::Mat theGraph(histRows, histCols, CV_8UC3, backGroundColor);  //用于绘图的Mat对象
    cv::Point p1(0, 0), p2(0, theGraph.rows-1); //用于绘图的两点

    for (int i=0; i<BIN_NUMBER; i++) {
   
        float value = bin_data[i] * 0.95f; //在直方图上方留有一些空白
        value = maxValue - value; //翻转,注意绘图的位置
        value = value / maxValue *theGraph.rows; //在图上的高度
        p1.y = value; //该bin方框左上角的点
        p2.x = float(i+1) * 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值