人工智能研究网  www.studyai.cn

下面的代码通过计算图像中给定区域的方向梯度直方图来估计图像的旋转角度

主要内容包括:

一、计算局部图像块方向梯度直方图的函数

二、把给定图像按照给定的角度旋转

三、如何利用旋转后的图像的方向梯度直方图和原图像的方向梯度直方图来估计旋转角度

四、绘制方向梯度直方图

计算效果如下次:

主要代码如下:

// LocalHistogramOfOrientedGradients.cpp : 定义控制台应用程序的入口点。
//局部方向梯度直方图#include
#include using namespace std;
using namespace cv;/*
计算给定像素位置上的加权方向梯度直方图(orientation gradient  histogram)img:原始图像pt: 指定的像素点radius: 统计半径isSmoothed:是否平滑输出直方图用高斯函数进行中心加权;isWeighted,和 weighted_sigma: 是否加权和计算权重的标准差hist: 要输出的直方图n: 直方图的bin个数返回值:直方图的峰值(最大值)
*/
static float calcOrientationHist( const Mat& img, Point pt, int radius, float* hist, int n ,int isSmoothed,int isWeighted,float weighted_sigma)
{//radius应该是以pt为中心的正方形的边长的一半int i, j, k, len = (radius*2+1)*(radius*2+1);//使用高斯函数中心加权float expf_scale = -1.f/(2.f * weighted_sigma * weighted_sigma);//为什么加4呢,是为了给临时直方图开辟多余的4个存储位置,//用来存放temphist[-1],temphist[-2],temphist[n],temphist[n+1]的//为什么加n呢,这n个位置是留给temphist[0 ... n-1]的//为什么len*4呢,这4个len长度的数组位置是留给X、Y、W以及方向Ori的AutoBuffer buf(len*4 + n+4);//X是横向梯度,Y是纵向梯度,Mag是梯度幅值=sqrt(X^2+Y^2), Ori是梯度方向 = arctan(Y/X)float *X = buf, *Y = X + len, *Mag = X, *Ori = Y + len, *W = Ori + len;float* temphist = W + len + 2;//加2是用来存放temphist[-1],temphist[-2]的//临时直方图清零for( i = 0; i < n; i++ )temphist[i] = 0.f;//从上往下,从左往右扫描求横向,纵向的梯度值以及对应的权值for( i = -radius, k = 0; i <= radius; i++ ){int y = pt.y + i;//指向原图像img的第pt.y+i行if( y <= 0 || y >= img.rows - 1 )//边界检查continue;for( j = -radius; j <= radius; j++ ){int x = pt.x + j;//指向原图像img的第pt.x+j列if( x <= 0 || x >= img.cols - 1 )//边界检查continue;//横向梯度float dx = (float)(img.at(y, x+1) - img.at(y, x-1));//纵向梯度float dy = (float)(img.at(y-1, x) - img.at(y+1, x));//保存纵向梯度和横向梯度X[k] = dx; Y[k] = dy;//计算加权数组if(isWeighted) W[k] = (i*i + j*j)*expf_scale;elseW[k] = 1.f; //如果不加权,则每个统计点上的权重是一样的k++;}}//把实际的统计点数复制给len,由于矩形局部邻域有可能超出图像边界,len = k;//所以实际的点数总是小于等于 (radius*2+1)*(radius*2+1)//在指定像素点的邻域内 计算梯度幅值, 梯度方向 and 权重  exp(W, W, len); //权重fastAtan2(Y, X, Ori, len, true);//梯度方向magnitude(X, Y, Mag, len);//梯度幅值//填充临时直方图,直方图的横轴是梯度方向方向角度[0,360),bin宽度为n/360;//纵轴是梯度幅值乘以对应的权重for( k = 0; k < len; k++ ){int bin = cvRound((n/360.f)*Ori[k]);//求出第k个角度Ori[k]的bin索引号if( bin >= n )bin -= n;if( bin < 0 )bin += n;temphist[bin] += W[k]*Mag[k];   }if(isSmoothed){// 直方图平滑,平滑后放入输出直方图数组中temphist[-1] = temphist[n-1];temphist[-2] = temphist[n-2];temphist[n] = temphist[0];temphist[n+1] = temphist[1];for( i = 0; i < n; i++ ){hist[i] = (temphist[i-2] + temphist[i+2])*(1.f/16.f) +(temphist[i-1] + temphist[i+1])*(4.f/16.f) +temphist[i]*(6.f/16.f);}}else  //不平滑直方图{for( i = 0; i < n; i++ ){hist[i] = temphist[i];}}//求直方图梯度的最大值float maxval = hist[0];for( i = 1; i < n; i++ )maxval = std::max(maxval, hist[i]);return maxval;
}void DrawHist(Mat& hist, string&  winname)
{Mat drawHist;int histSize = hist.rows;// 创建直方图画布int hist_w = 360; int hist_h = 360;//直方图图像的宽度和高度int bin_w = cvRound( (double) hist_w/histSize );//直方图中一个矩形条纹的宽度Mat histImage( hist_w, hist_h, CV_8UC3, Scalar( 0,0,0) );//创建画布图像/// 将直方图归一化到范围 [ 0, histImage.rows ]normalize(hist, drawHist, 0,histImage.rows, NORM_MINMAX, -1, Mat() );/// 在直方图画布上画出直方图for(int i=1;i(i-1))),Scalar(0,0,255),1,8,0);  //折线表示 /* line( histImage, Point( bin_w*(i-1), hist_h - cvRound(hist.at(i-1)) ) ,Point( bin_w*(i), hist_h - cvRound(hist.at(i)) ),Scalar( 0, 0, 255), 1, 8, 0  );*/}/// 显示直方图cv::namedWindow(winname,1);cv::imshow(winname, histImage );
}int main(int argc, char** argv)
{const string filename = "meinv2.jpg";Mat Image = imread(filename,1);if(Image.empty()){std::cout<<"无法读取图像...."< rotateHist = Mat::zeros(bins_count,1,CV_32FC1); float*  rh = (float*)rotateHist.data;calcOrientationHist(rotate_dst,center,radius,rh,bins_count,isSmoothed,isWeighted,sigma);//绘制直方图string winname2 = "rotated hist";DrawHist(rotateHist,winname2);//- -利用旋转前和旋转后的两个直方图的纵轴主峰对应的角度bin估算图像的旋转角度--------------------cout<<"直方图bin的宽度: "<<(360.f/bins_count)<<"度"<

结果分析:

绕图像中心点顺时针旋转30度缩放因子为1的估计结果:

从上图看出,顺时针旋转奶茶妹妹后,方向梯度直方图整体向左移动了一定距离

真实的旋转角度为 -30度,估计的旋转角度为 -24度,误差6度正好是直方图的bin的宽度

绕图像中心点逆时针旋转30度缩放因子为1的估计结果:

从上图看出,逆时针旋转奶茶妹妹后,方向梯度直方图整体向右移动了一定距离

真实旋转角度为30度,估计的旋转角度也为30度

OpenCV 使用方向梯度直方图估计图像旋转角度相关推荐

  1. OpenCV学习之六: 使用方向梯度直方图估计图像旋转角度

    OpenCV学习之六: 使用方向梯度直方图估计图像旋转角度 原文:http://blog.csdn.net/zhjm07054115/article/details/26964275 下面的代码通过计 ...

  2. 【图像特征提取1】方向梯度直方图HOG---从理论到实践------附带积分图像的解析

    (一)特征检测算法的综述 计算机视觉理论中的特征描述是常见的目标分析技术之一,关键点的检测和关键点的提取是目标分析的重要手段和重要步骤之一.局部图像特征描述的核心问题是不变性和可分析性,不变性是基于特 ...

  3. 深度学习----CNN的图像学习之HOG(方向梯度直方图)详解

    一.原理 二.参数的理解 2.1.灰度值 2.2.归一化 2.3.细胞 2.4.窗口 2.5.类型 2.6.Gamma标准化 2.7.图像梯度及梯度算子 2.8.直方图 2.9.高斯空域加窗 三.步骤 ...

  4. 图像学习之如何理解方向梯度直方图HOG(Histogram Of Gradient)

    本文转自:雷锋网,作者:思颖.连接:https://yq.aliyun.com/articles/176607,https://www.leiphone.com/news/201708/ZKsGd2J ...

  5. 图像学习之如何理解方向梯度直方图(Histogram Of Gradient)

    特征描述子(Feature Descriptor) 特征描述子就是图像的表示,抽取了有用的信息,丢掉了不相关的信息.通常特征描述子会把一个w*h*3(宽高3,3个channel)的图像转换成一个长度为 ...

  6. 图像特征:方向梯度直方图 HOG

    文章目录 参考资料 简介 算法流程 灰度化和gamma校正 计算梯度 统计cell的梯度方向直方图 Block 块内归一化(重点) 组合为HOG特征 HOG特征与可视化 OpenCV 算法实现 参考资 ...

  7. OpenCV方向梯度直方图HOG的实例(附完整代码)

    OpenCV方向梯度直方图HOG的实例 OpenCV方向梯度直方图HOG的实例 OpenCV方向梯度直方图HOG的实例 #include <iostream> #include <f ...

  8. 图像特征提取算法:方向梯度直方图HOG

    1.基本介绍 HOG,全称是方向梯度直方图(Histogram Of Gradient),是目前计算机视觉.模式识别领域很常用的一种描述图像局部纹理的特征.这个特征名字起的也很直白,就是说先计算图片某 ...

  9. 方向梯度直方图(Histogram Of Gradient)详解

    特征描述子(Feature Descriptor) 特征描述子就是图像的表示,抽取了有用的信息,丢掉了不相关的信息.通常特征描述子会把一个w*h*3(宽高3,3个channel)的图像转换成一个长度为 ...

最新文章

  1. vivo 互联网业务就近路由技术实战
  2. 探索停车黑科技,知位停车破局停车难题!
  3. I - Washing clothes
  4. 从零开始学习Hadoop--第1章 Hadoop的安装
  5. 我是一个尝试做自媒体的程序员
  6. hive 2.3 mysql_Hive(二)CentOS7.5安装Hive2.3.3
  7. OpenCV : 投影变换
  8. python访问陌生人qq空间_用Python登录好友QQ空间点赞
  9. 基于3D Frangi滤波的血管强化方法(附代码python)
  10. jq点击图片展示预览效果
  11. 艾司博讯:拼多多商品讲解视频如何制作
  12. archetype说明
  13. html css雪碧图,css常见小技巧(雪碧图)
  14. WIN10鼠标指针一直转圈解决方案及UAC了解
  15. Datawhale学习笔记-飞桨AI-Task02:头脑风暴:让人拍案叫绝的创意是如何产生的?
  16. 2022~2023计算机毕业设计之题目选题
  17. 火狐浏览器改变书签栏位置_通过书签改善生活
  18. 最近使用到的linux一些命令或操作日常记录
  19. Webpack与其他打包工具的区别
  20. 安徽计算机一级2016考试试题,2016最新计算机一级考试试题题库操作题

热门文章

  1. oracle+root+密码忘记,教您如何修复各种UNIX系统下root密码
  2. 中学计算机老师 当领导可能性,求分享,当中学计算机老师带信息学奥赛是怎样的感受 - 信息科学技术学院(EECS)版 - 北大未名BBS...
  3. 目前HTML常用的字符集编码方式,HTML知识点
  4. oracle的自动增长,Oracle实现id自动增长
  5. c++max函数怎么用_比函数还强大的Excel分列技巧,你知道怎么用吗
  6. 一个可以让你保持专注,用心生活,专心工作的绿色插件
  7. 过度加班被表彰引员工不满。官方回应:持续高强度的急行军不持久,尽快优化调整...
  8. 皮一皮:看看你有没有在自杀...
  9. 奇奇怪怪的大佬:理发店小弟到阿里P10
  10. 每日一皮:键盘未找到的窘境...