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实现+测试(读取图片)
这一部分有所改动,ORB在计算BRIEF描述子时建立的坐标系是以关键点为圆心,以关键点和取点区域的形心的连线为X轴建立2维坐标系。
这里C实现,不再是圆,而是以关键点为中心,左8右7,16*16的正方形。
//#include"stdafx.h"
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2\imgproc\types_c.h>
#include <math.h>
#include<cstring>
//#include "Ic_Angle_head.h"
//#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];
src = imread(imgpath, 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.注意动态链接库的配置