老规矩,先上背景,算是表示对LBP算法提出者的一种尊敬(其实,是为了装...kkk,大家都懂ha)。

一、LBP背景:

LBP(Local Binary Pattern,局部二值模式)是一种用来描述图像局部纹理特征的算子;它具有旋转不变性和灰度不变性等显著的优点。它是首先由T. Ojala, M.Pietikäinen, 和D. Harwood在1994年提出,用于纹理特征提取。而且,提取的特征是图像的局部的纹理特征。至今,仍在图像识别和人脸识别部分,有很好的效果。

二、LBP特征的原理:

从94年T. Ojala, M.Pietikäinen, 和D. Harwood提出至今,LBP经历过多次的改进,以下根据时间顺序介绍:

FirstBleed:

原始的LBP算子定义为在3*3的窗口内,以窗口内的中心点的像素值为标准,对比窗口内其余8个元素的像数值大小,大于中心点的位置用1表示,小于为0。如此,3*3领域内的8个点恰可产生8为二进制数字(通常转化为十进制表示成LBP值)即为中心点的LBP特征值。

上图:

SecondBleed:

原始的LBP提出后,研究人员不断对其改进和优化,以下是改进点。

(一):圆形LBP算子:

原始LBP算子固定为某个区域,在图像尺寸和频率纹理发生改变时,会出现很大的偏差,不能正确反映像素点周围的纹理信息。为适应不同尺寸的纹理特征,Ojal将圆形邻域替代正方形邻域。改进后的LBP允许半径为R的圆形邻域有任意多个特征点。从而得到诸如半径为R的圆形区域内含有P个采样点的LBP算子:

上图:

计算方法:

xt =xd + Rcos(2πp/P)

yt = yd  - Rsin(2πp/P)

其中(xt,yt)为某个采样点,(xd,yd)为邻域中心点,p为第p个采样点,P为采样点的个数。通过上式可以得到想要的采样点的坐标。另:得到的采样点的坐标未必完全为整数,改进后的LBP采用双线性插值得到该采样点的像素值:

几种不同半径不同采样点数量的LBP算子:

(二)旋转不变LBP特征:

上面已具备灰度不变性(即尺寸大小不变性),还不具备旋转不变性,研究人员在上面的基础上进行扩展,提出了具有旋转不变性的LBP特征。

首先,不断旋转圆形领域内的采样点的位置,得到一系列的LBP特征值,从这些LBP特征值中选择最小的作为LBP中心像素点的LBP特征值。做法如下:

如上图,进行旋转,最后得到LBP特征值为15.(旋转是改变采样点二进制位置)

(三)Uniform Pattern LBP特征:

Uniform Pattern LBP,也称为等价模式或均匀模式。对一个LBP特征,假设对于半径为R的圆形区域内含有P个采样点,则会产生2p二进制表达方法。随着邻域内采样点数目的增加,二进制模式的种类以指数形式增加,不利于纹理的提取、分类、识别及存取。为解决二进制模式过多的问题,Ojalar提出采用一种”等价模式“对LBP算子进行降维。在实际图像中,绝大多数LBP模式只包括从0到1或从1到0的转变。故Ojalar将”等价模式“定义为:当某个LBP所对应的二进制数从0到1或从1到0的转变最多有两次转变时,该LBP所对应的二进制就称为一个等价模式。如00000000(0次跳变)、00000111(1次跳变)、10001111(2次跳变)均为等价模式类。除等价模式类外的模式均归为混合模式类。通过这样,模式数量由原来的2p种减少为P(P-1)+2+1种(文章中大写P均代表采样点的数量)。

具体实现:

采样点数8个,即256个LBP特征值,分成59类:跳变0次——2个,跳变1次——0个,跳变2次——56个,跳变3次——0个,跳变4次——140个,跳变5次——0个,跳变6次——56个,跳变7次——0个,跳变8次——2个。

(四)MB-LBP特征:

MB-LBP特征,全称为Multiscale Block LBP,中科院的人发明,原理和HOG特征提取有相似之处。下面是原理介绍:

首先将图像分成一个个小块,再将每个小块分成一个个小的区域,小区域内的灰度值的平均值即为当前小区域的灰度值,与周围小区域灰度进行比较形成LBP特征,生成的LBP特征成为MB-LBP:如图:

同时,作者对得到的MB-LBP特征值进行均值模式编码,通过对得到的特征图求直方图,得到了LBP特征值0-255之间(0-255即直方图中的bin)的特征数量,通过对bin中的数值进行排序,通过权衡,将排序在前63位的特征值看作是等价模式类,其他的为混合模式类,总共64类,作者在论文中称之为SEMB-LBP(Statistically Effective MB-LBP )。(在此介绍一下直方图方法,首先得到的LBP特征值的二进制最多256种,而后对整个图像的LBP特征值的二进制统计、排序,前63位即为等价模式,后面均为混合模式类)。类似于等价模式LBP,等价模式的LBP的等价模式类为58种,混合模式类1种,共59种。二者除了等价模式类的数量不同之外,主要区别在于:对等价模式类的定义不同,等价模式LBP是根据0-1的跳变次数定义的,而SEMB-LBP是通过对直方图排序得到的。

ThirdBleed:

LBPH——图像的LBP特征向量:

LBPH,Local Binary Patterns Histograms,即LBP特征的统计直方图,LBPH将LBP特征与图像的空间信息结合在一起。这种表示方法由Ahonen等人在论文[3]中提出,他们将LBP特征图像分成m个局部块,并提取每个局部块的直方图,然后将这些直方图依次连接在一起形成LBP特征的统计直方图,即LBPH。

一幅图像具体的计算LBPH的过程(以Opencv中的人脸识别为例):

1. 计算图像的LBP特征图像,已经介绍。

2. 将LBP特征图像进行分块,Opencv中默认将LBP特征图像分成8行8列64块区域

3. 计算每块区域特征图像的直方图cell_LBPH,将直方图进行归一化,直方图大小为1*numPatterns

4. 将上面计算的每块区域特征图像的直方图按分块的空间顺序依次排列成一行,形成LBP特征向量,大小为1*(numPatterns*64)

5. 用机器学习的方法对LBP特征向量进行训练,用来检测和识别目标

举例说明LBPH的维度:

采样点为8个,如果用的是原始的LBP或Extended LBP特征,其LBP特征值的模式为256种,则一幅图像的LBP特征向量维度为:64*256=16384维,

而如果使用的UniformPatternLBP特征,其LBP值的模式为59种,其特征向量维度为:64*59=3776维,可以看出,使用等价模式特征,其特征向量的维度大大减少,

这意味着使用机器学习方法进行学习的时间将大大减少,而性能上没有受到很大影响。

下面,进入一篇一次的源代码和实战环节,上代码:

实战环节:

目前,Opencv内,暂无LBP简便的接口函数,如若使用,可复制上面代码,或下面例子。

LBP在人脸识别部分的应用:

#include#include#include#include#include

using namespacestd;using namespacecv;int main(int argc,char*argv[])

{

vectorimages;

vectorlabels;char buff[10];for(int i=1;i<8;i++)

{

sprintf(buff,"0%d.tif",i);

Mat image=imread(buff);

Mat grayImage;

cvtColor(image,grayImage,COLOR_BGR2GRAY);

images.push_back(grayImage);

labels.push_back(1);

}for(int i=8;i<12;i++)

{

sprintf(buff,"0%d.tif",i);

Mat image=imread(buff);

Mat grayImage;

cvtColor(image,grayImage,COLOR_BGR2GRAY);

images.push_back(grayImage);

labels.push_back(2);

}

Ptr p =createLBPHFaceRecognizer();

p->train(images,labels);

Mat test= imread("12.tif");

Mat grayImage;

cvtColor(test,grayImage,COLOR_BGR2GRAY);int result = p->predict(grayImage);

cout<

system("pause");return 0;

}

原始LBP特征计算代码:

template

voidgetOriginLBPFeature(InputArray _src,OutputArray _dst)

{

Mat src=_src.getMat();

_dst.create(src.rows-2,src.cols-2,CV_8UC1);

Mat dst=_dst.getMat();

dst.setTo(0);for(int i=1;i

{for(int j=1;j

{

_tp center= src.at<_tp>(i,j);

unsignedchar lbpCode = 0;

lbpCode|= (src.at<_tp>(i-1,j-1) > center) << 7;

lbpCode|= (src.at<_tp>(i-1,j ) > center) << 6;

lbpCode|= (src.at<_tp>(i-1,j+1) > center) << 5;

lbpCode|= (src.at<_tp>(i ,j+1) > center) << 4;

lbpCode|= (src.at<_tp>(i+1,j+1) > center) << 3;

lbpCode|= (src.at<_tp>(i+1,j ) > center) << 2;

lbpCode|= (src.at<_tp>(i+1,j-1) > center) << 1;

lbpCode|= (src.at<_tp>(i ,j-1) > center) << 0;

dst.at(i-1,j-1) =lbpCode;

}

}

}

圆形LBP特征计算:

template

void getCircularLBPFeature(InputArray _src,OutputArray _dst,int radius,intneighbors)

{

Mat src=_src.getMat();//LBP特征图像的行数和列数的计算要准确

_dst.create(src.rows-2*radius,src.cols-2*radius,CV_8UC1);

Mat dst=_dst.getMat();

dst.setTo(0);//循环处理每个像素

for(int i=radius;i

{for(int j=radius;j

{//获得中心像素点的灰度值

_tp center = src.at<_tp>(i,j);

unsignedchar lbpCode = 0;for(int k=0;k

{//根据公式计算第k个采样点的坐标,这个地方可以优化,不必每次都进行计算radius*cos,radius*sin

float x = i + static_cast(radius * cos(2.0 * CV_PI * k /neighbors));float y = j - static_cast(radius * sin(2.0 * CV_PI * k /neighbors));//根据取整结果进行双线性插值,得到第k个采样点的灰度值//1.分别对x,y进行上下取整

int x1 = static_cast(floor(x));int x2 = static_cast(ceil(x));int y1 = static_cast(floor(y));int y2 = static_cast(ceil(y));//2.计算四个点(x1,y1),(x1,y2),(x2,y1),(x2,y2)的权重//下面的权重计算方式有个问题,如果四个点都相等,则权重全为0,计算出来的插值为0//float w1 = (x2-x)*(y2-y);//(x1,y1)//float w2 = (x2-x)*(y-y1);//(x1,y2)//float w3 = (x-x1)*(y2-y);//(x2,y1)//float w4 = (x-x1)*(y-y1);//(x2,y2)//将坐标映射到0-1之间

float tx = x -x1;float ty = y -y1;//根据0-1之间的x,y的权重计算公式计算权重

float w1 = (1-tx) * (1-ty);float w2 = tx * (1-ty);float w3 = (1-tx) *ty;float w4 = tx *ty;//3.根据双线性插值公式计算第k个采样点的灰度值

float neighbor = src.at<_tp>(x1,y1) * w1 + src.at<_tp>(x1,y2) *w2 + src.at<_tp>(x2,y1) * w3 +src.at<_tp>(x2,y2) *w4;//通过比较获得LBP值,并按顺序排列起来

lbpCode |= (neighbor>center) <

}

dst.at(i-radius,j-radius) =lbpCode;

}

}

}//圆形LBP特征计算,效率优化版本,声明时默认neighbors=8

template

void getCircularLBPFeatureOptimization(InputArray _src,OutputArray _dst,int radius,intneighbors)

{

Mat src=_src.getMat();//LBP特征图像的行数和列数的计算要准确

_dst.create(src.rows-2*radius,src.cols-2*radius,CV_8UC1);

Mat dst=_dst.getMat();

dst.setTo(0);for(int k=0;k

{//计算采样点对于中心点坐标的偏移量rx,ry

float rx = static_cast(radius * cos(2.0 * CV_PI * k /neighbors));float ry = -static_cast(radius * sin(2.0 * CV_PI * k /neighbors));//为双线性插值做准备//对采样点偏移量分别进行上下取整

int x1 = static_cast(floor(rx));int x2 = static_cast(ceil(rx));int y1 = static_cast(floor(ry));int y2 = static_cast(ceil(ry));//将坐标偏移量映射到0-1之间

float tx = rx -x1;float ty = ry -y1;//根据0-1之间的x,y的权重计算公式计算权重,权重与坐标具体位置无关,与坐标间的差值有关

float w1 = (1-tx) * (1-ty);float w2 = tx * (1-ty);float w3 = (1-tx) *ty;float w4 = tx *ty;//循环处理每个像素

for(int i=radius;i

{for(int j=radius;j

{//获得中心像素点的灰度值

_tp center = src.at<_tp>(i,j);//根据双线性插值公式计算第k个采样点的灰度值

float neighbor = src.at<_tp>(i+x1,j+y1) * w1 + src.at<_tp>(i+x1,j+y2) *w2 + src.at<_tp>(i+x2,j+y1) * w3 +src.at<_tp>(i+x2,j+y2) *w4;//LBP特征图像的每个邻居的LBP值累加,累加通过与操作完成,对应的LBP值通过移位取得

dst.at(i-radius,j-radius) |= (neighbor>center) <

}

}

}

}

旋转不变圆形LBP特征计算:

template

void getRotationInvariantLBPFeature(InputArray _src,OutputArray _dst,int radius,intneighbors)

{

Mat src=_src.getMat();//LBP特征图像的行数和列数的计算要准确

_dst.create(src.rows-2*radius,src.cols-2*radius,CV_8UC1);

Mat dst=_dst.getMat();

dst.setTo(0);for(int k=0;k

{//计算采样点对于中心点坐标的偏移量rx,ry

float rx = static_cast(radius * cos(2.0 * CV_PI * k /neighbors));float ry = -static_cast(radius * sin(2.0 * CV_PI * k /neighbors));//为双线性插值做准备//对采样点偏移量分别进行上下取整

int x1 = static_cast(floor(rx));int x2 = static_cast(ceil(rx));int y1 = static_cast(floor(ry));int y2 = static_cast(ceil(ry));//将坐标偏移量映射到0-1之间

float tx = rx -x1;float ty = ry -y1;//根据0-1之间的x,y的权重计算公式计算权重,权重与坐标具体位置无关,与坐标间的差值有关

float w1 = (1-tx) * (1-ty);float w2 = tx * (1-ty);float w3 = (1-tx) *ty;float w4 = tx *ty;//循环处理每个像素

for(int i=radius;i

{for(int j=radius;j

{//获得中心像素点的灰度值

_tp center = src.at<_tp>(i,j);//根据双线性插值公式计算第k个采样点的灰度值

float neighbor = src.at<_tp>(i+x1,j+y1) * w1 + src.at<_tp>(i+x1,j+y2) *w2 + src.at<_tp>(i+x2,j+y1) * w3 +src.at<_tp>(i+x2,j+y2) *w4;//LBP特征图像的每个邻居的LBP值累加,累加通过与操作完成,对应的LBP值通过移位取得

dst.at(i-radius,j-radius) |= (neighbor>center) <

}

}

}//进行旋转不变处理

for(int i=0;i

{for(int j=0;j

{

unsignedchar currentValue = dst.at(i,j);

unsignedchar minValue =currentValue;for(int k=1;k

{//循环左移

unsigned char temp = (currentValue>>(neighbors-k)) | (currentValue<

{

minValue=temp;

}

}

dst.at(i,j) =minValue;

}

}

}

均匀(等价)模式:

template

void getUniformPatternLBPFeature(InputArray _src,OutputArray _dst,int radius,intneighbors)

{

Mat src=_src.getMat();//LBP特征图像的行数和列数的计算要准确

_dst.create(src.rows-2*radius,src.cols-2*radius,CV_8UC1);

Mat dst=_dst.getMat();

dst.setTo(0);//LBP特征值对应图像灰度编码表,直接默认采样点为8位

uchar temp = 1;

uchar table[256] = {0};for(int i=0;i<256;i++)

{if(getHopTimes(i)<3)

{

table[i]=temp;

temp++;

}

}//是否进行UniformPattern编码的标志

bool flag = false;//计算LBP特征图

for(int k=0;k

{if(k==neighbors-1)

{

flag= true;

}//计算采样点对于中心点坐标的偏移量rx,ry

float rx = static_cast(radius * cos(2.0 * CV_PI * k /neighbors));float ry = -static_cast(radius * sin(2.0 * CV_PI * k /neighbors));//为双线性插值做准备//对采样点偏移量分别进行上下取整

int x1 = static_cast(floor(rx));int x2 = static_cast(ceil(rx));int y1 = static_cast(floor(ry));int y2 = static_cast(ceil(ry));//将坐标偏移量映射到0-1之间

float tx = rx -x1;float ty = ry -y1;//根据0-1之间的x,y的权重计算公式计算权重,权重与坐标具体位置无关,与坐标间的差值有关

float w1 = (1-tx) * (1-ty);float w2 = tx * (1-ty);float w3 = (1-tx) *ty;float w4 = tx *ty;//循环处理每个像素

for(int i=radius;i

{for(int j=radius;j

{//获得中心像素点的灰度值

_tp center = src.at<_tp>(i,j);//根据双线性插值公式计算第k个采样点的灰度值

float neighbor = src.at<_tp>(i+x1,j+y1) * w1 + src.at<_tp>(i+x1,j+y2) *w2 + src.at<_tp>(i+x2,j+y1) * w3 +src.at<_tp>(i+x2,j+y2) *w4;//LBP特征图像的每个邻居的LBP值累加,累加通过与操作完成,对应的LBP值通过移位取得

dst.at(i-radius,j-radius) |= (neighbor>center) <

if(flag)

{

dst.at(i-radius,j-radius) = table[dst.at(i-radius,j-radius)];

}

}

}

}

}//计算跳变次数

int getHopTimes(intn)

{int count = 0;

bitset<8> binaryCode =n;for(int i=0;i<8;i++)

{if(binaryCode[i] != binaryCode[(i+1)%8])

{

count++;

}

}returncount;

}

MB-LBP代码:

//MB-LBP特征的计算

void getMultiScaleBlockLBPFeature(InputArray _src,OutputArray _dst,intscale)

{

Mat src=_src.getMat();

Mat dst=_dst.getMat();//定义并计算积分图像

int cellSize = scale / 3;int offset = cellSize / 2;

Mat cellImage(src.rows-2*offset,src.cols-2*offset,CV_8UC1);for(int i=offset;i

{for(int j=offset;j

{int temp = 0;for(int m=-offset;m

{for(int n=-offset;n

{

temp+= src.at(i+n,j+m);

}

}

temp/= (cellSize*cellSize);

cellImage.at(i-cellSize/2,j-cellSize/2) =uchar(temp);

}

}

getOriginLBPFeature(cellImage,dst);

}

MB-LBP编码的计算:

//求SEMB-LBP

void SEMB_LBPFeature(InputArray _src,OutputArray _dst,intscale)

{

Mat dst=_dst.getMat();

Mat MB_LBPImage;

getMultiScaleBlockLBPFeature(_src,MB_LBPImage,scale);//imshow("dst",dst);

Mat histMat;int histSize = 256;float range[] = {float(0),float(255)};const float* ranges ={range};//计算LBP特征值0-255的直方图

calcHist(&MB_LBPImage,1,0,Mat(),histMat,1,&histSize,&ranges,true,false);

histMat.reshape(1,1);

vector histVector(histMat.rows*histMat.cols);

uchar table[256];

memset(table,64,256);if(histMat.isContinuous())

{//histVector = (int *)(histMat.data);//将直方图histMat变为vector向量histVector

histVector.assign((float*)histMat.datastart,(float*)histMat.dataend);

vectorhistVectorCopy(histVector);//对histVector进行排序,即对LBP特征值的数量进行排序,降序排列

sort(histVector.begin(),histVector.end(),greater());for(int i=0;i<63;i++)

{for(int j=0;j

{if(histVectorCopy[j]==histVector[i])

{//得到类似于Uniform的编码表

table[j]=i;

}

}

}

}

dst=MB_LBPImage;//根据编码表得到SEMB-LBP

for(int i=0;i

{for(int j=0;j

{

dst.at(i,j) = table[dst.at(i,j)];

}

}

}

LBPH特征图像的计算:

//计算LBP特征图像的直方图LBPH

Mat getLBPH(InputArray _src,int numPatterns,int grid_x,int grid_y,boolnormed)

{

Mat src=_src.getMat();int width = src.cols /grid_x;int height = src.rows /grid_y;//定义LBPH的行和列,grid_x*grid_y表示将图像分割成这么些块,numPatterns表示LBP值的模式种类

Mat result = Mat::zeros(grid_x *grid_y,numPatterns,CV_32FC1);if(src.empty())

{return result.reshape(1,1);

}int resultRowIndex = 0;//对图像进行分割,分割成grid_x*grid_y块,grid_x,grid_y默认为8

for(int i=0;i

{for(int j=0;j

{//图像分块

Mat src_cell = Mat(src,Range(i*height,(i+1)*height),Range(j*width,(j+1)*width));//计算直方图

Mat hist_cell = getLocalRegionLBPH(src_cell,0,(numPattern-1),true);//将直方图放到result中

Mat rowResult =result.row(resultRowIndex);

hist_cell.reshape(1,1).convertTo(rowResult,CV_32FC1);

resultRowIndex++;

}

}return result.reshape(1,1);

}//计算一个LBP特征图像块的直方图

Mat getLocalRegionLBPH(const Mat& src,int minValue,int maxValue,boolnormed)

{//定义存储直方图的矩阵

Mat result;//计算得到直方图bin的数目,直方图数组的大小

int histSize = maxValue - minValue + 1;//定义直方图每一维的bin的变化范围

float range[] = { static_cast(minValue),static_cast(maxValue + 1) };//定义直方图所有bin的变化范围

const float* ranges ={ range };//计算直方图,src是要计算直方图的图像,1是要计算直方图的图像数目,0是计算直方图所用的图像的通道序号,从0索引//Mat()是要用的掩模,result为输出的直方图,1为输出的直方图的维度,histSize直方图在每一维的变化范围//ranges,所有直方图的变化范围(起点和终点)

calcHist(&src,1,0,Mat(),result,1,&histSize,&ranges,true,false);//归一化

if(normed)

{

result/= (int)src.total();

}//结果表示成只有1行的矩阵

return result.reshape(1,1);

}

提取lbp特征java代码_LBP特征提取原理及代码实现相关推荐

  1. 提取lbp特征java代码_目标检测的图像特征提取之_LBP特征

    LBP(Local Binary Pattern,局部二值模式)是一种用来描述图像局部纹理特征的算子:它具有旋转不变性和灰度不变性等显著的优点.它是首先由T. Ojala, M.Pietikäinen ...

  2. 提取lbp特征java代码_LBP特征提取实现

    捯饬了一两天才搞好! 在lbp.m下输入下面代码,运行结果如图: 代码: I=imread('rice.png'); mapping=getmapping(8,'u2'); H1=lbp(I,1,8, ...

  3. 提取lbp特征java代码_特征提取算法之LBP

    图像特征,图像纹理,图像频域等多种角度提取图像的特征. LBP,局部二值模式,局部特征描述算子,具有很强的纹理特征描述能力,具有光照不变性和旋转不变性.用python进行简单的LBP算法实验: 1 f ...

  4. 用matlab提取lbp特征,求教大神给解释一下LBP特征提取每部分程序是干什么的

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 function X1 = LBP(Resimage) % Returns a rotation invariant LBP (uniform patte ...

  5. HRNet提取骨架特征点+ ST-GCN训练自己的数据集代码实践问题记录

    软硬件环境: python 3.6.5 Ubuntu 18.04 LTS Pytorch 1.1.0 NVIDIA TITAN XP 8GB 项目链接https://github.com/open-m ...

  6. java sendmessage_SendMessage、PostMessage原理和源代码详解

    本文讲解SendMessage.PostMessage两个函数的实现原理,分为三个步骤进行讲解,分别适合初级.中级.高级程序员进行理解,三个步骤分别为: 1.SendMessage.PostMessa ...

  7. 风控ML[13] | 特征稳定性指标PSI的原理与代码分享

    PSI这个指标我们在风控建模前后都是需要密切关注的,这个指标直接反映了模型的稳定性,对于我们评估模型是否需要迭代有着直接的参考意义.今天我将从下面几方面来介绍一下这个指标. Index 01 PSI的 ...

  8. Java方法重载实现原理及代码实例

    方法的重载 重载就是在一个类中,有相同的函数名称,但形参不同的函数 方法重载的规则: 方法名称必须相同 参数列表必须不同(个数不同,类型不同,参数排列顺序不同) 方法的返回值类型可以相同也可以不相同 ...

  9. knn算法python代码_KNN 算法原理及代码实现

    在本文中,我们将讨论一种广泛使用的分类技术,称为K最近邻(KNN).我们的重点主要集中在算法如何工作以及输入参数如何影响预测结果. 内容包括: 何时使用KNN算法? KNN算法原理 如何选择K值 KN ...

最新文章

  1. 将txt文件和excel文件导入SQL2000数据库
  2. Redis基本使用及百亿数据量中的使用技巧分享
  3. linux开启ping服务,Linux 云服务器禁止和开启Ping
  4. win7系统的CMD窗口切换目录--小计
  5. 解析ip数据包java_ip包,ip数据包,数据包或者包的理解
  6. JAVA 设计模式 装饰者模式
  7. 尼日利亚4g频段_4G全球频段划分及主要运营商对应表2015版
  8. SSIM公式:结构相似性计算原理,基于SSIM的图像质量评价
  9. 学习RPA-电商自动化入门①
  10. 中国拖车洒水器市场趋势报告、技术动态创新及市场预测
  11. 2018-2019的裁员风波(程序员要有危机意识,程序员堪比娱乐圈,更新换代快)
  12. Zookeeper分布式锁解决羊群效应的方案
  13. ABP AOP 用例
  14. C/C++ : 12-24小时制转换
  15. Linux基础命令(补充:命令行提示字符加颜色)
  16. Windows nginx 操作和配置
  17. php漏洞防范措施,php漏洞php后门浅析以及防范措施
  18. 「THUWC 2017」在美妙的数学王国中畅游
  19. 随机信号处理笔记之色噪声及白化滤波器
  20. 计算机主板风扇安装,cpu风扇怎么装 cpu风扇安装方法【图文】

热门文章

  1. Newtonsoft.Json序列化库
  2. Google“谷歌”引发的王怀南血案
  3. 规则网络上的演化博弈
  4. DOS命令----百度百科
  5. ARM 官方文档下载地址
  6. Tableua数据大屏——餐饮门店每日业务情况总览
  7. 大数据技术原理与应用(第八章 Hadoop再探讨)
  8. 罗技驱动调节灵敏度方法介绍
  9. 国际项目投标那些事(三)海外项目招标文件的组成
  10. 数据库查询语言的进化(下)