C++ 图像处理(二十二) HOG特征提取

HOG特征提取

原理
(一)预处理:

包括伽马校正和灰度化。这是可选的步骤,因为实验证明做不做影响不大。伽马校正是减少光度对实验的影响。灰度化是将彩色 图片变成灰度图。其实彩色图片也可以直接处理。不过是分别对三通道的颜色值进行梯度计算,最后选择梯度最大的那个。为简单起见,假设输入为灰度图,同时大小是64*128(这个大小是上面论文的大小,也可以自己确定不同的大小,但是实验效果就不能得到保证)。

代码:

//HOG特征提取(灰度图)
void* HOG(QImage &image,QImage &otp)
{
    //分成8x8的小cell
    int step = 8;
    int bins = 9;

    //获取图片的宽高,调整图像的尺寸,把图片尺寸改成8的整倍数,方便计算
    int width = image.width();
    int height = image.height();

    int cols = width / step;
    int rows = height / step;

    width = cols * step;
    height = rows * step;

    //尺寸变化
    image.scaled(width,height);




    //创建一个空白的QImage对象,并初始化为0
    QImage* out = new QImage(width,height,QImage::Format_ARGB32);
    Init_Image(*out,0);

    //遍历用的遍历
    int i = 0, j = 0;
    int x = 0,y = 0;

    //计算梯度与方向
    QVector<double> gradiant_x;     //x 方向的梯度
    QVector<double> gradiant_y;     //y 方向的梯度
    QVector<double> gradiant;       //梯度幅值
    QVector<double> direct;         //梯度方向
    //sobel 算子计算梯度
    Sobel_mat(image,gradiant_x,0);
    Sobel_mat(image,gradiant_y,1);
    //计算梯度的幅值与梯度的方向
    cartToPolar(gradiant_x,gradiant_y,gradiant,direct);




    //int all_cell = width*height;
    int curr_index = 0;  //数组的下标指针
    double gray = 0;     //临时变量,存储梯度幅值
    int theta = 0;       //临时变量,存储梯度方向
    int dire_temp = 0; //取方向20的倍数
    int mo = 0;        //取方向20的摸
    double weight = 0;  //权重
    double wn = 0;      //临时变量


    QVector<double> histemp(bins,0);   //每个8x8的cell直方图;
    QVector<QVector<double>> histog;  //总的直方图

    //走8步一次
    for(i = 0; i<height; i+=step)
    {
        for(j = 0; j<width; j+=step)
        {
            //8x8领域的梯度方向直方图
            for(int k = 0; k<step;k++)
            {
                for(int l = 0; l<step; l++)
                {

                    x = j + l;
                    y = i + k;

                    //下标指针
                    curr_index = y * width + x;

                    //梯度值
                    gray = gradiant[curr_index];

                    //方向
                    theta = (int)direct[curr_index];

                    //梯度的方向取值是(-π,π)
                    if(theta<0)
                    {
                        theta = theta + 180;
                    }

                    //双线性差值
                    mo = theta % 20;
                    dire_temp = theta / 20;

                    //计算偏移权重
                    if(mo >= 10)
                    {
                        wn = mo - 10;
                        weight = (20-wn) / 20.0f;
                    }
                    else {
                        wn = 10 - mo;
                        weight = (20-wn) / 20.0f;
                    }

                    //根据权重赋值
                    if(mo>=10)
                    {
                        histemp[dire_temp] += (weight * gray);
                        if(dire_temp < 8)
                        {
                            histemp[dire_temp+1] += ((1.0-weight)*gray);
                        }
                    }
                    else {
                         histemp[dire_temp] += (weight * gray);
                        if(dire_temp > 0)
                        {
                            histemp[dire_temp-1] += ((1.0-weight)*gray);
                        }
                    }

                }
            }
            histog.push_back(histemp);
            histemp.fill(0);
        }
    }


    //归一化Naturalization
    QVector<QVector<double>> blocks;  //2x2的block = 4个cell(8x8) = 16x16个
    QVector<double> cell_1;
    QVector<double> cell_2;
    QVector<double> cell_3;
    QVector<double> cell_4;

    for(i = 0; i<rows-1; i++)
    {
        for(j = 0; j<cols-1; j++)
        {

            x = j +1;
            y = i + 1;

            curr_index = i * cols + j;
            cell_1 =  histog[curr_index];

            curr_index = i * cols + x;
            cell_2 =  histog[curr_index];

            curr_index = y * cols + j;
            cell_3 =  histog[curr_index];

            curr_index = y * cols + x;
            cell_4 =  histog[curr_index];


            QVector<double> block_temp = generateBlockVector(cell_1,cell_2,cell_3,cell_4);

            blocks.push_back(block_temp);

        }
    }





    otp = *out;
    return 0;
}

//向量的模长

QVector<double> generateBlockVector(QVector<double> cell_1,QVector<double> cell_2,QVector<double> cell_3,QVector<double> cell_4)
{
    QVector<double> block;
    block.append(cell_1);
    block.append(cell_2);
    block.append(cell_3);
    block.append(cell_4);
    double sum = 0;

    for(int i = 0; i<cell_1.size(); i++)
    {
        sum += pow(cell_1[i],2.0) + pow(cell_2[i],2.0) + pow(cell_3[i],2.0) + pow(cell_4[i],2.0);
    }
    sum = sqrt(sum);

    for(int i = 0; i<block.size(); i++)
    {
        block[i] = block[i] / sum;
    }

    return block;
}


  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值