Opencv学习之路——自己编写的HOG算法

#include<opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include<opencv2\opencv.hpp>
#include<iostream>
#include<fstream>

using namespace std;
using namespace cv;

#define Max 100

class Cell{
private:
    int pixel_x;                  //cell的像素的起始位置行坐标;
    int pixel_y;                  //cell的像素的起始位置纵坐标;
    Mat img;                      //待处理的图像,通常该该图像是经过Gamma校正的灰度图;
    double pixel[10][10];         //我们一般默认cell为8*8的像素大小,但是为了储存周边店的像素,需要多加两个像素储存点的位置;
    double gradient_M[9][9];            //保存梯度的幅值;
    double gradient_Angle[9][9];        //保存像素梯度的方向;
    double gradient_h[9][9];
    double gradient_v[9][9];

public:
    double bin[9];                //将梯度方向分成九个方向,在根据具体像素梯度的方向大小,进行投票;
    Cell(Mat src){    //构造函数;
        img=src;
    }

    void Set_Cell(int x,int y);
    void Get_Pixel();                                   //为了计算机使用方便,我们把一个cell当中的像素先读下来,用pixel[][]数组储存;
    void Gradient_Pixel();                              //计算机图像像素的梯度幅值和梯度角度;
    void Bin_Selection_Normalization();             //根据每个像素的幅值进行维度的区分和归一化,并且返回bin[]数组;
};

void Cell::Set_Cell(int x,int y){
    pixel_x=x;
    pixel_y=y;
}

void Cell::Get_Pixel(){
    for(int i=pixel_x-1,m=0;i<pixel_x+9;i++,m++){
            uchar *data=img.ptr<uchar>(i);
            for(int j=pixel_y-1,n=0;j<pixel_y+9;j++,n++){
                pixel[m][n]=data[j];
            }
    }
//    for(int i=0;i<9;i++){
//        for(int j=0;j<9;j++){
//            cout<<i<<j<<" "<<pixel[i][j]<<"\n";
//        }
//    }
}

void  Cell::Gradient_Pixel(){
    for(int i=1;i<9;i++){
        for(int j=1;j<9;j++){
            gradient_h[i][j]=pixel[i+1][j]-pixel[i-1][j];
            gradient_v[i][j]=pixel[i][j+1]-pixel[i][j-1];
            gradient_M[i][j]=sqrt(gradient_h[i][j]*gradient_h[i][j]+gradient_v[i][j]*gradient_v[i][j]);
            gradient_Angle[i][j]=atan2(gradient_h[i][j],gradient_v[i][j])*180;
        }
    }

//    for(int i=0;i<9;i++){
//        for(int j=0;j<9;j++){
//            cout<<i<<j<<" "<<gradient_h[i][j]<<" "<<gradient_v[i][j]<<" "<<gradient_M[i][j]<<" "<<gradient_Angle[i][j]<<"\n";
//        }
//    }
}

void  Cell::Bin_Selection_Normalization(){
        for(int i=0;i<9;i++){
        bin[i]=0;
    }

    for(int i=1;i<9;i++){
        for(int j=1;j<9;j++){
            if((gradient_Angle[i][j]>=0&&gradient_Angle[i][j]<20)||(gradient_Angle[i][j]>=180&&gradient_Angle[i][j]<200)){
                bin[0]=bin[0]+gradient_M[i][j];
            }
            if((gradient_Angle[i][j]>=20&&gradient_Angle[i][j]<40)||(gradient_Angle[i][j]>=200&&gradient_Angle[i][j]<220)){
                bin[1]=bin[1]+gradient_M[i][j];
            }
            if((gradient_Angle[i][j]>=40&&gradient_Angle[i][j]<60)||(gradient_Angle[i][j]>=220&&gradient_Angle[i][j]<240)){
                bin[2]=bin[2]+gradient_M[i][j];
            }
            if((gradient_Angle[i][j]>=60&&gradient_Angle[i][j]<80)||(gradient_Angle[i][j]>=240&&gradient_Angle[i][j]<260)){
                bin[3]=bin[3]+gradient_M[i][j];
            }
            if((gradient_Angle[i][j]>=80&&gradient_Angle[i][j]<100)||(gradient_Angle[i][j]>=260&&gradient_Angle[i][j]<280)){
                bin[4]=bin[4]+gradient_M[i][j];
            }
            if((gradient_Angle[i][j]>=100&&gradient_Angle[i][j]<120)||(gradient_Angle[i][j]>=280&&gradient_Angle[i][j]<300)){
                bin[5]=bin[5]+gradient_M[i][j];
            }
            if((gradient_Angle[i][j]>=120&&gradient_Angle[i][j]<140)||(gradient_Angle[i][j]>=300&&gradient_Angle[i][j]<320)){
                bin[6]=bin[6]+gradient_M[i][j];
            }
            if((gradient_Angle[i][j]>=140&&gradient_Angle[i][j]<160)||(gradient_Angle[i][j]>=320&&gradient_Angle[i][j]<340)){
                bin[7]=bin[7]+gradient_M[i][j];
            }
            if((gradient_Angle[i][j]>=160&&gradient_Angle[i][j]<=180)||(gradient_Angle[i][j]>=340&&gradient_Angle[i][j]<=360)){
                bin[8]=bin[8]+gradient_M[i][j];
            }
        }
    }
    ////////////////////////////////////
    //归一化;
    double sum_bin=0;
    for(int i=0;i<9;i++){
        sum_bin=sum_bin+bin[i];
    }
    for(int i=0;i<9;i++){
        bin[i]=bin[i]/sum_bin;
        if(bin[i]>0.2){
            bin[i]=0.2;
        }
    }
    sum_bin=0;
    for(int i=0;i<9;i++){
        sum_bin=sum_bin+bin[i];
    }
    for(int i=0;i<9;i++){
        bin[i]=bin[i]/sum_bin;
    }
}
//Block类部分****************
class Block{
    int block_pixel_x;           //block的起始像素点横坐标位置;
    int block_pixel_y;           //block的起始像素点纵坐标位置;
    Mat src;                     //图像必须是灰度图;
    double bins[38];             //该类主要是对block进行相关处理,我们默认block为四个cell,即2*2;所以bins为36维;
    int k;

public:
    Block(Mat img){
        src=img;
        k=0;
    }

    void Set_Block(int x,int y);
    void Cut_Block();            //本人认为这是整个算法当中比较重要的一部分,即图像切割划分部分;
    void Block_into_HistImage();
    void output_bins();
};

void Block::Set_Block(int x,int y){
    block_pixel_x=x;
    block_pixel_y=y;
}

void Block::Cut_Block(){
    k=0;
    Cell cell(src);
    for(int i=block_pixel_x, m=0;m<2;i=i+8,m++){
        for(int j=block_pixel_y, n=0;n<2;j=j+8,n++){
            cell.Set_Cell(i,j);
            cell.Get_Pixel();
            cell.Gradient_Pixel();
            cell.Bin_Selection_Normalization();
            for(int i=0;i<9;i++){
                bins[k++]=cell.bin[i];
            }
        }
    }
}

void Block::Block_into_HistImage(){            //该部分算法是将bins生成直方图;
    int hight=256;
    int width=80;
    IplImage *hist_image=cvCreateImage(Size(80,256),8,3);
    for(int i=0;i<36;i++){
        cvRectangle(hist_image,CvPoint(i*2,hight-1),CvPoint((i+1)*2-1,hight-bins[i]*100),CV_RGB(255,255,255));
    }

    cvNamedWindow("1",1);
    cvShowImage("1",hist_image);
    cvWaitKey(0);
}

void Block::output_bins(){
    //ofstream out ("1.txt");
    for(int i=0;i<36;i++){
        cout<<bins[i]<<"\n";
    }
    cout<<"*******************************************\n";
}

int main(){
    Mat img=imread("G:/2.png",1);               //载入图片;
    if(img.empty())
    {
        return -1;
    }
    Mat gray1;
    Mat gray;
    cvtColor(img,gray1,COLOR_RGB2GRAY);
    resize(gray1,gray,Size(130,66),0,0,1);
    namedWindow("gray",1);
    imshow("gray",gray);
//    cvWaitKey(0);
    Block block(gray);
    for(int i=1,m=0;m<7;m++,i=i+8){
        for(int j=1,n=0;n<15;n++,j=j+8){
            block.Set_Block(i,j);
            block.Cut_Block();
            //block.Block_into_HistImage();
            block.output_bins();
        }
    }
}
时间: 2024-12-12 18:44:13

Opencv学习之路——自己编写的HOG算法的相关文章

opencv学习笔记(七)SVM+HOG

opencv学习笔记(七)SVM+HOG 一.简介 方向梯度直方图(Histogram of Oriented Gradient,HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子.它通过计算和统计图像局部区域的梯度直方图来构成特征.Hog特征结合SVM分类器已经被广泛用于图像识别中,尤其在行人检测中获得了极大的成功.需要提醒的是,HOG+SVM进行行人检测的方法是法国研究院Dalal在2005的CVPR上提出的. 最近在做车标识别相关的研究,用到了SVM+HOG的方法进行识

Opencv学习之路—Opencv下基于HOG特征的KNN算法分类训练

在计算机视觉研究当中,HOG算法和LBP算法算是基础算法,但是却十分重要.后期很多图像特征提取的算法都是基于HOG和LBP,所以了解和掌握HOG,是学习计算机视觉的前提和基础. HOG算法的原理很多资料都可以查到,简单来说,就是将图像分成一个cell,通过对每个cell的像素进行梯度处理,进而根据梯度方向和梯度幅度来得到cell的图像特征.随后,将每个cell的图像特征连接起来,得到一个BLock的特征,进而得到一张图片的特征.Opencv当中自带HOG算法,可以直接调用,进行图像的特征提取.但

数据结构与算法学习之路:背包问题的贪心算法和动态规划算法

一.背包问题描述: 有N种物品和一个重量为M的背包,第i种物品的重量是w[i],价值是p[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包重量,且价值总和最大. 二.解决方法: 1.贪心算法:贪心算法基于的思想是每一次选择都作当前最好的选择,这样最后的结果虽然不一定是最优解,但是也不会比最优解差很多. 举个例子说明可能好懂一些:一帮基友去聚餐,菜是一份一份上的,我每一次夹菜都只夹牛肉/海鲜吃,可能到最后我吃的牛肉/海鲜很多,但不一定代表我吃掉的东西的总价值最高,但是相对来说价值也很高

opencv学习之路(21)、模板匹配及应用

一.模板匹配概念 二.单模板匹配 1 #include "opencv2/opencv.hpp" 2 #include <iostream> 3 using namespace std; 4 using namespace cv; 5 6 void main() 7 { 8 Mat temp=imread("E://mu.jpg"); 9 Mat src=imread("E://lena.jpg"); 10 Mat dst=src.c

opencv学习之路(25)、轮廓查找与绘制(四)——正外接矩形

一.简介 二.外接矩形的查找绘制 1 #include "opencv2/opencv.hpp" 2 using namespace cv; 3 void main() 4 { 5 //外接矩形的查找绘制 6 Mat srcImg =imread("E://12.jpg"); 7 imshow("src",srcImg); 8 Mat dstImg = srcImg.clone(); //原图备份 9 cvtColor(srcImg, srcIm

opencv学习之路(20)、直方图应用

一.直方图均衡化--equalizeHist() 1 #include "opencv2/opencv.hpp" 2 using namespace cv; 3 4 void main() 5 { 6 Mat srcImg = imread("E://02.jpg", 0); //以灰度方式打开,需要输入单通道图像 7 imshow("src", srcImg); 8 Mat dstImg; //均衡化后的图像 9 equalizeHist(sr

opencv学习之路(17)、边缘检测

一.概述 二.canny边缘检测 1 #include "opencv2/opencv.hpp" 2 using namespace cv; 3 4 void main() 5 { 6 //Canny边缘检测 7 Mat srcImg = imread("E://1.png",0); //0表示以灰度图读入,彩色图和灰度图进行边缘检测时略有不同,建议使用灰度图 8 //medianBlur(srcImg, srcImg,5);//中值滤波 9 imshow(&quo

opencv学习之路(5)、鼠标和滑动条操作

一.鼠标事件 1 #include<opencv2/opencv.hpp> 2 #include<iostream> 3 using namespace cv; 4 using namespace std; 5 6 Mat img(500,500,CV_8UC3,Scalar(255,255,255));//定义成全局变量 7 8 void OnMouse(int event,int x,int y,int flags,void* param){ 9 if(event==CV_EV

opencv学习之路(4)、Mat类介绍,基本绘图函数

一.Mat类创建 1 #include <opencv2/opencv.hpp> 2 using namespace cv; 3 4 void main(){ 5 Mat img1=imread("E://1.jpg"); 6 Mat img2(img1); 7 Mat img3=img1; 8 Mat img4=img1.clone(); 9 Mat img5; 10 img1.copyTo(img5); 11 12 cvtColor(img1,img1,CV_BGR2H