#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();
}
}
}