导航:首页 > 源码编译 > brief算法

brief算法

发布时间:2022-10-04 20:34:41

Ⅰ brief特征描述子算法用matlab来编写的话怎么实现点对的选择

以下是遗传算法的伪代码。
BEGIN:
I = 0; //进化种群代数
Initialize P(I); //初始化种群
Fitness P(I); //“适者生存”遗传选择
While(not Terminate-Condition) //不满足终止条件时,循环
{
I ++; //循环
GA-Operation P(I); //遗传算法运算or操作
Fitness P(I); //“适者生存”遗传选择
}
END. //结束算法

Ⅱ 谁知道用C++实现后缀变中缀的算法呀

后缀式转中缀式么?

下面是代码,如有帮助,谢谢采纳

#include <iostream>
#include <string>
#include <stack>
using namespace std;
/* 运算符类,含符号和优先级,目前只支持四则运算 */
struct exp_symbol{
char op;
int priority;
exp_symbol(char op=0)
{
this->op = 0;
priority = 255;
if( '+' == op || '-' == op )
{
this->op = op;
priority = 1;
}
else if( '*' == op || '/' == op )
{
this->op = op;
priority = 2;
}
}
exp_symbol(const exp_symbol &sym):op(sym.op),priority(sym.priority){ }
friend bool operator < (const exp_symbol &l_sym, const exp_symbol &r_sym)
{
return (l_sym.priority < r_sym.priority) ? true : false;
}
exp_symbol & operator = (const exp_symbol &r_sym)
{
if( this != &r_sym )
{
op = r_sym.op;
priority = r_sym.priority;
}
return *this;
}
};
/* 表达式类,表达式字符串和运算符构成 */
struct expression{
string expr;
exp_symbol ex_sym;
expression(double x):ex_sym(0)
{
char buffer[64];
sprintf(buffer,"%g", x);
expr = buffer;
}
expression(const exp_symbol &sym, const string &l_expr, const exp_symbol &l_sym, const string &r_expr, const exp_symbol &r_sym):ex_sym(sym)
{
char op = sym.op;
if( l_sym < sym )
expr = "( " + l_expr + " ) " + op + ' ';
else
expr = l_expr + ' ' + op + ' ';
if( sym < r_sym )
expr += r_expr;
else
expr = expr + "( " + r_expr + " )";
}
expression(const expression &exp):expr(exp.expr), ex_sym(exp.ex_sym){ }
};
/* 从字符串中输入一个运算符 */
static int getsymbol(const char * &src_expr, exp_symbol &op_sym)
{
char op=0;
int len=0;
do {
if(0 == sscanf(src_expr, "%c%n", &op, &len))
break;
src_expr += len;
} while( ' ' == op );
op_sym = exp_symbol(op);
return (int)op_sym.op;
}
/**
* @brief 后缀表达式转中缀表达式
* @note <表达式>=<常数>|<表达式><运算符><表达式>
* @note 遇到常数,压栈;遇到运算符,从栈中弹出两个表达式,与运算符合成新的表达式,压栈;直到输入结束
*/
int PostToMiddleExpr(const char * src_expr, string & dst_expr)
{
double x = 0.0;
int len=0, bValid=1;
exp_symbol op_sym(0);
std::stack<expression> stExpr;

while( bValid )
{
bValid = 0;
if( sscanf(src_expr, "%lf%n", &x, &len) > 0 ) /* 运算数,直接入栈 */
{
src_expr += len;
stExpr.push( expression(x) );
bValid = 1;
}
else if( getsymbol(src_expr, op_sym) > 0 ) /* 运算符,出栈两个表达式,组成新的表达式 */
{
if(!stExpr.empty())
{
const expression &expr2 = stExpr.top();
string r_expr = expr2.expr;
exp_symbol r_sym = expr2.ex_sym;
stExpr.pop();
if(!stExpr.empty())
{
const expression &expr1 = stExpr.top();
string l_expr = expr1.expr;
exp_symbol l_sym = expr1.ex_sym;
stExpr.pop();
stExpr.push(expression(op_sym, l_expr,l_sym, r_expr, r_sym));
bValid = 1;
}
}
}
}

/* 判断表达式栈并返回中缀表达式 */
if(stExpr.empty())
return -1;
dst_expr = stExpr.top().expr;
stExpr.pop();
if(!stExpr.empty())
{
do{
stExpr.pop();
}while(!stExpr.empty());
return -1;
}
return 0;
}
/**
* 后缀表达式转中缀表达式的试验程序~
*/
int main( void )
{
string dst_expr;
const char *src_str = "19.3 23.4 - 3.5 * 1.7 + 1.4 / 3.4 *";
PostToMiddleExpr( src_str, dst_expr);
cout << "dst_expr = "<< dst_expr << endl;
return 0;
}

Ⅲ opencv提供了多少个特征点的descriptor

OpenCV 中和 2D 特征检测相关的算法的头文件位于

opencv\moles\features2d\include\opencv2\features2d.hpp,除SIFT、SURF以外的特征。

opencv\moles\nonfree\include\opencv2\nonfree\features2d.hpp,只包含SIFT、SURF这两个受专利保护的特征,因此不是免费的(nonfree)。

我们来看具体的类
DescriptorExtractor 的子类都是描述子提取器,包含

FREAKBriefDescriptorExtractor

FeatureDetector 的子类都是特征检测器,包含

MSER

StarDetector,又名 StarFeatureDetector

FastFeatureDetector

GFTTDetector,又名 GoodFeaturesToTrackDetector

SimpleBlobDetector

DenseFeatureDetector

FeatureDetector 还提供一系列特殊的适配器子类,用于增强或加速之前的 FeatureDetector 类

GridAdaptedFeatureDetector

PyramidAdaptedFeatureDetector
AdjusterAdapter

DynamicAdaptedFeatureDetector

FastAdjuster

StarAdjuster

SurfAdjuster

Feature2D 的子类既是 FeatureDetector,又是 DescriptorExtractor,包含

BRISK

ORB

SIFT

SURF
希望这个回答可以授之以渔。

Ⅳ 小波算法

Function wavelet(s,wname,n,options);
Begin
{
功能:
一维序列小波消噪。
参数:
s:一维序列
wname:小波函数名
现有小波函数名(小波函数的选取依靠经验)
Daubechies:
'db1' , 'db2', ... ,'db45' 'db1' 就是haar 小波函数

Coiflets :
'coif1', ... , 'coif5'
Symlets :
'sym2' , ... , 'sym8'
Biorthogonal:
'bior1.1', 'bior1.3' , 'bior1.5'
'bior2.2', 'bior2.4' , 'bior2.6', 'bior2.8'
'bior3.1', 'bior3.3' , 'bior3.5', 'bior3.7'
'bior3.9', 'bior4.4' , 'bior5.5', 'bior6.8'.
Reverse Biorthogonal:
'rbio1.1', 'rbio1.3' , 'rbio1.5'
'rbio2.2', 'rbio2.4' , 'rbio2.6', 'rbio2.8'
'rbio3.1', 'rbio3.3' , 'rbio3.5', 'rbio3.7'
'rbio3.9', 'rbio4.4' , 'rbio5.5', 'rbio6.8'.

n :分解层数
options : 选项
选择字段说明
array('brief':1, // 默认为1 采用简单剔除高频谐波 达到消噪的目的
// 如果为 0 采用估计序列噪音标准差剔除噪音,
'sigma':0, // 为0 默认采用 序列的高阶谐波估计标准差;也可自己输入值
'which':1, // 以 某一层谐波作为噪音估计的数据,默认第一层
'alpha':2, // 阈值惩罚系数,默认为2
"thr":0, // 阈值大小,默认0 采用谐波估计,也可以直接给出
'sorh':'s', // 阈值方式设置,'s' 软阈值,'h'硬阈值 默认为's'
);

返回结果:
一维数字数组,消噪后的序列。
范例:
s := array(2484.82690429688,2479.05493164063,2482.34301757813,2437.794921875,
2447.7548828125,2512.962890625,2443.05688476563,2433.15893554688,
2393.18310546875,2415.05395507813,2392.06201171875,2365.34301757813,
2359.21997070313,2344.787109375,2348.51611328125,2420.00,2438.7900390625,
2431.375,2440.40209960938,2383.48510742188,2377.51196289063,2331.36596679688,
2317.27490234375,2370.3330078125,2409.67211914063,2427.47998046875,
2435.61401367188,2473.40991210938,2468.25,2470.01904296875,2504.10791015625,
2508.09008789063,2528.2939453125,2509.79907226563,2503.8359375,2524.9189453125,
2479.53588867188,2481.083984375,2528.71411132813,2529.76098632813,2466.958984375,
2463.0458984375,2416.56201171875,2415.1298828125,2412.625,2395.06494140625,
2397.55395507813,2380.22412109375,2383.03393554688,2412.39306640625,
2333.4140625,2386.86010742188,2360.6640625,2333.22900390625,2325.90502929688,
2332.72998046875,2329.82006835938,2315.27001953125,2291.544921875,2248.59008789063,
2228.52490234375,2180.89501953125,2224.84008789063,2218.23510742188,2215.92993164063,
2191.14794921875,2186.29711914063,2204.78393554688,2190.11010742188,2166.205078125,
2170.01293945313,2173.56103515625,2199.4169921875,2169.38989257813,2148.45190429688,
2163.39501953125,2225.88989257813,2285.74389648438,2276.0458984375,2275.01000976563,
2244.580078125,2206.19311523438,2298.3759765625,2266.38403320313,2296.07495117188,
2319.11791992188,2285.0380859375,2292.61010742188,2268.080078125,2312.55590820313,
2330.40502929688,2331.13598632813,2291.90209960938,2347.53002929688,2349.58911132813,
2351.98095703125,2351.85498046875,2344.77099609375,2366.70190429688,2356.86010742188,
2357.18090820313,2363.59692382813,2381.42993164063,2403.5869140625,2409.55395507813,
2439.6279296875,2447.05688476563,2451.85693359375,2428.48706054688,2426.11499023438,
2460.69311523438);
n := 2;
options := array('brief':1,'sigma':0,'which':1,'alpha':2,"thr":0,'sorh':'s');
return wavelet(s,wname,n,options) ;

天软数学组
20120627
}

if not ifarray(options) then options := array();
defaut := wavedefaut() union options;
cout := 4;
cl:=wavedec(s,n,wname); //小波分解
if defaut['brief']=1 then
ret :=wrcoef('a',cl[0],cl[1],wname,n);
else
begin
//***************小波消噪*************************************************
k := defaut['which']; //标准差估计选项 ,k 为 1 到 n的整数 默认为1;
if defaut['sigma']=0 then sigma := wnoisest(cl[0],cl[1],k);
else //通过小波第k层细节系数(谐波)估计 ,噪音标准差
sigma := defaut['segma'];
if defaut['alpha']=0 then alpha :=2; // alpha 惩罚因子 大于1 的数 一般为默认2;
else alpha := defaut['alpha'];
if defaut['thr']=0 then
thr := wbmpen(cl[0],cl[1],sigma,alpha); //噪音信号全局阈值
else thr := defaut['thr'];
sorh := defaut['sorh'];
ret:=wdencmp('gbl',cl[0],cl[1],wname,n,thr,sorh)[0]; //采用软阈值和近似信号进行消噪;
end //第一个参数为'gbl'为扩展接口备用,可以随意输入
return ret;
end;
function wavedefaut();
begin
return array('brief':1,'sigma':0,'which':1,'alpha':2,
"thr":0,'sorh':'s'
);

end

Ⅳ opencv surf算法连线颜色怎么设置一样

/**
* @file SURF_Homography
* @brief SURF detector + descriptor + FLANN Matcher + FindHomography
* @author A. Huaman
*/

#include <stdio.h>
#include <iostream>
#include <cv.h>
#include "opencv2/core/core.hpp"
#include <opencv2/opencv.hpp>
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/nonfree/features2d.hpp"
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/nonfree/nonfree.hpp>

using namespace cv;
using namespace std;

#ifdef _DEBUG
#pragma comment (lib, "opencv_calib3d246d.lib")
#pragma comment (lib, "opencv_contrib246d.lib")
#pragma comment (lib,"opencv_imgproc246d.lib")
#pragma comment (lib, "opencv_core246d.lib")
#pragma comment (lib, "opencv_features2d246d.lib")
#pragma comment (lib, "opencv_flann246d.lib")
#pragma comment (lib, "opencv_gpu246d.lib")
#pragma comment (lib, "opencv_highgui246d.lib")
#pragma comment (lib, "opencv_legacy246d.lib")
#pragma comment (lib, "opencv_ml246d.lib")
#pragma comment (lib, "opencv_objdetect246d.lib")
#pragma comment (lib, "opencv_ts246d.lib")
#pragma comment (lib, "opencv_video246d.lib")
#pragma comment (lib, "opencv_nonfree246d.lib")
#else
#pragma comment (lib, "opencv_calib3d246.lib")
#pragma comment (lib, "opencv_contrib246.lib")
#pragma comment (lib, "opencv_imgproc246.lib")
#pragma comment (lib, "opencv_core246.lib")
#pragma comment (lib, "opencv_features2d246.lib")
#pragma comment (lib, "opencv_flann246.lib")
#pragma comment (lib, "opencv_gpu246.lib")
#pragma comment (lib, "opencv_highgui246.lib")
#pragma comment (lib, "opencv_legacy246.lib")
#pragma comment (lib, "opencv_ml246.lib")
#pragma comment (lib, "opencv_objdetect246.lib")
#pragma comment (lib, "opencv_ts246.lib")
#pragma comment (lib, "opencv_video246.lib")
#pragma comment (lib, "opencv_nonfree246.lib")
#endif

int main()
{
initMole_nonfree();//初始化模块,使用SIFT或SURF时用到
Ptr<FeatureDetector> detector = FeatureDetector::create( "SURF" );//创建SIFT特征检测器,可改成SURF/ORB
Ptr<DescriptorExtractor> descriptor_extractor = DescriptorExtractor::create( "SURF" );//创建特征向量生成器,可改成SURF/ORB
Ptr<DescriptorMatcher> descriptor_matcher = DescriptorMatcher::create( "BruteForce" );//创建特征匹配器
if( detector.empty() || descriptor_extractor.empty() )
cout<<"fail to create detector!";

//读入图像
Mat img1 = imread("1.jpg");
Mat img2 = imread("2.jpg");

//特征点检测
double t = getTickCount();//当前滴答数
vector<KeyPoint> m_LeftKey,m_RightKey;
detector->detect( img1, m_LeftKey );//检测img1中的SIFT特征点,存储到m_LeftKey中
detector->detect( img2, m_RightKey );
cout<<"图像1特征点个数:"<<m_LeftKey.size()<<endl;
cout<<"图像2特征点个数:"<<m_RightKey.size()<<endl;

//根据特征点计算特征描述子矩阵,即特征向量矩阵
Mat descriptors1,descriptors2;
descriptor_extractor->compute( img1, m_LeftKey, descriptors1 );
descriptor_extractor->compute( img2, m_RightKey, descriptors2 );
t = ((double)getTickCount() - t)/getTickFrequency();
cout<<"SIFT算法用时:"<<t<<"秒"<<endl;

cout<<"图像1特征描述矩阵大小:"<<descriptors1.size()
<<",特征向量个数:"<<descriptors1.rows<<",维数:"<<descriptors1.cols<<endl;
cout<<"图像2特征描述矩阵大小:"<<descriptors2.size()
<<",特征向量个数:"<<descriptors2.rows<<",维数:"<<descriptors2.cols<<endl;

//画出特征点
Mat img_m_LeftKey,img_m_RightKey;
drawKeypoints(img1,m_LeftKey,img_m_LeftKey,Scalar::all(-1),0);
drawKeypoints(img2,m_RightKey,img_m_RightKey,Scalar::all(-1),0);
//imshow("Src1",img_m_LeftKey);
//imshow("Src2",img_m_RightKey);

//特征匹配
vector<DMatch> matches;//匹配结果
descriptor_matcher->match( descriptors1, descriptors2, matches );//匹配两个图像的特征矩阵
cout<<"Match个数:"<<matches.size()<<endl;

//计算匹配结果中距离的最大和最小值
//距离是指两个特征向量间的欧式距离,表明两个特征的差异,值越小表明两个特征点越接近
double max_dist = 0;
double min_dist = 100;
for(int i=0; i<matches.size(); i++)
{
double dist = matches[i].distance;
if(dist < min_dist) min_dist = dist;
if(dist > max_dist) max_dist = dist;
}
cout<<"最大距离:"<<max_dist<<endl;
cout<<"最小距离:"<<min_dist<<endl;

//筛选出较好的匹配点
vector<DMatch> goodMatches;
for(int i=0; i<matches.size(); i++)
{
if(matches[i].distance < 0.2 * max_dist)
{
goodMatches.push_back(matches[i]);
}
}
cout<<"goodMatch个数:"<<goodMatches.size()<<endl;

//画出匹配结果
Mat img_matches;
//红色连接的是匹配的特征点对,绿色是未匹配的特征点
drawMatches(img1,m_LeftKey,img2,m_RightKey,goodMatches,img_matches,
Scalar::all(-1)/*CV_RGB(255,0,0)*/,CV_RGB(0,255,0),Mat(),2);

imshow("MatchSIFT",img_matches);
IplImage result=img_matches;

waitKey(0);

//RANSAC匹配过程
vector<DMatch> m_Matches=goodMatches;
// 分配空间
int ptCount = (int)m_Matches.size();
Mat p1(ptCount, 2, CV_32F);
Mat p2(ptCount, 2, CV_32F);

// 把Keypoint转换为Mat
Point2f pt;
for (int i=0; i<ptCount; i++)
{
pt = m_LeftKey[m_Matches[i].queryIdx].pt;
p1.at<float>(i, 0) = pt.x;
p1.at<float>(i, 1) = pt.y;

pt = m_RightKey[m_Matches[i].trainIdx].pt;
p2.at<float>(i, 0) = pt.x;
p2.at<float>(i, 1) = pt.y;
}

// 用RANSAC方法计算F
Mat m_Fundamental;
vector<uchar> m_RANSACStatus; // 这个变量用于存储RANSAC后每个点的状态
findFundamentalMat(p1, p2, m_RANSACStatus, FM_RANSAC);

// 计算野点个数

int OutlinerCount = 0;
for (int i=0; i<ptCount; i++)
{
if (m_RANSACStatus[i] == 0) // 状态为0表示野点
{
OutlinerCount++;
}
}
int InlinerCount = ptCount - OutlinerCount; // 计算内点
cout<<"内点数为:"<<InlinerCount<<endl;

// 这三个变量用于保存内点和匹配关系
vector<Point2f> m_LeftInlier;
vector<Point2f> m_RightInlier;
vector<DMatch> m_InlierMatches;

m_InlierMatches.resize(InlinerCount);
m_LeftInlier.resize(InlinerCount);
m_RightInlier.resize(InlinerCount);
InlinerCount=0;
float inlier_minRx=img1.cols; //用于存储内点中右图最小横坐标,以便后续融合

for (int i=0; i<ptCount; i++)
{
if (m_RANSACStatus[i] != 0)
{
m_LeftInlier[InlinerCount].x = p1.at<float>(i, 0);
m_LeftInlier[InlinerCount].y = p1.at<float>(i, 1);
m_RightInlier[InlinerCount].x = p2.at<float>(i, 0);
m_RightInlier[InlinerCount].y = p2.at<float>(i, 1);
m_InlierMatches[InlinerCount].queryIdx = InlinerCount;
m_InlierMatches[InlinerCount].trainIdx = InlinerCount;

if(m_RightInlier[InlinerCount].x<inlier_minRx) inlier_minRx=m_RightInlier[InlinerCount].x; //存储内点中右图最小横坐标

InlinerCount++;
}
}

// 把内点转换为drawMatches可以使用的格式
vector<KeyPoint> key1(InlinerCount);
vector<KeyPoint> key2(InlinerCount);
KeyPoint::convert(m_LeftInlier, key1);
KeyPoint::convert(m_RightInlier, key2);

// 显示计算F过后的内点匹配
Mat OutImage;
drawMatches(img1, key1, img2, key2, m_InlierMatches, OutImage);
cvNamedWindow( "Match features", 1);
cvShowImage("Match features", &IplImage(OutImage));
waitKey(0);

cvDestroyAllWindows();

//矩阵H用以存储RANSAC得到的单应矩阵
Mat H = findHomography( m_LeftInlier, m_RightInlier, RANSAC );

//存储左图四角,及其变换到右图位置
std::vector<Point2f> obj_corners(4);
obj_corners[0] = Point(0,0); obj_corners[1] = Point( img1.cols, 0 );
obj_corners[2] = Point( img1.cols, img1.rows ); obj_corners[3] = Point( 0, img1.rows );
std::vector<Point2f> scene_corners(4);
perspectiveTransform( obj_corners, scene_corners, H);

//画出变换后图像位置
Point2f offset( (float)img1.cols, 0);
line( OutImage, scene_corners[0]+offset, scene_corners[1]+offset, Scalar( 0, 255, 0), 4 );
line( OutImage, scene_corners[1]+offset, scene_corners[2]+offset, Scalar( 0, 255, 0), 4 );
line( OutImage, scene_corners[2]+offset, scene_corners[3]+offset, Scalar( 0, 255, 0), 4 );
line( OutImage, scene_corners[3]+offset, scene_corners[0]+offset, Scalar( 0, 255, 0), 4 );
imshow( "Good Matches & Object detection", OutImage );

waitKey(0);
imwrite("warp_position.jpg",OutImage);

int drift = scene_corners[1].x; //储存偏移量

Ⅵ 8点算法 需要哪些sift数据

一、特征点(角点)匹配图像匹配能够应用的场合非常多,如目标跟踪,检测,识别,图像拼接等,而角点匹配最核心的技术就要属角点匹配了,所谓角点匹配是指寻找两幅图像之间的特征像素点的对应关系,从而确定两幅图像的位置关系。角点匹配可以分为以下四个步骤:1、提取检测子:在两张待匹配的图像中寻找那些最容易识别的像素点(角点),比如纹理丰富的物体边缘点等。2、提取描述子:对于检测出的角点,用一些数学上的特征对其进行描述,如梯度直方图,局部随机二值特征等。检测子和描述子的常用提取方法有:sift,harris,surf,fast,agast,brisk,freak,brisk,brief/orb等。3、匹配:通过各个角点的描述子来判断它们在两张图像中的对应关系,常用方法如flann等。4、消噪:去除错误匹配的外点,保留正确的匹配点。常用方法有KDTREE,BBF,Ransac,GTM等。二、SIFT匹配方法的提出为了排除因为图像遮挡和背景混乱而产生的无匹配关系的关键点,SIFT的作者Lowe提出了比较最近邻距离与次近邻距离的SIFT匹配方式:取一幅图像中的一个SIFT关键点,并找出其与另一幅图像中欧式距离最近的前两个关键点,在这两个关键点中,如果最近的距离除以次近的距离得到的比率ratio少于某个阈值T,则接受这一对匹配点。因为对于错误匹配,由于特征空间的高维性,相似的距离可能有大量其他的错误匹配,从而它的ratio值比较高。显然降低这个比例阈值T,SIFT匹配点数目会减少,但更加稳定,反之亦然。Lowe推荐ratio的阈值为0.8,但作者对大量任意存在尺度、旋转和亮度变化的两幅图片进行匹配,结果表明ratio取值在0.4~0.6之间最佳,小于0.4的很少有匹配点,大于0.6的则存在大量错误匹配点,所以建议ratio的取值原则如下:ratio=0.4:对于准确度要求高的匹配;ratio=0.6:对于匹配点数目要求比较多的匹配;ratio=0.5:一般情况下。三、常见的SIFT匹配代码1、vlfeat中sifttoolbox中的vl_ubcmatch.c使用的是普通的欧氏距离进行匹配(该SIFT代码贡献自AndreaVedaldi)。2、Lowe的C++代码中使用的是欧氏距离,但是在matlab代码中为了加速计算,使用的是向量夹角来近似欧氏距离:先将128维SIFT特征向量归一化为单位向量(每个数除以平方和的平方根),然后点乘来得到向量夹角的余弦值,最后利用反余弦(acos函数)求取向量夹角。实验证明Lowe的法正确率和耗时都很不错。同样,也可以采用knnsearch函数求最近点和次近点:knnsearch采用euclidean距离时得到的结果与lowe采用的近似方法结果几乎一致,正好印证了模拟欧氏距离的效果。3、RobHess的OpenSIFT采用了KDTREE来对匹配进行优化。4、CSDN大神v_JULY_v实现了KDTREE+BBF对SIFT匹配的优化和消除错误匹配:从K近邻算法、距离度量谈到KD树、SIFT+BBF算法-结构之法算法之道-博客频道-CSDN.NET。5、OpenCV中features2d实现的SIFT匹配有多种matcher:VectorDescriptorMatcher,BFMatcher(Brute-forcedescriptormatcher),FernDescriptorMatcher,OneWayDescriptorMatcher,FlannBasedMatcher等等。目前只知道采用knnsearch,提供了多种距离度量方式,具体区别不懂。

Ⅶ 请教如何在delpih中使用HMAC-SHA1算法

* @brief 使用HMAC-SHA1算法生成oauth_signature签名值
*
* @param $key 密钥
* @param $str 源串
*
* @return 签名值
*/
function getSignature($str, $key) {
$signature = "";
if (function_exists('hash_hmac')) {
$signature = base64_encode(hash_hmac("sha1", $str, $key, true));
} else {
$blocksize = 64;
$hashfunc = 'sha1';
if (strlen($key) > $blocksize) {
$key = pack('H*', $hashfunc($key));
}
$key = str_pad($key, $blocksize, chr(0x00));
$ipad = str_repeat(chr(0x36), $blocksize);
$opad = str_repeat(chr(0x5c), $blocksize);
$hmac = pack(
'H*', $hashfunc(
($key ^ $opad) . pack(
'H*', $hashfunc(
($key ^ $ipad) . $str
)
)
)
);
$signature = base64_encode($hmac);
}

return $signature;
}

Ⅷ 120由浅入深学网络--静态路由与动态路由

我们在 VLAN 的实验中学习到 VLAN 能够很好的隔离网路,减小广播域,但是隔离了网络的广播域也就意味着它们将处于不同的网络之中,这样仅仅依靠数据链路层的帧是无法相互通信的。所以若是我们需要 VLAN 间能够相互通信就必须得依靠网络的第三层网络层,通过路由的功能来连接两个不同网络使之相互通信。

使两个 VLAN 相互通信我们称之为 VLAN 间的路由,而实现这一功能的方法有两个:
单臂路由
SVI 接口

单臂路由(one-armed router 或者 router-on-a-stick)是指在路由器的一个接口上通过配置子接口(或“逻辑接口”,并不存在真正物理接口)的方式,实现原来相互隔离的不同 VLAN(虚拟局域网)之间的互联互通。
单臂路由就是依靠的路由器的路由功能,因为二层交换机没有办法实现路由。同时一个接口只能接收来自一个 VLAN 的数据(因为一个接口不能隶属于多个 VLAN),传统的 VLAN 间路由方式便是在 Switch 与 Router 之间连接多个端口以保证多个接收多个 VLAN 的数据,但是当 VLAN 很多的情况下,Router 不可能满足这么多端口,所以出现了子端口的实现,这是一种依靠软件实现的逻辑上的端口。这样便只需要通过一根物理连接线来实现多个 VLAN 接口的连接。

我们通过这样的一个实验来实现单臂路由的功能:
实验目的:配置实现单臂路由
实验材料:三台交换机、一台路由器

实验方法:
拖动三台交换机、一台路由器至画布,两台用作模拟PC,一台用所模拟 Switch,一台用作 Router
配置路由器、交换机的名字与连接线路
配置交换机中的 vlan,以及三个接口的模式
配置两台 PC 的 IP 地址与默认网关(下文详解),他们处于不同的 VLAN 中
配置路由器的子接口,以及子接口的 IP 地址
尝试使用 PC 相互 ping 通

1.构建实验环境,在画布中拖出三台交换机与一台路由器,并修改他们的设备名称,同时修改两台用作模拟 PC 的交换机图标,然后相互连接。结构如图所示:

2.配置交换机相关的内容,在 Switch1 中配置两个 VLAN,分别为 vlan 2:test2、vlan 3:test3。同时将与 PC 连接的两个端口分别配置为 access vlan 2 与 access vlan 3,还有与路由器相连接的端口配置为 trunk 模式。若是与路由器相连接的端口不配置成 trunk 模式将无法发送多个 vlan 的数据包。

3.修改 PC 端口的 IP 地址

此时我们可以尝试通过 PC1 去 ping PC2,我们会发现肯定是 ping 不通的,因为他们处于不同的网段同时处于不同的 VLAN 中。

3.为两台 PC 配置默认网关(默认网关用于将数据包发送至路由端口,下文详解)

可用回到特权模式中,通过 show ip route 查看,是否成功配置:

4.在路由器中配置逻辑子接口,分别用于接收 vlan2 与 vlan3 的数据。因为是接收来自交换机发来的信息,所以该子接口的数据封装模式与交换机中的相同,交换机此处 trunk 模式使用的是 dot1q 的封装方法,所以子接口中的也必须是这个方法。(还记得在 VLAN 划分实验中我们将到 trunk 模式主要作用是添加 VLAN 标签)

这样我们就成功的配置好了我们的子端口,我们可以通过 show ip int brief 查看接口信息中是否有这两个子接口的配置,还可以通过 show vlans 查看子接口的状态,以及通过 show ip route 命令来查看当前的路由信息,若是有两个直连路由表项,说明我们配置成功的生效了:

5.完成了所有的配置,准备工作,我们再次尝试通过使用 PC1 去 Ping PC2 发现 5个点都变成了感叹号,表示所有的 ICMP 包(ping 工具使用的是 ICMP 协议)都得到了响应,PC1 可以与 PC2 正常通信了:

由上述的两个原因,为此出现了一种新的功能,便是在三层交换上的 SVI 接口,这样便不需要单独添加一台路由器了。
SVI 是 Switch Virtual Interface 的简称。它是三层交换机上的一个虚拟端口,类似于 Router 上的子端口,由软件实现。每个 SVI 只能关联一个 VLAN,设置一个 IP 地址。

基于上个实验,我们做出这样的修改:
去除 Router 设备
设置 SVI 接口地址

我们将去除 Router 设备,由我们的三层交换机来实现相关的功能,将之前的网关地址设置为 SVI 的 IP 地址即可

1.去除 Router 设备,关闭 Switch 上的 e0/0 接口,同时配置 SVI 的 IP 地址:

如此便完成了 SVI 的配置,我们可以在 Switch 的特权模式中使用 show ip route 可以看到此时我们有两个直连的路由信息。同时我们还可以尝试使用 PC1 去 ping PC2。(若是配置与我完全一致,但是 ping 不通,可以尝试在 Switch 的全局模式中使用 no ip cef 命令)

此处使用 no ip cef 命令关闭转发机制便是该版本的镜像并没有很好的在 Linux 中实现其提供的功能,可能该镜像的设备本是使用硬件辅助实现该功能等等。若是不关闭 cef 的转发机制,将导致你明明配置无误,却无法正常的通信。
由此我们便成功的配置了单臂路由与 SVI 接口来成功的实现 VLAN 之间的相互通信了。

在之前的实验中我们经常提到默认网关之一名词,接下来我们便来了解一下该名词的含义。
默认网关由两个词组成默认与网关。其中什么叫做网关呢?
网关(Gateway)就是一个网络与另一个网络连接的关口。

比如成都市与广州市都只有一个邮局,而每个邮局前都会有一个专职的负责人,此时若是成都市的小明想与广州市的小红联系只能通过这样的一个过程:
首先将写好的信交给邮局的专职负责人,
邮局的专职负责人查看信封上的地址,发现该地址并不是本省中的地址,并且邮编写的是广东省的地址。
成都的邮局专职负责人便将该消息转发送给广州的邮局专职负责人,让他交给收件人
广州的邮局专职负责人收到信封后,发现目的地址便是本省中的地址,便寻找该地址将消息送到收件人的手中。

在这个例子中邮局的专职负责人便是网关。负责将本网段中的消息发送给其他网段的网关的接口。
默认网关的意思是一台主机如果找不到可用的网关,就把数据包发给默认指定的网关,由这个网关来处理数据包。只要指定了默认网关之后,只要主机在发送数据包之前由目的地址与其子网掩码做 AND 运算得出的网络号与本机的网络号不同,便将数据发送给默认网关,由默认网关处理数据该如何发送。

在全局模式中我们可以通过这样的命令来实现默认网关的配置:

通过 show ip route 我们可以看到这样的结果:

我们了解到数据包发送到其他网段是通过查询路由表,然后决定下一跳发送的路径。而路由表中的表项是如何得来的呢?

首先以路由的角度将协议分为:
可路由协议(Routed Protocol):利用网络层完成通信的协议,例如 IP、IPX 等,该对象是被路由的。
路由协议(Routing Protocol):主要用于创建与维护路由表,本质是实现路由功能,该对象是路由其他对象的,例如 RIP、OSPF、IGRP、IS-IS 等等。

而路由表中的信息分为两大类:
直连路由:也就是该设备中的接口所配置的 IP 地址与其所处的网络
远程路由:也就是发向其他路由设备所处的 IP 地址与其所处的网络

直连路由是在 IP 接口地址配置后便自动添加的,而远程路由的信息来源又会分为两大类:
静态路由:由人工配置的下一跳地址,在网络拓扑发生变化时同样需要人工修改,但是配置完成之后并不会占用过多的系统资源,与网络的带宽。在静态路由中有缺省路由(也就是默认路由)、浮动路由的存在。适用于小型网络与末梢网络
动态路由:通过动态路由协议,设备与设备之间相互通信,相互学习。再由某种路由算法计算出下一跳的路径,当有多条路径的时候还有优先级的排序,并且在网络拓扑发生变化的时候,会自动学习网络中的变化适当改变路径,适用于大型网络。

其中动态路由协议有这样几种分类的标准:
按算法分为:距离矢量(典型的协议有 RIP、IGRP、BGP)、链路状态(典型的协议有 OSPF IS-IS)、混合算法(典型的协议有 EIGRP)
按照是否发送子网掩码分为:有类(典型的有 RIP、IGRP)与无类(支持子网划分与路由汇总,典型的有 OSPF 等)
按照使用的网络规模分为:IGP(Interior gateway protocol),内部网关协议,几乎所有的路由协议都属于内部网关协议)与 EGP(Exterior Gateway Protocol),外部网关协议,BGP 用于自治系统之间的路由计算)

其中按照算法分的距离矢量表示的是根据源到目的的跳数来计算(之前有提过,下一跳表示去往下一个路由);所谓的链路状态便是多方面考虑如链路的开销、链路上的所有的相邻路由器、网络带宽,网络拥塞等等综合考虑;所谓的混合算法便是这两个的结合考虑。
其中的自治系统是表示属于某一个特定的网络机构中路由集合。在自治系统内部使用的路由协议就是内部网关协议,而自治系统之间的是外部网关协议。

反应路由性能的参考对象主要还是收敛时间与管理距离(在上一节实验我们都提到过):
收敛时间(convergence time):从网络拓扑变化到网络中所有的路由器都知道这个变化的时间就叫收敛时间;
管理距离(administrative distance):用于综合评价路由协议性能参数,描述路由协议计算路由条目的准确度与可信度。

所谓的静态路由便是由纯手工的配置在路由表项中,这样的配置路由方式非常的耗时,效率不高,并且在网络拓扑发生改变的时候需要手工的一项一项的修改,十分的麻烦,事情总是利弊双面的,有弊就有利,虽然麻烦但是就因为不会自动学习修改所以不会发送通告占用带宽,也不会占用太多的 CPU 与 RAM 这样的系统资源。并且可以手工控制数据包的转发路径,因此静态路由在小型企业中还是十分常用。
静态路由的配置很简单,只需要通过这样的一条命令即可:

我们可以通过这样的例子来学习静态路由的配置:
还是使用上述 SVI 的实验环境,我们在 Switch 上添加一个路由,并且配置为 202.203.0.0 这个网段下:

此时 PC 肯定是无法 ping 通 202.203.0.2 地址的,因为虽然在 Switch 中有该网段的路由表项(因为是直连网段),但是数据包在 Router 接收到之后,响应时发现路由表中无 192.168.1.0 网段表项,不知道怎么转发回来,便只有丢弃该数据包了。

通过 show ip route 我们可以看到静态路由成功的添加了:

并且此时可以 ping 通对端的 IP 地址:

这只是一条记录,并且只是 192.168.1.0 网段可以 ping 通,若是 PC2 去 ping 还是会不通,因为 PC2 在 192.168.2.0 网段,路由表中没有可以匹配的项。此时我们发现所有的地址都会通过 Switch,基本设备都是围绕它来的,他知道所有的路由路径,我便可以直接设置一个默认路由,也就是只要路由表中没有目的地址所匹配的表项,就都丢给默认路由。
既然如此也就代表着默认路由要匹配所有项,因为表中一旦无匹配就让他路由,换个角度就代表他得匹配所有项,而匹配所有项的地址便是 0.0.0.0,同时子网掩码也是这个值。因为 0 表示的是任意的(wildcard)
默认路由就是一种特殊的静态路由,所以若是要配置默认路由只需要将上述的命令中的目的地址与子网掩码改成 0.0.0.0 0.0.0.0 即可。

我们可以在刚刚的环境中实验一次,先擦除原先的静态路由然后再配置:

这就是便是默认路由只要路由表中没有匹配的项就让它来路由。
当然按照我们之前所说的冗余思想,避免单点故障使得一个数据包到达目的地可能有多条路径,此时我们便可以配置浮动路由,所谓的浮动路由便是当优先级较高的路径出现问题时,还有一条路径能够及时的替补上来。而优先级的体现在于我们上节实验中所提到的 AD,当值越小的时候其优先级便越高。
浮动路由的配置很简单,就是在添加备选路径时,把静态路由命令的网关地址修改以及后面添加 AD 值,该值的取值范围是 0~255。例如:

但是三层交换机并不支持浮动路由,需要路由器才能实现。

在画布中拖动两台路由器,实现这样的拓扑结构,同时配置浮动路由使得在一条线路断掉时,还是可以工作。(需要借助环回接口,在全局模式中 int loopback 0(这个为编号,自取) 便可以像配置端口一般为其配置 IP 地址了)

验证方式:
首先查看路由表中的静态路由是 192.168.1.2,并且能够 Router 设备能够 ping 通 202.204.1.1
然后 shutdown s2/0 端口,再次 ping 202.204.1.1 还是能通,并且此时的路由表的静态路由项发生变化

注意:此处使用的两个都是串口,因为 GNS3 的路由串口实现没有问题,浮动路由只需要一个端口断开,另外一边不通就知道断开了便启用浮动路由。但是若是使用的以太口,GNS3 实现出来与真实设备不同,不同之处在 GNS3 用以太口实现的话检测不出对端断开了,必须同时断开此端口与对端端口才行,所以此处使用串口。

阅读全文

与brief算法相关的资料

热点内容
解压小熊手机壳 浏览:342
成都市区建成面积算法 浏览:658
智能家居单片机 浏览:95
买男装用什么app好 浏览:853
文件夹合并了怎么拆开 浏览:257
波段副图源码无未来函数 浏览:86
livecn服务器地址 浏览:257
程序员这个工作真的很吃香吗 浏览:844
程序员和数学分析师待遇 浏览:678
压缩气弹簧怎么拆 浏览:321
华为公有云服务器添加虚拟ip 浏览:209
程序员和运营哪个累 浏览:24
抖音安卓信息提示音怎么设置 浏览:454
光速虚拟机的共享文件夹 浏览:248
程序员培训机构发的朋友圈真实性 浏览:742
天干地支简单算法 浏览:299
下载个压缩文件 浏览:300
普通人电脑关机vs程序员关机 浏览:628
米酷建站源码 浏览:115
氢气app怎么搜搭配 浏览:619