# ORB算法中计算FAST角点的主方向 IC_Angle（C++ 转C）

#### 1.openCv库中 IC_Angle源码

static float IC_Angle(const Mat& image, const int half_k, Point2f pt,
const vector<int> & u_max)
{
int m_01 = 0, m_10 = 0;

const uchar* center = &image.at<uchar> (cvRound(pt.y), cvRound(pt.x));

// Treat the center line differently, v=0
for (int u = -half_k; u <= half_k; ++u)
m_10 += u * center[u];

// Go line by line in the circular patch
int step = (int)image.step1();

// Treat the center line differently, v=0
for (int v = 1; v <= half_k; ++v)
{
// Proceed over the two lines  上下和左右两条线同时计算
int v_sum = 0;
int d = u_max[v];
for (int u = -d; u <= d; ++u)
{
int val_plus = center[u + v*step], val_minus = center[u - v*step];
//计算上下的时候是有符号的，所以这边是减
v_sum += (val_plus - val_minus);
//这边加是由于u已经确定好了符号
m_10 += u * (val_plus + val_minus);
}
m_01 += v * v_sum;
}

return fastAtan2((float)m_01, (float)m_10);
}

#### 2.C实现＋测试（读取图片）

//#include"stdafx.h"
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2\imgproc\types_c.h>
#include <math.h>
#include<cstring>
//#include <stdlib.h>

using namespace cv;
using namespace std;

typedef struct
{
float data[65536];		// 像素值
int rows, cols;		// 行数和列数

}Img;
typedef  struct
{
int x;
int y;
}my_Point;
float IC_Angle(Img *src, Img* dst, my_Point pt)
{
float M_00 =0, M_10 = 0, M_01 = 0, Qx, Qy, Angle;
for (int i = pt.x- 8; i <= pt.x + 7; i++)
{
for (int j = pt.y - 8; j <= pt.y + 7; j++)
{
M_00 = M_00 + dst->data[i * dst->cols + j];
M_10 = M_10 + i * dst->data[i * dst->cols + j];
M_01 = M_01 + j *dst->data[i * dst->cols + j];
}
}
Qx = M_10 / M_00;
Qy = M_01 / M_00;
Angle = atan((Qy - pt.y) / (Qx - pt.x))* (180/ 3.1415926);
cout << Angle << endl;
return Angle;
}
int main(int argc, char* argv[])
{
Mat src;
Mat dst;
string imgpath = "E:\\C_100_practice\\IC_Angle\\1.jpg";
//string imgpath = argv[1];
cvtColor(src, dst, CV_BGR2GRAY);
//imshow("src", src);
//imshow("dst",dst);
Img _src;
_src.rows = src.rows;
_src.cols = src.cols;
for (int i = 0; i < src.rows; i++)
for (int j = 0; j < src.cols; j++) {
_src.data[i * src.cols + j] = static_cast<float>(dst.at<uchar>(i, j));
}
Img _dst;
_dst.rows = _src.rows;
_dst.cols = _src.cols;
my_Point pt;//设置P点坐标
pt.x = 10;
pt.y = 10;
float res = IC_Angle(&_src, &_dst, pt);

waitKey(0);
return 0;
}

#### 3.C实现＋测试（随机生成数组）

#include <iostream>
#include <math.h>
#include<cstring>
#include <cstdlib>   ///生成随机数组
#include <ctime>     ///
using namespace std;
void Random(int* a, int n, int l, int r)//生成范围在l~r的随机数
{
srand(time(0));  //设置时间种子
for (int i = 0; i < n; i++) {
a[i] = rand() % (r - l + 1) + l;//生成区间r~l的随机数
}
}
void Print(int* a, int n)
{
for (int i = 0; i < n; i++)
cout << a[i] << " ";
cout << endl;
}
int arrSum(int* arr, int len)//M00
{
int i = 0, sum = 0;
for (i = 0; i < len; i++)
sum += arr[i];
return sum;
}
int arrSum_x(int* arr, int len)// M10
{
int i = 0, j = 0,sum = 0;
for (i = 0; i < len; i++)
{
for (j = 0;j < len; j++) {
sum += i * arr[i*16+j];
}
}
return sum;
}
int arrSum_y(int* arr, int len)// M10
{
int i = 0, j = 0, sum = 0;
for (i = 0; i < len; i++)
{
for (j = 0; j< len; j++) {
sum += j * arr[i * 16 + j];
}
}
return sum;
}

int main()
{
int a[256];//数组元素的个数，即生成随机数的个数、 模拟一个16*16 的图片 所以生成256 个数
Random(a, 256, 1, 10);//生成随机数的通常范围为0~32767，这里通过取模控制取值为0~10
Print(a, 256);
my_Point pt;//设置P点坐标
pt.x = 7;
pt.y = 7;
float M_00 = 0, M_10 = 0, M_01 = 0, Qx, Qy, Angle;
for (int i = 0; i < 16; i++)
{
for (int j = 0; j <16; j++)
{
M_00 = M_00 + a[i * 16 + j];
M_10 = M_10 + i * a[i * 16 + j];
M_01 = M_01 + j * a[i * 16 + j];
}
}
Qx = M_10 / M_00;
Qy = M_01 / M_00;
Angle = atan((Qy - pt.y) / (Qx - pt.x)) * (180 / 3.1415926);
double  I = arrSum(a, 256);
double  qx = arrSum_x(a, 16)/I;
double  qy = arrSum_y(a, 16) / I;
cout << "Qx: " << Qx << endl;
cout << "Qy: " << Qy << endl;
cout << "qx: " << qx << endl;
cout << "qy: " << qy << endl;
cout << "I: " << I << endl;
cout << Angle << endl;
return 0;
}

#### 4.参考阅读

（i） ORB算法解读.
（ii）VS配置OpenCv.注意动态链接库的配置

05-18 2万+
01-14 5万+
12-23 983
03-31 1万+
03-17 1万+