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[][]; //我们一般默认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算法的更多相关文章
- opencv学习笔记(七)SVM+HOG
opencv学习笔记(七)SVM+HOG 一.简介 方向梯度直方图(Histogram of Oriented Gradient,HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子 ...
- Opencv学习之路—Opencv下基于HOG特征的KNN算法分类训练
在计算机视觉研究当中,HOG算法和LBP算法算是基础算法,但是却十分重要.后期很多图像特征提取的算法都是基于HOG和LBP,所以了解和掌握HOG,是学习计算机视觉的前提和基础. HOG算法的原理很多资 ...
- OpenCV 学习之路(2) -- 操作像素
本节内容: 访问像素值 用指针扫描图像 用迭代器扫描图像 编写高效的图像扫描循环 扫描图像并访问相邻像素 实现简单的图像运算 图像重映射 访问像素值 准备工作: 创建一个简单函数,用它在图像中加入椒盐 ...
- OpenCV 学习之路(1)
OpenCV的第一个代码: #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #i ...
- opencv学习之路(41)、人脸识别
一.人脸检测并采集个人图像 //take_photo.cpp #include<opencv2/opencv.hpp> using namespace cv; using namespac ...
- opencv学习之路(40)、人脸识别算法——EigenFace、FisherFace、LBPH
一.人脸识别算法之特征脸方法(Eigenface) 1.原理介绍及数据收集 特征脸方法主要是基于PCA降维实现. 详细介绍和主要思想可以参考 http://blog.csdn.net/u0100066 ...
- opencv学习之路(39)、PCA
一.PCA理论介绍 网上已经有许多介绍pca原理的博客,这里就不重复介绍了.详情可参考 http://blog.csdn.net/zhongkelee/article/details/44064401 ...
- opencv学习之路(38)、Mat像素统计基础——均值,标准差,协方差;特征值,特征向量
本文部分内容转自 https://www.cnblogs.com/chaosimple/p/3182157.html 一.统计学概念 二.为什么需要协方差 三.协方差矩阵 注:上述协方差矩阵还需要除以 ...
- opencv学习之路(37)、运动物体检测(二)
一.运动物体轮廓椭圆拟合及中心 #include "opencv2/opencv.hpp" #include<iostream> using namespace std ...
随机推荐
- xul 创建一个按钮
MDN Mozilla 产品与私有技术 Mozilla 私有技术 XUL Toolbars 添加工具栏按钮 (定制工具栏) 添加工具栏按钮 (定制工具栏) 在本文章中 创建一个 overlay 在工具 ...
- .NET平台下Redis使用(二)【StackExchange.Redis学习】
Program.cs内容: using Newtonsoft.Json; using StackExchange.Redis; using System; using System.Data; usi ...
- java问题解读,String类为什么是final的
一.理解final 望文生义,final意为“最终的,最后的”,我理解为“不能被改变的”,它可以修饰类.变量和方法. 所以我是否可以理解为被它所修饰的类.变量和方法都不能被改变呢?答案是”是“,因为有 ...
- JDK8 函数式接口
JDK8中为了适应函数式响应编程模式,引入了函数式接口概念以增加Lambda表达式的功能.函数式接口其实本质上还是一个接口,但是它是一种特殊的接口:SAM类型的接口(Single Abstract M ...
- vs打开wixproj后缀文件
1.在正常情况下vs是无法打开wixproj工程的,能打开也只能是以记事本方式打开该文件本身 2.所以此时需要下载wixtool,安装后即可打开上述类型文件 3.最好也安装好vs对应版本的扩展包 4. ...
- 51nod 1222 莫比乌斯反演
思路: yhx找的反演题 题解已经烂大街了 #pragma GCC optimize("O3") //By SiriusRen #include <bits/stdc++.h ...
- ACM_无聊者序列(斐波那契数列大数取余(同余)+规律)
Problem Description: 瓜瓜在玩着由红色和蓝色的大理石做成的玻璃珠,他将n个玻璃珠从左到右排成一个序列叫做无聊者序列.一个非空的红色和蓝色玻璃珠组成的序列是一个无聊者序列.这个序列的 ...
- cloudera-scm-server启动时出现Caused by: java.io.FileNotFoundException: /var/lib/cloudera-scm-server/.keystore (No such file or directory)问题解决方法(图文详解)
不多说,直接上干货! 问题详情 查看/var/log/cloudera-scm-server.log的启动日志 问题来源 我在用cloudermanager安装好之后,然后,在对如下. 配置kerbe ...
- 【java并发容器】并发容器之CopyOnWriteArrayList
原文链接: http://ifeve.com/java-copy-on-write/ Copy-On-Write简称COW,是一种用于程序设计中的优化策略.其基本思路是,从一开始大家都在共享同一个内容 ...
- 右边根据左边的高度自动居中只需要两行CSS就可以完成
右边根据左边的高度自动居中只需要两行CSS就可以完成 <style type="text/css" > div{ display: inline-block; vert ...