#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. 四:Java之字符串操作String、StringBuffer和StringBuilder

    string是我们经经常使用到的一个类型,事实上有时候认为敲代码就是在重复的操作字符串,这是C的特点,在java中.jdk非常好的封装了关于字符串的操作.三个类String .StringBuffer ...

  2. LeetCode 976. Largest Perimeter Triangle (三角形的最大周长)

    题目标签:Array 题目给了我们一个 边长的 array, 让我们找出 最大边长和的三角形,当然前提得是这三条边能组成三角形.如果array 里得边长组成不了三角形,返回0. 最直接的理解就是,找到 ...

  3. Index statistics collected bug

    SQL运行引擎会从pg_stats.pg_class等相关系统字典表.视图获取生成最佳运行计划的数据,假设相关字典视图的数据不准确就没有办法生成良好的运行计划. 发现下面Bug一枚. 0. 插入数据之 ...

  4. WebSocket握手总结

    网址:http://blog.csdn.net/edwingu/article/details/44040961 WebSocket protocol 是HTML5一种新的协议.它实现了浏览器与服务器 ...

  5. Sara Cope关于text-shadow的介绍

    作者:Sara Cope p { text-shadow: 1px 1px 1px #000; } 你可以通过逗号“,”应用多个文本阴影. p { text-shadow: 1px 1px 1px # ...

  6. Python细节(一)深浅拷贝

    深浅拷贝 只要涉及拷贝,就会涉及创建新对象 浅拷贝,会创建一个新的容器,列表中的元素和原列表的元素用的是同一个内存空间 第一种方法:从头切到尾,完整的复制一份 lst = [1,2,3,4] lst1 ...

  7. leetCode----day01---- 从排序数组中删除重复项

    需求: 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成. ...

  8. MAC应用无法打开或文件损坏的处理方法

    在MAC下安装一些软件时提示"来自身份不明开发者",其实这是MAC新系统启用了新的安全机制.默认只信任 Mac App Store 下载的软件和拥有开发者 ID 签名的应用程序.换 ...

  9. ACM_巧克力

    Chocolate,Chocolate Time Limit: 2000/1000ms (Java/Others) Problem Description: 都说发神喜欢吃巧克力,有一次发神徒弟买了一 ...

  10. HTML 表格与表单 个人简历

    <title>个人简历</title></head> <body background="1e30e924b899a9015b946ac41f950 ...