zoukankan      html  css  js  c++  java
  • Opencv学习之路——自己编写的HOG算法

    #include<opencv2corecore.hpp>
    #include<opencv2highguihighgui.hpp>
    #include<opencv2opencv.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]<<"
    ";
    //        }
    //    }
    }
    
    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]<<"
    ";
    //        }
    //    }
    }
    
    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]<<"
    ";
        }
        cout<<"*******************************************
    ";
    }
    
    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();
            }
        }
    }
  • 相关阅读:
    【HCIE-RS_TAC诊断5-2】
    【HCIE-RS_TAC诊断5-1】
    【HCIE-RS_TAC诊断4】
    【HCIE-RS_TAC诊断3】
    【HCIE-RS_TAC诊断2】
    华为ICT大赛辅导——双AC主备双链路备份
    shell 函数与内置变量
    CF505E Mr. Kitayuta vs. Bamboos
    CF559E Gerald and Path
    CF538H Summer Dichotomy
  • 原文地址:https://www.cnblogs.com/code-wangjun/p/5691078.html
Copyright © 2011-2022 走看看