#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[][]; //我们一般默认cell为8*8的像素大小,但是为了储存周边店的像素,需要多加两个像素储存点的位置;
double gradient_M[][]; //保存梯度的幅值;
double gradient_Angle[][]; //保存像素梯度的方向;
double gradient_h[][];
double gradient_v[][]; public:
double bin[]; //将梯度方向分成九个方向,在根据具体像素梯度的方向大小,进行投票;
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-,m=;i<pixel_x+;i++,m++){
uchar *data=img.ptr<uchar>(i);
for(int j=pixel_y-,n=;j<pixel_y+;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=;i<;i++){
for(int j=;j<;j++){
gradient_h[i][j]=pixel[i+][j]-pixel[i-][j];
gradient_v[i][j]=pixel[i][j+]-pixel[i][j-];
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])*;
}
} // 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=;i<;i++){
bin[i]=;
} for(int i=;i<;i++){
for(int j=;j<;j++){
if((gradient_Angle[i][j]>=&&gradient_Angle[i][j]<)||(gradient_Angle[i][j]>=&&gradient_Angle[i][j]<)){
bin[]=bin[]+gradient_M[i][j];
}
if((gradient_Angle[i][j]>=&&gradient_Angle[i][j]<)||(gradient_Angle[i][j]>=&&gradient_Angle[i][j]<)){
bin[]=bin[]+gradient_M[i][j];
}
if((gradient_Angle[i][j]>=&&gradient_Angle[i][j]<)||(gradient_Angle[i][j]>=&&gradient_Angle[i][j]<)){
bin[]=bin[]+gradient_M[i][j];
}
if((gradient_Angle[i][j]>=&&gradient_Angle[i][j]<)||(gradient_Angle[i][j]>=&&gradient_Angle[i][j]<)){
bin[]=bin[]+gradient_M[i][j];
}
if((gradient_Angle[i][j]>=&&gradient_Angle[i][j]<)||(gradient_Angle[i][j]>=&&gradient_Angle[i][j]<)){
bin[]=bin[]+gradient_M[i][j];
}
if((gradient_Angle[i][j]>=&&gradient_Angle[i][j]<)||(gradient_Angle[i][j]>=&&gradient_Angle[i][j]<)){
bin[]=bin[]+gradient_M[i][j];
}
if((gradient_Angle[i][j]>=&&gradient_Angle[i][j]<)||(gradient_Angle[i][j]>=&&gradient_Angle[i][j]<)){
bin[]=bin[]+gradient_M[i][j];
}
if((gradient_Angle[i][j]>=&&gradient_Angle[i][j]<)||(gradient_Angle[i][j]>=&&gradient_Angle[i][j]<)){
bin[]=bin[]+gradient_M[i][j];
}
if((gradient_Angle[i][j]>=&&gradient_Angle[i][j]<=)||(gradient_Angle[i][j]>=&&gradient_Angle[i][j]<=)){
bin[]=bin[]+gradient_M[i][j];
}
}
}
////////////////////////////////////
//归一化;
double sum_bin=;
for(int i=;i<;i++){
sum_bin=sum_bin+bin[i];
}
for(int i=;i<;i++){
bin[i]=bin[i]/sum_bin;
if(bin[i]>0.2){
bin[i]=0.2;
}
}
sum_bin=;
for(int i=;i<;i++){
sum_bin=sum_bin+bin[i];
}
for(int i=;i<;i++){
bin[i]=bin[i]/sum_bin;
}
}
//Block类部分****************
class Block{
int block_pixel_x; //block的起始像素点横坐标位置;
int block_pixel_y; //block的起始像素点纵坐标位置;
Mat src; //图像必须是灰度图;
double bins[]; //该类主要是对block进行相关处理,我们默认block为四个cell,即2*2;所以bins为36维;
int k; public:
Block(Mat img){
src=img;
k=;
} 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=;
Cell cell(src);
for(int i=block_pixel_x, m=;m<;i=i+,m++){
for(int j=block_pixel_y, n=;n<;j=j+,n++){
cell.Set_Cell(i,j);
cell.Get_Pixel();
cell.Gradient_Pixel();
cell.Bin_Selection_Normalization();
for(int i=;i<;i++){
bins[k++]=cell.bin[i];
}
}
}
} void Block::Block_into_HistImage(){ //该部分算法是将bins生成直方图;
int hight=;
int width=;
IplImage *hist_image=cvCreateImage(Size(,),,);
for(int i=;i<;i++){
cvRectangle(hist_image,CvPoint(i*,hight-),CvPoint((i+)*-,hight-bins[i]*),CV_RGB(,,));
} cvNamedWindow("",);
cvShowImage("",hist_image);
cvWaitKey();
} void Block::output_bins(){
//ofstream out ("1.txt");
for(int i=;i<;i++){
cout<<bins[i]<<"\n";
}
cout<<"*******************************************\n";
} int main(){
Mat img=imread("G:/2.png",); //载入图片;
if(img.empty())
{
return -;
}
Mat gray1;
Mat gray;
cvtColor(img,gray1,COLOR_RGB2GRAY);
resize(gray1,gray,Size(,),,,);
namedWindow("gray",);
imshow("gray",gray);
// cvWaitKey(0);
Block block(gray);
for(int i=,m=;m<;m++,i=i+){
for(int j=,n=;n<;n++,j=j+){
block.Set_Block(i,j);
block.Cut_Block();
//block.Block_into_HistImage();
block.output_bins();
}
}
}

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

  1. opencv学习笔记(七)SVM+HOG

    opencv学习笔记(七)SVM+HOG 一.简介 方向梯度直方图(Histogram of Oriented Gradient,HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子 ...

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

    在计算机视觉研究当中,HOG算法和LBP算法算是基础算法,但是却十分重要.后期很多图像特征提取的算法都是基于HOG和LBP,所以了解和掌握HOG,是学习计算机视觉的前提和基础. HOG算法的原理很多资 ...

  3. OpenCV 学习之路(2) -- 操作像素

    本节内容: 访问像素值 用指针扫描图像 用迭代器扫描图像 编写高效的图像扫描循环 扫描图像并访问相邻像素 实现简单的图像运算 图像重映射 访问像素值 准备工作: 创建一个简单函数,用它在图像中加入椒盐 ...

  4. OpenCV 学习之路(1)

    OpenCV的第一个代码: #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #i ...

  5. opencv学习之路(41)、人脸识别

    一.人脸检测并采集个人图像 //take_photo.cpp #include<opencv2/opencv.hpp> using namespace cv; using namespac ...

  6. opencv学习之路(40)、人脸识别算法——EigenFace、FisherFace、LBPH

    一.人脸识别算法之特征脸方法(Eigenface) 1.原理介绍及数据收集 特征脸方法主要是基于PCA降维实现. 详细介绍和主要思想可以参考 http://blog.csdn.net/u0100066 ...

  7. opencv学习之路(39)、PCA

    一.PCA理论介绍 网上已经有许多介绍pca原理的博客,这里就不重复介绍了.详情可参考 http://blog.csdn.net/zhongkelee/article/details/44064401 ...

  8. opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量

    本文部分内容转自 https://www.cnblogs.com/chaosimple/p/3182157.html 一.统计学概念 二.为什么需要协方差 三.协方差矩阵 注:上述协方差矩阵还需要除以 ...

  9. opencv学习之路(37)、运动物体检测(二)

    一.运动物体轮廓椭圆拟合及中心 #include "opencv2/opencv.hpp" #include<iostream> using namespace std ...

随机推荐

  1. 《天龙八部》及Ogre3D模型的3ds max导入插件(源码公布)

    測试UE4项目.苦于没有像样的模型和动画资源,所以想到把<天龙八部>等网游的资源导出来用. 于是做了个max导入插件. 效果还是不错的. 效果图: 上图是<斗破苍穹>的游戏资源 ...

  2. _stdcall与_cdecl

    _cdecl(C Declaration的缩写)是C/C++和MFC程序默认使用的调用约定,因此可以省略,也可以在函数声明时加上_cdecl关键字来手工指定.采用_cdecl约定时,函数参数按照从右到 ...

  3. 数据库操作语句大全(sql)

    一.基础 1.说明:创建数据库CREATE DATABASE database-name 2.说明:删除数据库drop database dbname3.说明:备份sql server--- 创建 备 ...

  4. java有用的启动参数

    三大类选项: 1. 标准选项: 功能是很稳定的,所有的标准选项都是以-开头,比如-version, -server等. 2. X选项:以-X开头,这类选项的功能还是很稳定,但官方的说法是它们的行为可能 ...

  5. [Swift通天遁地]五、高级扩展-(4)快速生成Invert、Mix、Tint、Shade颜色及调整饱和度阶

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  6. oracle学习笔记(二十) 子程序——函数与触发器

    子程序--函数 语法 之前select语句中使用的函数,都是SQL内置函数,我们可以通过自定义函数更满足我们的需要. 自定义函数的语法和存储过程差不多. create [or replace] $fu ...

  7. EasyUI系列学习(二)-使用EasyUI

    一.引入必要文件 <!--1.0引入jQuery核心库--> <script src="jquery-easyui-1.4.4/jquery.min.js"> ...

  8. JVM中线程状态转换图

    JVM中线程的状态转换图 线程在一定条件下,状态会发生变化.线程一共有以下几种状态: 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该 ...

  9. HTML 表单 存为EXCEL文件时 中文显示乱码

    在做宣传品发放系统时,需求要把数据库查询的记录生成表单并转存excel文件. 在转存的EXCEL文件中文显示乱码,表格和其他字符正常,检查后发现是创建EXCEL文件打开模式不对 之前: myfile ...

  10. 实现X*N

    #include<iostream> using namespace std; double foo(int n,double x) { if(1==n) { return x; } el ...