写在前面的话

上一篇开篇博文写好之后找女朋友看了一下,希望她提一点建设性建议。结果她很委婉的告诉我,写的还行就是太表面了,告诉我要注意细节的描述与具体的实现过程与原理等等。其实我只是想骗她看一下增加一下点击量,顺便知道我写的博客新手能不能看懂而已。结果她告诉我,她那么聪明当然能看懂,别人就未必能看懂了!!!吼吼吼,信了她的邪,什么时候都不忘记赞美一下她自己的小妖精。上一篇写的不好的话请各位见谅,吾理小子文笔有点差,但是我会尽自己的最大努力把自己懂的东西分享出来,希望对你有用。为了讲述清楚车牌识别的每一个环节,吾理小子决定把写好的工程源码重新解剖,在每一个环节中贴出该部分完整的代码,新手可直接拿去运行观看实际效果。各位感动吗!

进入正题,上次重点介绍了车牌识别的流程,本文来详细聊一下车牌提取的实现过程。

车牌提取方法

车牌提取通常也称为车牌定位,其目的是从含有车牌的图像中找到车牌区域。车牌定位的重要性不言而喻,作为车牌识别的第一个步骤,车牌区域的提取成功与否是完成车牌识别的基础也是首要决定因素。车牌提取的方法有很多,不同的分类方法有不同的叫法。通过对常见的几种方法的归纳总结,见下图:(编辑一张图片,喷出一口鲜血)

本文着重讲解基于颜色信息的定位方法。上图中可以看到基于彩色信息的定位方法具有准确、快速、精确等优点,对于新手也更加容易理解。通过对质量较高的原始图像进行相应处理之后,定位出车牌区域。现象明显,一气呵成。有助与新手继续研究下去。

到目前为止,关于车牌定位的问题国内外众多学者提出了很多方法,适用条件不尽相同,各有利弊。弄懂了基本的颜色定位之后,可以尝试结合其它的方法来提升车牌定位的性能。

车牌特点

说完车牌定位的方法之后,需要对我们提取的对象本身的特点进行说明。车牌的大小固定,字体格式是由国家相关部门统一规定,与一般常见的字体格式都不一样。据说是由常见的宋体字修改而来,一般民用的车牌包含数字0-9,还有全国26个省市的简称,总共是36个字符。车牌的颜色以及字体颜色如下:

蓝牌白字:普通小型车(其中包括政府机关专用号段、政法部门警车以外的行政用车)的牌照
           黄牌黑字:大型车辆、摩托车、驾校教练车牌照
           黑牌白字:涉外车辆牌照,式样和蓝牌基本相同
                  白牌:政法部门(公安、法院、检察院、国安、司法)警车、武警部队车辆、解放军军车的牌照都是白牌
                  警车:公安警车的牌照样式为[某·A1234警],除“警”为红字外其他的都是黑字,一共4位数字,含义与普通牌照相同

我们研究的目标是普通民用小型车,也就是蓝牌白字车牌。说到这里,顺便说明一下蓝牌白字车牌的颜色信息,对于正常曝光的图像而言,蓝色车牌的三个通道值大约为Blue=138,Green=63,Red=23。除了颜色信息外,车牌形状为矩形,具有固定的长宽比3:1。知道车牌的这些信息后,在使用颜色信息定位时可以做为限制条件,这样可以提高车牌定位的准确性。

车牌提取的步骤

讲完车牌提取的方法和车牌本身的特点之后,接下来仔细说明基于颜色信息的定位方法各个环节处理效果图。

第一步:读取待处理图像

首先,读取待处理的彩色图像,判断图像是否读取成功,成功时显示原始图像。最后打印图像的长和宽,方便对图像的尺寸有一个了解。

Mat OriginalImg ;
OriginalImg = imread("TestPhoto (1).jpg", IMREAD_COLOR);//读取原始彩色图像if (OriginalImg.empty())  //判断图像对否读取成功{cout << "错误!读取图像失败\n";return -1;}imshow("原图", OriginalImg); //显示原始图像cout << "Width:" << OriginalImg.rows << "\tHeight:" << OriginalImg.cols << endl;//打印图像长宽

运行效果

第二步:图像尺寸变换

读取原图像后,可以看到原图像像素较高,对于车牌识别而言,过高的分辨率对识别结果效果太大的帮助,反而会影响识别的速度,也就是系统实时性会变差。所以在这里对尺寸进行统一变换,在保证输入图像的长宽比不变的情况下,将图像的长度变成640,相应的宽度可以通过计算得到。

    Mat ResizeImg; if (OriginalImg.cols > 640)resize(OriginalImg, ResizeImg, Size(640, 640* OriginalImg.rows / OriginalImg.cols));imshow("尺寸变换图", ResizeImg);

上图和原图的区别就是尺寸不一致。后续的处理步骤都是在缩放之后的图像基础上来做,适当分辨率的图像有助于提高系统的响应速度,也就是实时性。

第三步:基于颜色信息二值化

基于颜色的二值化处理就是通过颜色信息将图像二值化,上面已经提到了正常曝光的车牌各个通道的颜色信息大约是Blue=138,Green=63,Red=23。但是颜色信息有一定的偏差,因此在二值化时放宽颜色条件,然后再通过其他特点来精确寻找车牌区域。本文设置各个通道的偏差值为50。程序如下,注意观察颜色信息以及偏差值在程序中的体现。

unsigned char pixelB, pixelG, pixelR;  //记录各通道值
unsigned char DifMax = 50;             //基于颜色区分的阈值设置
unsigned char B = 138, G = 63, R = 23; //各通道的阈值设定,针对与蓝色车牌
Mat BinRGBImg = ResizeImg.clone();  //二值化之后的图像
int i = 0, j = 0;
for (i = 0; i < ResizeImg.rows; i++)   //通过颜色分量将图片进行二值化处理
{for (j = 0; j < ResizeImg.cols; j++){pixelB = ResizeImg.at<Vec3b>(i, j)[0]; //获取图片各个通道的值pixelG = ResizeImg.at<Vec3b>(i, j)[1];pixelR = ResizeImg.at<Vec3b>(i, j)[2];if (abs(pixelB - B) < DifMax && abs(pixelG - G) < DifMax && abs(pixelR - R) < DifMax){                                           //将各个通道的值和各个通道阈值进行比较BinRGBImg.at<Vec3b>(i, j)[0] = 255;     //符合颜色阈值范围内的设置成白色BinRGBImg.at<Vec3b>(i, j)[1] = 255;BinRGBImg.at<Vec3b>(i, j)[2] = 255;}else{BinRGBImg.at<Vec3b>(i, j)[0] = 0;        //不符合颜色阈值范围内的设置为黑色BinRGBImg.at<Vec3b>(i, j)[1] = 0;BinRGBImg.at<Vec3b>(i, j)[2] = 0;}}
}
imshow("基于颜色信息二值化", BinRGBImg);        //显示二值化处理之后的图像

第四步:形态学处理

基于颜色信息二值化的图像效果还是挺不错的,可以看到车牌区域基本完整,其他地方有一些细小的干扰,接下来进行形态学处理,消除小区域干扰。形态学闭操作——先膨胀后腐蚀,是图像的基本操作之一,其特点是填充细小空间,连接临近物体和平滑边界,不同矩形窗的大小会有不同的结果。(形态学基本知识可参考数字图像处理相关书籍)

Mat BinOriImg;     //形态学处理结果图像
Mat element = getStructuringElement(MORPH_RECT, Size(3, 3)); //设置形态学处理窗的大小
dilate(BinRGBImg, BinOriImg, element);     //进行多次膨胀操作
dilate(BinOriImg, BinOriImg, element);
dilate(BinOriImg, BinOriImg, element);erode(BinOriImg, BinOriImg, element);      //进行多次腐蚀操作
erode(BinOriImg, BinOriImg, element);
erode(BinOriImg, BinOriImg, element);
imshow("形态学处理后", BinOriImg);        //显示形态学处理之后的图像

第五步:增加限制条件寻找车牌区域并框选车牌

从上图中可以看到车牌的基本位置已经能够确定,接下来通过其他特点来进一步确定车牌区域。处理思路如下:

1.寻找各个空白区域外轮廓并计算面积;

2.为各个空白区域增加外接矩形并计算面积;

3.通过外轮廓面积与外接矩形的比值,判断区域的矩形度;

4.进一步判断长宽比;

5.满足全部条件确定车牌区域

double length, area, rectArea;     //定义轮廓周长、面积、外界矩形面积
double rectDegree = 0.0;           //矩形度=外界矩形面积/轮廓面积
double long2Short = 0.0;           //体态比=长边/短边
CvRect rect;           //外界矩形
CvBox2D box, boxTemp;  //外接矩形
CvPoint2D32f pt[4];    //矩形定点变量
double axisLong = 0.0, axisShort = 0.0;        //矩形的长边和短边
double axisLongTemp = 0.0, axisShortTemp = 0.0;//矩形的长边和短边
double LengthTemp;     //中间变量
float  angle = 0;      //记录车牌的倾斜角度
float  angleTemp = 0;
bool   TestPlantFlag = 0;  //车牌检测成功标志位
cvtColor(BinOriImg, BinOriImg, CV_BGR2GRAY);   //将形态学处理之后的图像转化为灰度图像
threshold(BinOriImg, BinOriImg, 100, 255, THRESH_BINARY); //灰度图像二值化
CvMemStorage *storage = cvCreateMemStorage(0);
CvSeq * seq = 0;     //创建一个序列,CvSeq本身就是一个可以增长的序列,不是固定的序列
CvSeq * tempSeq = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint), storage);
int cnt = cvFindContours(&(IplImage(BinOriImg)), storage, &seq, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
//第一个参数是IplImage指针类型,将MAT强制转换为IplImage指针类型
//返回轮廓的数目
//获取二值图像中轮廓的个数
cout << "number of contours   " << cnt << endl;  //打印轮廓个数
for (tempSeq = seq; tempSeq != NULL; tempSeq = tempSeq->h_next)
{length = cvArcLength(tempSeq);       //获取轮廓周长area = cvContourArea(tempSeq);       //获取轮廓面积if (area > 800 && area < 50000)     //矩形区域面积大小判断{rect = cvBoundingRect(tempSeq, 1);//计算矩形边界boxTemp = cvMinAreaRect2(tempSeq, 0);  //获取轮廓的矩形cvBoxPoints(boxTemp, pt);              //获取矩形四个顶点坐标angleTemp = boxTemp.angle;                 //得到车牌倾斜角度axisLongTemp = sqrt(pow(pt[1].x - pt[0].x, 2) + pow(pt[1].y - pt[0].y, 2));  //计算长轴(勾股定理)axisShortTemp = sqrt(pow(pt[2].x - pt[1].x, 2) + pow(pt[2].y - pt[1].y, 2)); //计算短轴(勾股定理)if (axisShortTemp > axisLongTemp)   //短轴大于长轴,交换数据{LengthTemp = axisLongTemp;axisLongTemp = axisShortTemp;axisShortTemp = LengthTemp;}elseangleTemp += 90;rectArea = axisLongTemp * axisShortTemp;  //计算矩形的面积rectDegree = area / rectArea;     //计算矩形度(比值越接近1说明越接近矩形)long2Short = axisLongTemp / axisShortTemp; //计算长宽比if (long2Short > 2.2 && long2Short < 3.8 && rectDegree > 0.63 && rectDegree < 1.37 && rectArea > 2000 && rectArea < 50000){Mat GuiRGBImg = ResizeImg.clone();TestPlantFlag = true;             //检测车牌区域成功for (int i = 0; i < 4; ++i)       //划线框出车牌区域cvLine(&(IplImage(GuiRGBImg)), cvPointFrom32f(pt[i]), cvPointFrom32f(pt[((i + 1) % 4) ? (i + 1) : 0]), CV_RGB(255, 0, 0));imshow("提取车牌结果图", GuiRGBImg);    //显示最终结果图box = boxTemp;angle = angleTemp;axisLong = axisLongTemp;axisShort = axisShortTemp;cout << "倾斜角度:" << angle << endl;}}
}

框选结果如下图所示。这部分牵扯到的变量较多,主要看思路,不必纠结为什么设置这么多变量,因为后面需要用到这些变量。

不知道细心的小伙伴有没有发现,其中有一个变量是倾斜角度。其实这个变量保存的是车牌区域的倾斜角度,通过观察原图中车牌的位置和姿态,和输出的倾斜角度的值可以明白这个值表达的含义。后续步骤就是车牌的倾斜矫正。各位首先有一个大致的了解。

车牌提取效果展示

下面展示一些提取车牌区域的效果图。

车牌提取源码

说完各个步骤的具体操作,最后贴上设计到的源码。各位自行验证改进!


#include <iostream>
#include <opencv2\opencv.hpp>using namespace std;
using namespace cv;int main(int,char *argv[])
{Mat OriginalImg;OriginalImg = imread("TestPhoto (1).jpg", IMREAD_COLOR);//读取原始彩色图像if (OriginalImg.empty())  //判断图像对否读取成功{cout << "错误!读取图像失败\n";return -1;}
//  imshow("原图", OriginalImg); //显示原始图像cout << "Width:" << OriginalImg.rows << "\tHeight:" << OriginalImg.cols << endl;//打印长宽Mat ResizeImg; if (OriginalImg.cols > 640)resize(OriginalImg, ResizeImg, Size(640, 640 * OriginalImg.rows / OriginalImg.cols));imshow("尺寸变换图", ResizeImg);unsigned char pixelB, pixelG, pixelR;  //记录各通道值unsigned char DifMax = 50;             //基于颜色区分的阈值设置unsigned char B = 138, G = 63, R = 23; //各通道的阈值设定,针对与蓝色车牌Mat BinRGBImg = ResizeImg.clone();  //二值化之后的图像int i = 0, j = 0;for (i = 0; i < ResizeImg.rows; i++)   //通过颜色分量将图片进行二值化处理{for (j = 0; j < ResizeImg.cols; j++){pixelB = ResizeImg.at<Vec3b>(i, j)[0]; //获取图片各个通道的值pixelG = ResizeImg.at<Vec3b>(i, j)[1];pixelR = ResizeImg.at<Vec3b>(i, j)[2];if (abs(pixelB - B) < DifMax && abs(pixelG - G) < DifMax && abs(pixelR - R) < DifMax){                                           //将各个通道的值和各个通道阈值进行比较BinRGBImg.at<Vec3b>(i, j)[0] = 255;     //符合颜色阈值范围内的设置成白色BinRGBImg.at<Vec3b>(i, j)[1] = 255;BinRGBImg.at<Vec3b>(i, j)[2] = 255;}else{BinRGBImg.at<Vec3b>(i, j)[0] = 0;        //不符合颜色阈值范围内的设置为黑色BinRGBImg.at<Vec3b>(i, j)[1] = 0;BinRGBImg.at<Vec3b>(i, j)[2] = 0;}}}imshow("基于颜色信息二值化", BinRGBImg);        //显示二值化处理之后的图像Mat BinOriImg;     //形态学处理结果图像Mat element = getStructuringElement(MORPH_RECT, Size(3, 3)); //设置形态学处理窗的大小dilate(BinRGBImg, BinOriImg, element);     //进行多次膨胀操作dilate(BinOriImg, BinOriImg, element);dilate(BinOriImg, BinOriImg, element);erode(BinOriImg, BinOriImg, element);      //进行多次腐蚀操作erode(BinOriImg, BinOriImg, element);erode(BinOriImg, BinOriImg, element);imshow("形态学处理后", BinOriImg);        //显示形态学处理之后的图像double length, area, rectArea;     //定义轮廓周长、面积、外界矩形面积double rectDegree = 0.0;           //矩形度=外界矩形面积/轮廓面积double long2Short = 0.0;           //体态比=长边/短边CvRect rect;           //外界矩形CvBox2D box, boxTemp;  //外接矩形CvPoint2D32f pt[4];    //矩形定点变量double axisLong = 0.0, axisShort = 0.0;        //矩形的长边和短边double axisLongTemp = 0.0, axisShortTemp = 0.0;//矩形的长边和短边double LengthTemp;     //中间变量float  angle = 0;      //记录车牌的倾斜角度float  angleTemp = 0;bool   TestPlantFlag = 0;  //车牌检测成功标志位cvtColor(BinOriImg, BinOriImg, CV_BGR2GRAY);   //将形态学处理之后的图像转化为灰度图像threshold(BinOriImg, BinOriImg, 100, 255, THRESH_BINARY); //灰度图像二值化CvMemStorage *storage = cvCreateMemStorage(0);CvSeq * seq = 0;     //创建一个序列,CvSeq本身就是一个可以增长的序列,不是固定的序列CvSeq * tempSeq = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint), storage);int cnt = cvFindContours(&(IplImage(BinOriImg)), storage, &seq, sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);//第一个参数是IplImage指针类型,将MAT强制转换为IplImage指针类型//返回轮廓的数目 //获取二值图像中轮廓的个数cout << "number of contours   " << cnt << endl;  //打印轮廓个数for (tempSeq = seq; tempSeq != NULL; tempSeq = tempSeq->h_next){length = cvArcLength(tempSeq);       //获取轮廓周长area = cvContourArea(tempSeq);       //获取轮廓面积if (area > 800 && area < 50000)     //矩形区域面积大小判断{rect = cvBoundingRect(tempSeq, 1);//计算矩形边界boxTemp = cvMinAreaRect2(tempSeq, 0);  //获取轮廓的矩形cvBoxPoints(boxTemp, pt);              //获取矩形四个顶点坐标angleTemp = boxTemp.angle;                 //得到车牌倾斜角度axisLongTemp = sqrt(pow(pt[1].x - pt[0].x, 2) + pow(pt[1].y - pt[0].y, 2));  //计算长轴(勾股定理)axisShortTemp = sqrt(pow(pt[2].x - pt[1].x, 2) + pow(pt[2].y - pt[1].y, 2)); //计算短轴(勾股定理)if (axisShortTemp > axisLongTemp)   //短轴大于长轴,交换数据{LengthTemp = axisLongTemp;axisLongTemp = axisShortTemp;axisShortTemp = LengthTemp;}elseangleTemp += 90;rectArea = axisLongTemp * axisShortTemp;  //计算矩形的面积rectDegree = area / rectArea;     //计算矩形度(比值越接近1说明越接近矩形)long2Short = axisLongTemp / axisShortTemp; //计算长宽比if (long2Short > 2.2 && long2Short < 3.8 && rectDegree > 0.63 && rectDegree < 1.37 && rectArea > 2000 && rectArea < 50000){Mat GuiRGBImg = ResizeImg.clone();TestPlantFlag = true;             //检测车牌区域成功for (int i = 0; i < 4; ++i)       //划线框出车牌区域cvLine(&(IplImage(GuiRGBImg)), cvPointFrom32f(pt[i]), cvPointFrom32f(pt[((i + 1) % 4) ? (i + 1) : 0]), CV_RGB(255, 0, 0));imshow("提取车牌结果图", GuiRGBImg);    //显示最终结果图box = boxTemp;angle = angleTemp;axisLong = axisLongTemp;axisShort = axisShortTemp;cout << "倾斜角度:" << angle << endl;}}}waitKey();return 0;}

好啦,本节就说到这里。下一篇开始说车牌的倾斜矫正,各位小伙伴期待吗?

基于OpenCV3.0的车牌识别系统设计(二)--车牌提取相关推荐

  1. matlab中liccode函数,基于matlab车牌识别系统设计与实现(最终版)

    <基于matlab车牌识别系统设计与实现.doc>由会员分享,可在线阅读全文,更多相关<基于matlab车牌识别系统设计与实现(最终版)>请在www.woc88.com上搜索. ...

  2. 基于matlab车牌识别程序,基于MATLAB车牌识别系统设计

    基于MATLAB车牌识别系统设计(任务书,开题报告,毕业论文11200字) 摘要 社会的不断发展带动着经济也不断的增长,从而也提高了人们的生活水平.汽车的需求量也日渐增加,现代化交通管理的出现,解决了 ...

  3. 基于 SoC 的卷积神经网络车牌识别系统设计(2-1)基于 Arm Cortex-M3 SoC 车牌识别系统的搭建

    基于 SoC 的卷积神经网络车牌识别系统设计(2-1)基于 Arm Cortex-M3 SoC 车牌识别系统的搭建 版权所有, ⌊ 新芯设计 ⌉ \lfloor新芯设计\rceil ⌊新芯设计⌉,转载 ...

  4. 基于 SoC 的卷积神经网络车牌识别系统设计(3-1)基于 Python 编程的车牌识别预处理、定位、分割、缩放的效果一览

    引言         这是一个在基于 OpenCV 的 Python 程序下,整体车牌定位.分割.识别的各个步骤的处理结果的展示,相当于算法的验证,只有先在软件上经过正确的严格的验证,才能进行硬件上的 ...

  5. 基于神经网络的车牌识别,卷积神经网络车牌识别

    现在很多工程项目都用车牌识别系统,我想问一下车牌识别系统的原理是什么? 核心算法:从六个步骤来提取我们抓拍的车牌信息,第一:图像捕捉采集.第二:车牌定位.第三:预处理.第四:字符分割.第五:字符识别. ...

  6. 【设计方案分享】基于单片机温度监测监控报警系统设计-基于单片机钞票自动智能识别系统设计-基于单片机乒乓球游戏机控制系统设计-基于单片机温度监测监控报警系统设计-基于单片机矩阵键盘的电子密码锁设计

    820基于单片机温度监测监控报警系统设计-设计资料 温度监测器功能描述: 1.主控芯片用的是51单片机(STC89C51). 2.使用温度传感器DS18b20采集温度. 3.用1602液晶显示显示温度 ...

  7. 基于单片机乒乓球游戏机控制系统设计-基于单片机矩阵键盘的电子密码锁设计-基于单片机温度监测监控报警系统设计-基于单片机钞票自动智能识别系统设计-设计资料【转发分享】

    819基于单片机乒乓球游戏机控制系统设计-设计资料下载 乒乓球游戏机设计任务为: (1)使用乒乓游戏机的甲乙双方各在不同的位置发球或击球. (2)乒乓球的位置和移动方向由灯亮及依次点燃的方向决定,球移 ...

  8. 表单识别(五)——票据识别-论文研读:基于深度学习的票据识别系统设计与实现,卞飞飞(上)

    (论文研读:基于深度学习的票据识别系统设计与实现,卞飞飞:) 引言: 传统的文本检测与识别算法主要指利用数字图像处理等非深度学习技术进行文本检测的方法,依赖于数字图像特征(如颜色.纹理.轮廓.形状等特 ...

  9. 基于SVM的语音情感识别系统设计

    基于SVM的语音情感识别系统设计 目录 基于SVM的语音情感识别系统设计 1  引言 2  情感语音信号的采集 3. 特征参数 §3.1 基音频率参数 §3.3 能量参数 4  语音情感的识别 §4. ...

  10. 【电路方案】基于单片机智能市电温度控制系统设计-基于单片机RGB颜色智能识别系统设计-基于单片机四路红外遥控开关电路设计-基于单片机自行车自动防盗报警系统设计-基于单片机智能无线病床呼叫系统设计

    822基于单片机智能无线病床呼叫系统设计-设计资料下载 硬件构成:单片机+最小系统+LCD1602液晶显示模块+无线收发模块+蜂鸣器模块+LED指示灯模块+按键模块 本设计基于STC89C51/52( ...

最新文章

  1. php 屏蔽mysql错误提示_PHP.ini中配置屏蔽错误信息显示和保存错误日志
  2. 字符串相加/大数相加(代码极短)
  3. linux release 版本的区别,编译debug版本和编译release版本的区别
  4. OJ1085: 求奇数的乘积(多实例测试)(C语言)
  5. Redis的主从复制和 哨兵模式
  6. 微软开源数据处理引擎 Trill,每天可分析万亿次事件
  7. magento模板制作教程(一)
  8. 北京公交将标配智能辅助驾驶,具备行人防撞、车道偏离预警
  9. idea中未被识别的maven项目,如何手动添加
  10. 深度学习神经网络的预测间隔
  11. 夜曲编程Python入门课程Pro
  12. java程序员推荐书籍
  13. RGB颜色 取色器/拾色器 颜色混搭
  14. 泊松分布(一种离散分布)
  15. 简单的avr c语言程序,avr单片机c语言编程风格介绍 - 全文
  16. 2017计算机二级ms office高级应用成绩查询
  17. 在线IP到地理位置解析的API接口,IP到地理位置、所属组织名、AS号、域名反查
  18. sd3403开发板学习(一)
  19. 将低版本CAD图纸转换成2018版本应该如何操作?
  20. 鹤林全集·怡情枫林 | 第一篇——岁末回首

热门文章

  1. 4、SYN-RCVD
  2. STM32——软件SPI控制AD7705
  3. python导入数据画直方图加正态曲线_用python制作正态分布图
  4. android 微信浮窗实现_Android仿微信文章悬浮窗效果的实现代码
  5. linux环境使用c语言获取系统时间,并拼接成字符串
  6. 简洁好用的Geek Unіnstaller
  7. python项目之神奇时钟
  8. 基于C++ Qt实现的红色警戒3修改器
  9. R语言|plot和par函数绘图详解,绘图区域设置 颜色设置 绘图后修改及图像输出
  10. 基础二:晶体与各向异性