一.所需结构体

CvHistogram

结构体原型:

typedef struct CvHistogram {int type;        /* 直方图类型 */CvArr* bins;  /* 直方图数据 */    float thresh[CV-MAX-DIM][2]; /* 每一维的直方块边界数组 */float** thresh2; /* 非均匀直方图 */
CvMatND mat;            /* 阵列柱状图的嵌入式矩阵头*/
} CvHistogram;

二.所需函数

1.cvCalcHist:

函数功能:用于计算图像直方图

函数原型:

void  cvCalcHist( IplImage** image, CvHistogram* hist,int accumulate = 0,const CvArr* mask = NULL );

参数介绍:

IplImage** image:              要计算直方图的图像指针,如果要累加直方图输入图像颜色深度必须一致CvHistogram* hist:          输出参数,计算出来的直方图。int accumulate:            表示是否对传入的 hist 清零。不清零的话可以将多幅图像的直方图累加,0代表清零,非0代表不清零!const CvArr* mask:       掩码,如果mask不为空,那么它必须是一个8位(CV_8U)的数组,并且它的大小的和输入的图像的大小相同,值非 0 的点将用来计算直方图。

返回值:无

2.CvCreateHist:

函数功能:用于创建直方图

函数原型:

CvHistogram*  cvCreateHist( int dims, int* sizes, int type,float** ranges = NULL,int uniform = 1);

参数介绍:

int dims:        表示图像是几维空间,即一般彩色图像是3通道的,dim=3;而灰度图是1通道的,dim=1,如果带有透明度的图像即RGBA则dim=4
int* sizes:     //直方图维数尺寸,size数组的长度为dims,每个数表示分配给对应维数的bin的个数。如dims=3,则size中用[s1,s2,s3]分别指定每维bin的个数。
int type:           直方图的表示格式: CV_HIST_ARRAY 意味着直方图数据表示为多维密集数组, CV_HIST_TREE 意味着直方图数据表示为多维稀疏数组
float** ranges:        表示方块范围,假设该值设置为0-255意思就是说将像素点压缩到0-255个元素之间(压缩方法是叠加,列如像素点有1024个那么会将1024个像素点的每个值相加在一块放到size组中,比如将10个像素点的值叠加在一块,然后放到对应的size组中!),并将这0-255个元素分别分布到对应的size中!
int uniform:        归一化标识,如果不为0,bin均匀处理ranges的取值范围,为0,根据ranges的设置非均匀处理对应范围的直方块

返回值:成功返回一个指向堆中CvHistogram结构体的CvHistogram指针

3.cvGetMinMaxHistValue:

函数功能:用于统计直方图中最小值和最大值

函数原型:

void cvGetMinMaxHistValue( const CvHistogram* hist, float* min_value, float* max_value,int* min_idx = NULL,int* max_idx = NULL);

参数介绍:

const CvHistogram* hist:         要统计的直方图
float* min_value:           直方图最小值的指针
float* max_value:           直方图最大值的指针
int* min_idx:               数组中最小坐标的指针
int* max_idx:               数组中最大坐标的指针 

返回值:无

4.cvConvertScale

函数功能:按比例缩放bin

函数原型:

void  cvConvertScale( const CvArr* src, CvArr* dst,double scale = 1,double shift = 0);

参数介绍:

const CvArr* src:      输入数组
CvArr* dst:       输出数组
double scale:         比例因子
double shift:         该加数与输入元素相加并按比例缩放到输出数组的元素上

返回值:无

5.cvReleaseHist

函数功能:释放直方图

函数原型:

void cvReleaseHist( CvHistogram**hist); 

参数介绍:

CvHistogram**hist :  直方图指针

返回值:无

二. 编写绘制灰度图像的直方图代码

准备工作已经完成,下面开始正式代码编写

2.1 准备工作

准备一张用于测试的图像文件,图像文件格式任意!

这里我的是jpg格式的图像文件

如需要可自行保存到本地

2.2 编写代码,加载测试图到内存

//打开测试图
IplImage * image = cvLoadImage("D:\\test.jpg",0);            //将本地测试图导入到程序堆中
if (image == NULL){                                       //判断是否打开成功printf("错误:无法打开该图像,图像文件路径不正确!");return -1;}

2.2 创建一个直方图

//创建一个直方图
int arr_size = 255;                    //定义一个变量用于表示直方图行宽
float hranges_arr[] = { 0, 255 };      //图像方块范围数组
float *phranges_arr = hranges_arr;     //cvCreateHist参数是一个二级指针,所以要用指针指向数组然后传参
CvHistogram *hist = cvCreateHist(1, &arr_size, CV_HIST_ARRAY, &phranges_arr, 1);   //创建一个一维的直方图,行宽为255,多维密集数组,方块范围为0-255,bin均化

2.3 创建一个空白图像用来绘制直方图

//创建一个空白图像用于绘制直方图
IplImage *histimg = cvCreateImage(cvSize(320, 200), 8, 3);
cvZero(histimg);    //清空histimag-imagedata数据

2.4 计算图像直方图

//计算图像直方图大小
cvCalcHist(&image, hist, 0, 0);     

2.5 缩放直方图尺寸

//直方图根据size分组然后根据ranges取值范围来统计图像像素点范围,也就是说ranges为0-255则将图像中像素值叠加在一起(叠加成MIN:0、MIX:255)组并分组到对应的size维中,所以size维里的每个元素非常大,所以要按比例缩小
float max_val;  //用于存储获取到的最大值cvGetMinMaxHistValue(hist, 0, &max_val, 0, 0); //获取直方图最大值
cvConvertScale(hist->bins,hist->bins, max_val ? 255. / max_val : 0., 0);  //按比例缩小直方图

2.6 绘制直方图

//开始绘制直方图
int bin_w;
bin_w = histimg->width / arr_size; //得到开始绘制点位置for (int i = 0; i < arr_size; i++){double val = (cvGetReal1D(hist->bins, i)*histimg->height / 255);//获取矩阵元素值,并转换为对应高度CvScalar color = CV_RGB(255, 255, 0);                                               cvRectangle(histimg, cvPoint(i*bin_w, histimg->height),cvPoint((i + 1)*bin_w, (int)(histimg->height - val)),color, 1, 8, 0);}

2.7 将直方图显示出来

//显示结果
cvShowImage("1", image);      //原图
cvShowImage("2", histimg);        //绘制出来的直方图
cvWaitKey(0);                   //消息循环

运行结果:

完整代码:

//打开测试图IplImage * image = cvLoadImage("D:\\3.jpg", 0);            //将本地测试图导入到程序堆中if (image == NULL){                                        //判断是否打开成功printf("错误:无法打开该图像,图像文件路径不正确!");return -1;}//创建一个直方图int arr_size = 255;                   //定义一个变量用于表示直方图行宽float hranges_arr[] = { 0, 255 };     //图像方块范围数组float *phranges_arr = hranges_arr;       //cvCreateHist参数是一个二级指针,所以要用指针指向数组然后传参CvHistogram *hist = cvCreateHist(1, &arr_size, CV_HIST_ARRAY, &phranges_arr, 1);  //创建一个一维的直方图,行宽为255,多维密集数组,方块范围为0-255,bin均化//创建一个空白图像用于绘制直方图IplImage *histimg = cvCreateImage(cvSize(320, 200), 8, 3);cvZero(histimg);//清空histimag-imagedata数据//计算图像直方图大小cvCalcHist(&image, hist, 0, 0);//直方图根据size分组然后根据ranges取值范围来统计图像像素点范围,也就是说ranges为0-255则将图像中像素值叠加在一起(叠加成MIN:0、MIX:255)组并分组到对应的size维中,所以size维里的每个元素非常大,所以要按比例缩小float max_val; //用于存储获取到的最大值cvGetMinMaxHistValue(hist, 0, &max_val, 0, 0);     //获取直方图最大值cvConvertScale(hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0);   //按比例缩小直方图//开始绘制直方图int bin_w; bin_w = histimg->width / arr_size;//得到开始绘制点位置for (int i = 0; i < arr_size; i++){double val = (cvGetReal1D(hist->bins, i)*histimg->height / 255); //获取矩阵元素值,并转换为对应高度CvScalar color = CV_RGB(255, 255, 0);                                                 cvRectangle(histimg, cvPoint(i*bin_w, histimg->height),cvPoint((i + 1)*bin_w, (int)(histimg->height - val)),color, 1, 8, 0);}//显示结果cvShowImage("1", image);        //灰度原图cvShowImage("2", histimg);      //绘制出来的直方图cvWaitKey(0);                 //消息循环

三. 基于直方图颜色数据的对比

1. 所需函数

1.1cvCompareHist

函数功能:用于对比直方图bins数据,并将对比结果以double类型返回

函数原型:

double  cvCompareHist( const CvHistogram* hist1,const CvHistogram* hist2,int method);

参数介绍:

const CvHistogram* hist1:    模板图
const CvHistogram* hist2:   要对比的图片
int method            : 对比方法可取宏:
#define CV_COMP_CORREL 0    //值越大匹配度越高
#define CV_COMP_CHISQR 1    //值越小匹配度越高
#define CV_COMP_INTERSECT 2 //(归一化)值越大匹配度越高
#define CV_COMP_BHATTACHARYYA 3 //(归一化)值越小匹配度越高

返回值:根据method参数的值返回不同的匹配值!

2. 准备两张图片

3.开始编写代码

3.1 将比对图加载到内存

//加载比对图IplImage * image = cvLoadImage("D:\\1.jpg", 0);            //将本地模板图导入到程序堆中if (image == NULL){                                        //判断是否打开成功printf("错误:无法打开该图像,图像文件路径不正确!");return -1;}IplImage * image1 = cvLoadImage("D:\\2.jpg", 0);         //将本地对比图导入到程序堆中if (image1 == NULL){                                       //判断是否打开成功printf("错误:无法打开该图像,图像文件路径不正确!");return -1;}

3.2 创建两个直方图

//创建两个直方图用于存储模板和对比图的bin//创建模板直方图int arr_size = 255;                 //定义一个变量用于表示直方图行宽float hranges_arr[] = { 0, 255 };     //图像方块范围数组float *phranges_arr = hranges_arr;       //cvCreateHist参数是一个二级指针,所以要用指针指向数组然后传参//创建对比图的直方图CvHistogram *hist = cvCreateHist(1, &arr_size, CV_HIST_ARRAY, &phranges_arr, 1);//创建一个一维的直方图,行宽为255,多维密集数组,方块范围为0-255,bin均化int arr_size1 = 255;                   //定义一个变量用于表示直方图行宽float hranges_arr1[] = { 0, 255 };        //图像方块范围数组float *phranges_arr1 = hranges_arr1;     //cvCreateHist参数是一个二级指针,所以要用指针指向数组然后传参CvHistogram *hist1 = cvCreateHist(1, &arr_size1, CV_HIST_ARRAY, &phranges_arr1, 1);//创建一个一维的直方图,行宽为255,多维密集数组,方块范围为0-255,bin均化3.3 计算两张图像的直方图

3.3 计算直方图大小

//计算图像的直方图大小,并保存到hist与hist1结构体中
cvCalcHist(&image, hist, 0, 0);
cvCalcHist(&image1, hist1, 0, 0);

3.4 对比直方图

//将计算后图像直方图与对比图进行比较,并将比较结果保存到Copare变量中
double Compare = cvCompareHist(hist, hist1, 0);        //使用CV_COMP_CORREL方法进行对比

3.5 将图像与对比结果显示出来

//将图像与对比结果显示出来
//创建窗口
cvNamedWindow("image_mode",0);//模板窗口
cvNamedWindow("image1",0);//对比图像窗口
//显示图像
cvShowImage("image_mode", image);
cvShowImage("image1", image1);
//打印对比结果:
printf("对比结果为:%lf", Compare);
cvWaitKey(0);       //消息循环

运行结果:

可以看到相似度很高

完整代码:

//加载比对图IplImage * image = cvLoadImage("D:\\1.jpg", 0);            //将本地模板图导入到程序堆中if (image == NULL){                                        //判断是否打开成功printf("错误:无法打开该图像,图像文件路径不正确!");return -1;}IplImage * image1 = cvLoadImage("D:\\2.jpg", 0);         //将本地对比图导入到程序堆中if (image1 == NULL){                                       //判断是否打开成功printf("错误:无法打开该图像,图像文件路径不正确!");return -1;}
//创建两个直方图用于存储模板和对比图的bin//创建模板直方图int arr_size = 255;                    //定义一个变量用于表示直方图行宽float hranges_arr[] = { 0, 255 };     //图像方块范围数组float *phranges_arr = hranges_arr;       //cvCreateHist参数是一个二级指针,所以要用指针指向数组然后传参//创建对比图的直方图CvHistogram *hist = cvCreateHist(1, &arr_size, CV_HIST_ARRAY, &phranges_arr, 1);//创建一个一维的直方图,行宽为255,多维密集数组,方块范围为0-255,bin均化int arr_size1 = 255;                   //定义一个变量用于表示直方图行宽float hranges_arr1[] = { 0, 255 };        //图像方块范围数组float *phranges_arr1 = hranges_arr1;     //cvCreateHist参数是一个二级指针,所以要用指针指向数组然后传参CvHistogram *hist1 = cvCreateHist(1, &arr_size1, CV_HIST_ARRAY, &phranges_arr1, 1);//创建一个一维的直方图,行宽为255,多维密集数组,方块范围为0-255,bin均化3.3 计算两张图像的直方图
//计算图像的直方图大小,并保存到hist与hist1结构体中
cvCalcHist(&image, hist, 0, 0);
cvCalcHist(&image1, hist1, 0, 0);
//将计算后图像直方图与对比图进行比较,并将比较结果保存到Copare变量中
double Compare = cvCompareHist(hist, hist1, 0);        //使用CV_COMP_CORREL方法进行对比
//将图像与对比结果显示出来
//创建窗口
cvNamedWindow("image_mode",0);//模板窗口
cvNamedWindow("image1",0);//对比图像窗口
//显示图像
cvShowImage("image_mode", image);
cvShowImage("image1", image1);
//打印对比结果:
printf("对比结果为:%lf", Compare);
cvWaitKey(0);       //消息循环

试试看,修改以上代码,打印结果时将直方图也一并绘制出来

在cvWaitKey代码前加入如下代码:

//直方图根据size分组然后根据ranges取值范围来统计图像像素点范围,也就是说ranges为0-255则将图像中像素值叠加在一起(叠加成MIN:0、MIX:255)组并分组到对应的size维中,所以size维里的每个元素非常大,所以要按比例缩小
//缩小模板直方图bin
float max_val;  //用于存储获取到的最大值
cvGetMinMaxHistValue(hist, 0, &max_val, 0, 0);      //获取直方图最大值
cvConvertScale(hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0); //按比例缩小直方图
//缩小对比直方图bin
float max_val1; //用于存储获取到的最大值
cvGetMinMaxHistValue(hist1, 0, &max_val1, 0, 0);        //获取直方图最大值
cvConvertScale(hist1->bins, hist1->bins, max_val1 ? 255. / max_val1 : 0., 0); //按比例缩小
IplImage *histimg = cvCreateImage(cvSize(320, 200), 8, 3); //模板图的直方图
IplImage *histimg1 = cvCreateImage(cvSize(320, 200), 8, 3);    //对比图的直方图
//绘制模板直方图int bin_w; bin_w = histimg->width / arr_size;//得到开始绘制点位置for (int i = 0; i < arr_size; i++){double val = (cvGetReal1D(hist->bins, i)*histimg->height / 255); //获取矩阵元素值,并转换为对应高度CvScalar color = CV_RGB(255, 255, 0);                                               cvRectangle(histimg, cvPoint(i*bin_w, histimg->height),cvPoint((i + 1)*bin_w, (int)(histimg->height - val)),color, 1, 8, 0);}//绘制对比图直方图int bin_w1; bin_w1 = histimg1->width / arr_size1;//得到开始绘制点位置for (int i = 0; i < arr_size1; i++){double val = (cvGetReal1D(hist1->bins, i)*histimg1->height / 255); //获取矩阵元素值,并转换为对应高度CvScalar color = CV_RGB(255, 255, 0);                                               cvRectangle(histimg1, cvPoint(i*bin_w1, histimg1->height),cvPoint((i + 1)*bin_w1, (int)(histimg1->height - val)),color, 1, 8, 0);}
//将直方图显示出来
cvShowImage("1", histimg);    //显示模板直方图
cvShowImage("2", histimg1);//显示对比直方图

运行结果:

修改后的完整代码:

//加载比对图IplImage * image = cvLoadImage("D:\\1.jpg",0);         //将本地模板图导入到程序堆中if (image == NULL){                                        //判断是否打开成功printf("错误:无法打开该图像,图像文件路径不正确!");return -1;}IplImage * image1 = cvLoadImage("D:\\2.jpg",0);          //将本地对比图导入到程序堆中if (image1 == NULL){                                       //判断是否打开成功printf("错误:无法打开该图像,图像文件路径不正确!");return -1;}//创建两个直方图用于存储模板和对比图的bin//创建模板直方图int arr_size = 255;                    //定义一个变量用于表示直方图行宽float hranges_arr[] = { 0, 255 };     //图像方块范围数组float *phranges_arr = hranges_arr;       //cvCreateHist参数是一个二级指针,所以要用指针指向数组然后传参//创建对比图的直方图CvHistogram *hist = cvCreateHist(1, &arr_size, CV_HIST_ARRAY, &phranges_arr, 3);//创建一个一维的直方图,行宽为255,多维密集数组,方块范围为0-255,bin均化int arr_size1 = 255;                   //定义一个变量用于表示直方图行宽float hranges_arr1[] = { 0, 255 };        //图像方块范围数组float *phranges_arr1 = hranges_arr1;     //cvCreateHist参数是一个二级指针,所以要用指针指向数组然后传参CvHistogram *hist1 = cvCreateHist(1, &arr_size1, CV_HIST_ARRAY, &phranges_arr1, 3);//创建一个一维的直方图,行宽为255,多维密集数组,方块范围为0-255,bin均化3.3 计算两张图像的直方图//计算图像的直方图大小,并保存到hist与hist1结构体中cvCalcHist(&image, hist, 0, 0);cvCalcHist(&image1, hist1, 0, 0);//将计算后图像直方图与对比图进行比较,并将比较结果保存到Copare变量中double Compare = cvCompareHist(hist, hist1, 0);     //使用CV_COMP_CORREL方法进行对比//将图像与对比结果显示出来//创建窗口cvNamedWindow("image_mode",0);cvNamedWindow("image1",0);//显示图像cvShowImage("image_mode", image);cvShowImage("image1", image1);//打印对比结果:printf("对比结果为:%lf", Compare);//直方图根据size分组然后根据ranges取值范围来统计图像像素点范围,也就是说ranges为0-255则将图像中像素值叠加在一起(叠加成MIN:0、MIX:255)组并分组到对应的size维中,所以size维里的每个元素非常大,所以要按比例缩小//缩小模板直方图binfloat max_val; //用于存储获取到的最大值cvGetMinMaxHistValue(hist, 0, &max_val, 0, 0);     //获取直方图最大值cvConvertScale(hist->bins, hist->bins, max_val ? 255. / max_val : 0., 0);   //按比例缩小直方图//缩小对比直方图binfloat max_val1;   //用于存储获取到的最大值cvGetMinMaxHistValue(hist1, 0, &max_val1, 0, 0);       //获取直方图最大值cvConvertScale(hist1->bins, hist1->bins, max_val1 ? 255. / max_val1 : 0., 0);   //按比例缩小IplImage *histimg = cvCreateImage(cvSize(320, 200), 8, 3);  //模板图的直方图IplImage *histimg1 = cvCreateImage(cvSize(320, 200), 8, 3);   //对比图的直方图//绘制模板直方图int bin_w;bin_w = histimg->width / arr_size;//得到开始绘制点位置for (int i = 0; i < arr_size; i++){double val = (cvGetReal1D(hist->bins, i)*histimg->height / 255); //获取矩阵元素值,并转换为对应高度CvScalar color = CV_RGB(255, 255, 0);                                               cvRectangle(histimg, cvPoint(i*bin_w, histimg->height),cvPoint((i + 1)*bin_w, (int)(histimg->height - val)),color, 1, 8, 0);}//绘制对比图直方图int bin_w1;bin_w1 = histimg1->width / arr_size1;//得到开始绘制点位置for (int i = 0; i < arr_size1; i++){double val = (cvGetReal1D(hist1->bins, i)*histimg1->height / 255); //获取矩阵元素值,并转换为对应高度CvScalar color = CV_RGB(255, 255, 0);                                                cvRectangle(histimg1, cvPoint(i*bin_w1, histimg1->height),cvPoint((i + 1)*bin_w1, (int)(histimg1->height - val)),color, 1, 8, 0);}cvShowImage("1", histimg);   //显示模板直方图
cvShowImage("2", histimg1);//显示对比直方图cvWaitKey(0);     //消息循环

使用Opencv绘制灰度直方图/对比相关推荐

  1. [Python图像处理] 三十七.OpenCV直方图统计两万字详解(掩膜直方图、灰度直方图对比、黑夜白天预测)

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

  2. opencv python matplotlib.pyplot.hist() 如何绘制灰度直方图,如何根据灰度直方图确定最优二值化值

    什么是灰度直方图? 图像直方图(histogram)是图像的统计学特征,常用于了解图像的基本特征以便分析.不过图像的直方图不具有空间特征. 图像的灰度直方图(histogram),就是将图像转化成灰度 ...

  3. [Python从零到壹] 五十一.图像增强及运算篇之图像灰度直方图对比分析万字详解

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  4. 【 OpenCV】——灰度直方图

    [ OpenCV]--灰度直方图 前言 本文介绍了灰度直方图的基础内容. 对函数参数的解释 void calcHist { const Mat*images,//输入的矩阵数组或数据集 int nim ...

  5. 【python图像处理】python绘制灰度直方图

    灰度直方图在数据统计分析.图像处理中有着比较广泛的应用,下面就介绍一下如何使用python来绘制灰度直方图. 下面直接看代码: import matplotlib.pyplot as plt impo ...

  6. python 灰度直方图_python3+opencv 使用灰度直方图来判断图片的亮暗操作

    1.如何让计算机自动判断一张图是否偏暗?或是判断一张图是否是处于夜晚?我们可以先把图片转换为灰度图,然后根据灰度值的分布来判断,如: 我们可以从上图看到,晚上的图片的灰度值是集中在前段的,如0~30多 ...

  7. python绘制灰度直方图_python+opencv 灰度直方图及其二值化

    图像直方图(histogram)是图像的统计学特征,常用于了解图像的基本特征以便分析.不过图像的直方图不具有空间特征. 图像的灰度直方图(histogram),就是将图像转化成灰度图像之后,统计各个像 ...

  8. C++OpenCV下绘制灰度直方图

    C++OpenCV下绘制直方图 直方图的定义:灰度直方图是对一幅灰度图像素分布的统计.对于一幅8Bit量化的图像来说.就是统计在0~255各个灰度级上,像素点的个数或者密度. 在OpenCV库提供了c ...

  9. 【数字图像处理】四.MFC对话框绘制灰度直方图

    本文主要讲述基于VC++6.0 MFC图像处理的应用知识,主要结合自己大三所学课程<数字图像处理>及课件进行回忆讲解,主要通过MFC单文档视图实现点击弹出对话框绘制BMP图片的灰度直方图, ...

最新文章

  1. 死猪脑”能复活吗?---评美国耶鲁大学医学院实验研究
  2. ajax java对象返回前台少了属性_AJAX常见提交数据的三种方式
  3. GIS坡度分析入门实例 - 使用SuperMap
  4. 数据库中char varchar nchar nvarchar的区别
  5. 【Redis学习笔记】2018-06-12 复制与传播
  6. CUDA学习(九十一)
  7. 有关PHP、HTML单引号、双引号转义以及转成HTML实体的那些事!
  8. Springboot遇到的问题
  9. java学完jdk后学什么_学完了javase之后要学什么?
  10. ffmpeg解码到opencv Mat中
  11. APT linux必知必会
  12. one list to muti list
  13. Java反射学习总结终(使用反射和注解模拟JUnit单元测试框架)
  14. 计算机机房需求调查表,机房建设需求调查表.doc
  15. redis php 使用实例
  16. mysql多个数据库查询_如何跨多个数据库查询
  17. uniapp点击复制文本
  18. Android文字转语音播报
  19. Spring Hibernate Validation
  20. python短信验证码登录_Python实现短信验证

热门文章

  1. vivado dds IP核笔记
  2. jdk下载安装并配置环境
  3. spring c3p0 mysql_spring boot整合mybatis使用c3p0数据源连接mysql
  4. activiti 解压zip java.lang.IllegalArgumentException: MALFORMED 错误
  5. 你真的理解a -- -- a a++ ++a 吗?
  6. 打印html文件都是空白页,我打印时的额外空白页面(IE中除外) – 是我的打印css吗?...
  7. java 内存分布_java的各类型数据在内存中分配情况详解_
  8. R语言作图之ggplot2作图2
  9. 这样找电子书,方法贴!
  10. python中0o10_Python中最常见的10个问题(列表)