原文在这里,参考这个进行了改进

感觉学到了很多东西,便在这里作下笔记。

效果:

目录

一、知识点学习:

1. fstream

2. 形态学开操作与形态闭操作

2.1 第一个角度:消除较小的联通区域 vs 弥合较小的联通区域

2.2 第二个角度:消除背景噪音 vs 消除前景噪音

3、approPolyDp函数

4、冒泡排序

5、匹配目标

6、putText函数打印中文

7、文字文件、标签文件

7.1 文字文件

7.2 标签文件

二、车牌识别代码

三、项目总结


一、知识点学习:

1. fstream

作用:输入输出文件;

例子:

    fstream fin;fin.open(filename, ios::in);if (!fin.is_open()){cout << "can not open the file!" << endl;return false;}string s;while (std::getline(fin, s)){string str = s;data_name.push_back(str);}fin.close();

上面用到的open函数详细介绍:

void open ( const char * filename,  ios_base::openmode mode = ios_base::in | ios_base::out );  

filename 操作文件名

mode 打开文件的方式,常用的有下面这两种

ios::in:     //文件以输入方式打开(文件数据输入到内存)
ios::out:    //文件以输出方式打开(内存数据输出到文件)

2. 形态学开操作与形态闭操作

这两个我一直不太懂,今天正好称这机会学习下。

2.1 第一个角度:消除较小的联通区域 vs 弥合较小的联通区域

形态学开运算的作用有以下这些:

  • 消除值高于邻近点的孤立点,达到去除图像中噪声的作用;
  • 消除较小的连通域,保留较大的连通域;
  • 断开较窄的狭颈,可以在两个物体纤细的连接处将它们分离;
  • 不明显改变较大连通域的面积的情况下平滑连通域的连界、轮廓;

形态学闭运算的作用有以下这些:

  • 消除值低于邻近点的孤立点,达到去除图像中噪声的作用;
  • 连接两个邻近的连通域;
  • 弥合较窄的间断和细长的沟壑;
  • 去除连通域内的小型空洞;
  • 和开运算一样也能够平滑物体的轮廓;

2.2 第二个角度:消除背景噪音 vs 消除前景噪音

开操作:消除背景噪音

闭操作:填充前景物体中的小洞,或者前景物体上的小黑点

3、approPolyDp函数

函数的作用:对图像轮廓点进行多边形拟合

函数的的调用形式:

void approxPolyDP( InputArray curve,OutputArray approxCurve,double epsilon, bool closed );

参数详解:

InputArray curve:一般是由图像的轮廓点组成的点集

OutputArray approxCurve:表示输出的多边形点集

double epsilon:主要表示输出的精度,就是另个轮廓点之间最大距离数,5,6,7,,8,,,,,

bool closed:表示输出的多边形是否封闭

4、冒泡排序

这里有直观的动图展示:动图

这里用到冒泡排序对车牌字符的Rect进行排序:

    for (size_t i =0; i< Character_ROI.size(); i++){for (size_t j=0; j< Character_ROI.size() -1 -i; j++){if (Character_ROI[j].rect.x > Character_ROI[j+1].rect.x){License temp = Character_ROI[j];Character_ROI[j] = Character_ROI[j+1];Character_ROI[j+1] = temp;}}}

假设有5个字符,它们的Rect的X坐标是  4 1 3 0 2, 现在用冒泡排序进行排序:

5、匹配目标

这里使用OpenCV absdiff函数计算两张图像的像素差,以此来判断图像的相似程度。

其他方法除了模板匹配,基于Hu矩轮廓匹配,基于篇幅原因就在另外博客再学习。

6、putText函数打印中文

我用的是OpenCV4.5.5,Ubuntun20.04,直接引入头文件就好了。

字体文件路径(windows系统):

/Windows/Fonts/

然后复制到Ubuntu系统下某个目录就行了

示例:

#include <iostream>
#include <opencv2/freetype.hpp>
#include <opencv2/opencv.hpp>using namespace std;
using namespace cv;int main()
{Mat src = imread("/home/jason/work/01-img/dog.png");string text = "中华田园犬";Ptr<cv::freetype::FreeType2> ft2;ft2 = cv::freetype::createFreeType2();ft2->loadFontData("/usr/share/fonts/winFonts/SIMYOU.TTF",0);ft2->putText(src, text, Point(300, 200), 30 , Scalar(0, 0,255), 2, 8, true);imshow("src", src);waitKey();return 0;
}

7、文字文件、标签文件

向博主私信了,但是没有回复,那就自己做一个。

7.1 文字文件

wps word导出的图片:

扣出字符来:

#include <iostream>
#include <opencv2/opencv.hpp>using namespace std;
using namespace cv;void Get_character(Mat & src, Mat & result)
{Mat gray;cvtColor(src, gray, COLOR_BGR2GRAY);// 黑色的点vector<Point> locations;for (int x=0; x< src.cols; x++)for (int y=0; y< src.rows; y++){if(gray.at<uchar>(y, x) < 255){locations.push_back(Point(x,y));}}// 字符左上角 右下角double xmin, ymin, xmax, ymax;vector<int> xs, ys;for(size_t i=0; i<locations.size(); i++){xs.push_back(locations[i].x);ys.push_back(locations[i].y);}Mat tempX(xs);Mat tempY(ys);Point p1;minMaxLoc(tempX, &xmin, &xmax,0,0);minMaxLoc(tempY, &ymin, &ymax, 0,0);// 画框Rect roi;Mat temp = src.clone();roi.x = xmin - 30;roi.y = ymin - 30;roi.width = xmax - xmin + 60;roi.height = ymax - ymin + 60;rectangle(src,roi, Scalar(255, 0,0), 1, 8);// 扣出来Mat ROI = temp(roi);imshow("ROI", ROI);result = ROI.clone();imshow("src", src);waitKey(10);
}int main()
{string tail = ".png";string head;string path, outpath;string outpath_head = "/home/jason/work/01-img/car/car_roi/";for (int i=0; i<= 69; i++){if (i<10){head = "/home/jason/work/01-img/car/car/0";}else{head = "/home/jason/work/01-img/car/car/";}path = head + to_string(i) + tail;outpath = outpath_head + to_string(i) + tail;Mat src = imread(path);Mat result;Get_character(src, result);imwrite(outpath,result);}return 0;
}

7.2 标签文件

二、车牌识别代码

我在识别俄过程中,发现自己字母字体与车牌字体对应不上,就可能出现偏差。

怎么办?我干脆就把车牌字符扣下来保存为模板!

locate.hpp

#include <iostream>
#include <opencv2/opencv.hpp>
#include<opencv2/freetype.hpp>
#include <fstream>
using namespace cv;
using namespace std;using namespace cv;
using namespace std;// 自定义车牌结构体
struct License
{Mat mat; // ROI图片Rect rect; // ROI所在矩形
};class Locate
{
private:// 车牌字符模板图片vector<Mat>  Dataset;// 车牌字符名vector<string> Data_name;// 字体文件路径string Font_Path;// 车牌字符扣出来另存路径string Character_Out_Path;bool Read_Data(string filename, vector<Mat>& dataset);bool Read_Data(string filename, vector<string>&data_name);void Image_Preprocessing(Mat& gray, Mat& result);void Morphological_Process(Mat& preprocess, Mat& result);void Character_ROI_Preprocessing(vector<License>& License_ROI);void Get_License_ROI(Mat &morpho, Mat &src,vector<License>& License_ROI);void Remove_vertial_Border(Mat& car_bord, Mat& result);void Remove_Horizon_Border(Mat& car_bord, Mat & result);public:bool Set_Input(string label_Path, string template_Path,string font_Path, string character_out_path);void Get_License_ROI(Mat& src, vector<License>& License_ROI);void Get_Character_ROI(vector<License>& License_ROI,vector<vector<License>>&Character_ROI,Mat &src, bool character_save);int pixCount(Mat image);void License_Recognition(vector<vector<License>>&Character_ROI,vector<vector<int>>&result_index);void Draw_Result(Mat &src,vector<License>& License_ROI,vector<vector<License>>&Character_ROI,vector<vector<int>>&result_index);};

locate.cpp

#include "Locate_License.h"// 读取文件 图片
bool Locate::Read_Data(string filename, vector<Mat>& dataset)
{vector<String> imagePathList;glob(filename, imagePathList); // 遍历文件夹下所有文件if (imagePathList.empty()) return  false;for (size_t i=0; i<imagePathList.size(); i++){cout << imagePathList[i] << endl;Mat image = imread(imagePathList[i]);resize(image, image, Size(50, 100), 1, 1, INTER_LINEAR);cvtColor(image, image, COLOR_BGR2GRAY);threshold(image, image, 0, 255, THRESH_BINARY_INV|THRESH_OTSU); // 字符需要是白色Mat kernel = getStructuringElement(MORPH_RECT, Size(3,3));dilate(image, image,kernel,Point(-1,-1),1);//        imshow(to_string(i), image);dataset.push_back(image);}this->Dataset = dataset;return true;
}//读取文件 标签
bool Locate::Read_Data(string filename, vector<string>&data_name)
{fstream fin;fin.open(filename, ios::in);if(!fin.is_open()){cout << "can not open the file!" << endl;return false;}string s;while (getline(fin, s)){string str = s;data_name.push_back(str);}fin.close();this->Data_name = data_name;return  true;
}bool Locate::Set_Input(string label_Path,string template_Path,string font_Path="/usr/share/fonts/winFonts/SIMYOU.TTF",string character_out_path = "/home/jason/work/01-img/car/out")
{this->Font_Path = font_Path;printf("字体路径设置为: %s, 请检查该目录是否正确\n",font_Path.c_str());this->Character_Out_Path = character_out_path;printf("车牌字符输出路径设置为: %s, 请检查该目录是否正确\n",character_out_path.c_str());if (Read_Data(label_Path, this->Data_name) &&Read_Data(template_Path, this->Dataset)){printf("***** 成功读取模板图片、标签数据\n");return true;}else{printf("***** err:读取模板图片、标签数据\n");return false;}
}// 突出字符
void Locate::Image_Preprocessing(Mat& gray, Mat& result)
{// 开操作,平滑作用,断开较窄的狭颈和消除细的突出物Mat kernel = getStructuringElement(MORPH_RECT, Size(25,25));Mat gray_blur;morphologyEx(gray, gray_blur, MORPH_OPEN, kernel);imshow("open1", gray_blur);// 灰度图-开操作图,突显字符等部分Mat rst;subtract(gray, gray_blur, rst, Mat());imshow("rst", rst);// Canny算子进行边缘检测Mat canny_Image;Canny(rst, canny_Image, 400, 200, 3);imshow("canny_Image", canny_Image);result=canny_Image.clone();
}// 通过膨胀连接相近的图像区域,
// 利用腐蚀去除孤立细小的色块,从而将所有的车牌上所有的字符都连通起来
void Locate::Morphological_Process(Mat& preprocess, Mat& result)
{// 图片膨胀处理Mat dilate_image, erode_image;//自定义核:进行 x 方向的膨胀腐蚀Mat elementX = getStructuringElement(MORPH_RECT, Size(19, 1));Mat elementY = getStructuringElement(MORPH_RECT, Size(1, 19));Point point(-1, -1);dilate(preprocess, dilate_image, elementX, point, 2);imshow("dilate1", dilate_image);//    // 闭操作,避免车牌与 其他区域联通在一起
//    Mat kernel = getStructuringElement(MORPH_RECT, Size(10, 10));
//    morphologyEx(dilate_image, dilate_image, MORPH_OPEN,
//                 kernel, Point(-1,-1),2);
//    imshow("MORPH_OPEN", dilate_image);erode(dilate_image, erode_image, elementX, point, 3);imshow("erode1", erode_image);dilate(erode_image, dilate_image, elementX, point, 2);imshow("dialte2", dilate_image);//自定义核:进行 Y 方向的膨胀腐蚀erode(dilate_image, erode_image, elementY, point, 1);imshow("yerode", erode_image);dilate(erode_image, dilate_image, elementY, point, 2);imshow("Ydilate", erode_image);// 平滑处理Mat median_Image;medianBlur(dilate_image, median_Image, 15);imshow("median1",median_Image);medianBlur(median_Image, median_Image, 15);imshow("median2", median_Image);result = median_Image.clone();
}// 扣出车牌
void Locate::Get_License_ROI(Mat &morpho, Mat &src, vector<License>& License_ROI)
{vector<vector<Point>> contours;findContours(morpho, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);//Mat temp =src.clone();drawContours(temp, contours, -1, Scalar(255,0,0), 4);//double area;for (size_t i=0; i< contours.size(); i++){// 轮廓 --》 rectRect rect = boundingRect(contours[i]);// 车牌的宽高比大约为3.3double width_height = (double)rect.width/ (double)rect.height;printf("height_width:%.2f\n", width_height);if (width_height>2.5 && width_height < 4.0){rectangle(temp, rect, Scalar(0,0, 255), 4, 8);License temp_license = {src(rect), rect};License_ROI.push_back(temp_license);}}imshow("标出车牌",temp);if (License_ROI.size() > 0){printf("****** 共提取到 %d 块车牌\n",(int)License_ROI.size());for (size_t i = 0; i< License_ROI.size(); i++){string tempName = "第" + to_string(i) + "块车牌";imshow(tempName, License_ROI[i].mat);}}else{printf("****** 没有发现车牌\n");}}// 从图片中扣出车牌
void Locate::Get_License_ROI(Mat& src, vector<License>& License_ROI)
{// 灰度图Mat gray;cvtColor(src, gray, COLOR_BGR2GRAY);imshow("gray", gray);// 均衡化equalizeHist(gray, gray);// 突出字符,并获得canny边缘Mat preprocess_result;Image_Preprocessing(gray, preprocess_result);// 将车牌字符形成一个整体Mat morpho_image;Morphological_Process(preprocess_result, morpho_image);// 扣出整块车牌Get_License_ROI(morpho_image, src, License_ROI);}void Locate::Remove_vertial_Border(Mat& car_bord, Mat & result)
{Mat vline = getStructuringElement(MORPH_RECT, Size(1,car_bord.rows));Mat dst1, temp1;erode(car_bord, temp1, vline);
//    imshow("V-erode",temp1);dilate(temp1, dst1, vline);
//    imshow("V-dilate",dst1);subtract(car_bord, dst1, result, Mat());
//    imshow("V-result",result);
}void Locate::Remove_Horizon_Border(Mat& car_bord, Mat & result)
{Mat hline = getStructuringElement(MORPH_RECT, Size(car_bord.rows,1));Mat dst1, temp1;erode(car_bord, temp1, hline);
//    imshow("H-erode",temp1);dilate(temp1, dst1, hline);
//    imshow("H-dilate",dst1);subtract(car_bord, dst1, result, Mat());
//    imshow("H-result",result);
}// 对整块车牌进行预处理,
void Locate::Character_ROI_Preprocessing(vector<License>& License_ROI)
{for (size_t i=0; i<License_ROI.size(); i++){// 灰度化Mat gray;cvtColor(License_ROI[i].mat, gray, COLOR_BGR2GRAY);imshow("gray--", gray);//        // 均衡化 这里不需要用,用了方而效果不好,因为车牌中车牌字符本身就很显眼,不需要用均衡
//        equalizeHist(gray, gray);// 大津阈值化Mat thresh;threshold(gray, thresh, 0, 255, THRESH_BINARY|THRESH_OTSU ); // 字是白色的的imshow("thres", thresh);Mat hori;Remove_Horizon_Border(thresh, hori);Mat vert;Remove_vertial_Border(hori,vert);imshow("H V", vert);Mat open;Mat kernel = getStructuringElement(MORPH_RECT, Size(2,2));morphologyEx(vert, open,MORPH_CLOSE, kernel, Point(-1,-1),1);imshow("连接汉字两边", open);License_ROI[i].mat = open.clone();}}//
void Locate::Get_Character_ROI(vector<License>& License_ROI,vector<vector<License>>&Character_ROI,Mat &src,bool character_save=true)
{Character_ROI_Preprocessing(License_ROI);Mat temp = src.clone();for (size_t j=0; j<License_ROI.size(); j++){Mat temp_carbod = License_ROI[j].mat.clone();Character_ROI.push_back({}); // 必须先添加一个空项进去vector<vector<Point>> contours;findContours(License_ROI[j].mat, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);drawContours(temp, contours, -1, Scalar(255,0,0), 2, 8);imshow("Get_Character_ROI", temp);for (size_t i = 0; i<contours.size(); i++){double area = contourArea(contours[i]);//由于我们筛选出来的轮廓是无序的,故后续我们需要将字符重新排序if (area > 100){Rect rect = boundingRect(contours[i]);// 计算外接矩形框高比double ratio = double(rect.height)/ double(rect.width);if (ratio > 1){// 字符扣出来Mat roi = License_ROI[j].mat(rect);resize(roi, roi, Size(50, 100), 1, 1, INTER_LINEAR);Character_ROI[j].push_back({roi, rect});  // 前面不添加一个空项进去,这就就报错// 字符在原图画框rectangle(temp_carbod ,rect, Scalar(255, 0, 0), 2, 8);imshow("字符框",temp_carbod);// 字符另外为if (character_save){threshold(roi,roi,0, 255, THRESH_BINARY_INV|THRESH_OTSU);string outpath = this->Character_Out_Path + "/" + to_string(i) + ".png";imwrite(outpath,roi);}}}}//将筛选出来的字符轮廓 按照其左上角点坐标从左到右依次顺序排列// 冒泡排序 ; 你查一下,用41302自己排下序就懂了for (size_t k =0; k<Character_ROI.size(); k++){for (size_t ii =0; ii< Character_ROI[k].size(); ii++){for (size_t jj=0; jj< Character_ROI[k].size() -1 -ii; jj++){if (Character_ROI[k][jj].rect.x > Character_ROI[k][jj+1].rect.x){License temp = Character_ROI[k][jj];Character_ROI[k][jj] = Character_ROI[k][jj+1];Character_ROI[k][jj+1] = temp;}}}}}if (Character_ROI.size() > 0){for (size_t k =0; k<Character_ROI.size(); k++){printf("******* 第 %d 块车牌共扣出: %d 个字符\n", (int)k,(int)Character_ROI[k].size());}}else{printf("***** err :第车牌没有扣出字符!\n");}}int Locate::pixCount(Mat image)
{int count =0;if (image.channels() == 1){for (int i=0; i<image.rows; i++){for (int j=0; j<image.cols; j++){if (image.at<uchar>(i, j) == 255) // 数的是白色像素{count++;}}}return count;}else{return -1;}
}// 识别车牌字符
// 使用OpenCV absdiff函数计算两张图像的像素差,以此来判断图像的相似程度
// 进行字符匹配的方法还有:模板匹配,基于Hu矩轮廓匹配
void Locate::License_Recognition(vector<vector<License>>&Character_ROI,vector<vector<int>>& result_inedx)
{for (size_t k =0; k<Character_ROI.size(); k++){result_inedx.push_back({});for (int i=0; i<Character_ROI[k].size(); i++){// 车牌单个字符预处理Mat roi_thresh;threshold(Character_ROI[k][i].mat, roi_thresh, 0, 255, THRESH_BINARY_INV); // 车牌字符需是白色string car = "car" + to_string(i);imshow(car,roi_thresh);int minCount = 1000000000;int index = 0;for (int j=0; j < this->Dataset.size(); j++){// 计算车牌字符与模板的像素差,以此判断两张图片是否相同Mat templa = this->Dataset[j];Mat dst;absdiff(roi_thresh, templa, dst);// 白字黑底,两图像素相减,白色像素越少,两图越接近int  count = pixCount(dst);if (count< minCount){minCount = count;index = j;}//            imshow(to_string(j),dst);}string p = "templ" + to_string(i);imshow(p, this->Dataset[index]);result_inedx[k].push_back(index);}}printf("*****共对 %d 块车牌的字符完成字符匹配\n",(int)Character_ROI.size());}// 显示最终效果
void Locate::Draw_Result(Mat &src, vector<License> &License_ROI,vector<vector<License>>&Character_ROI,vector<vector<int>>&result_index)
{Ptr<cv::freetype::FreeType2> ft2;ft2 = cv::freetype::createFreeType2();ft2->loadFontData(this->Font_Path,0);for (size_t k=0; k<License_ROI.size(); k++){// 原图上框出车牌rectangle(src, License_ROI[k].rect, Scalar(0, 255, 0), 2);// 在原图车牌框上方上打印车牌字符for (size_t i=0; i< Character_ROI[k].size(); i++){//        cout << data_name[result_index[i]] << " ";string str = this->Data_name[result_index[k][i]];ft2->putText(src, str,Point(License_ROI[k].rect.x + Character_ROI[k][i].rect.x,License_ROI[k].rect.y - Character_ROI[k][i].rect.y),30,Scalar(255, 0, 0), 1, 8, true);}//    cout  << endl;}}

main.cpp

#include "Locate_License.h"int main()
{Mat src = imread("/home/jason/work/01-img/car.png");if (src.empty()){cout << "No image!" << endl;system("pause");return -1;}Locate locate;locate.Set_Input("/home/jason/work/01-img/car/car.txt","/home/jason/work/01-img/car/template","/usr/share/fonts/winFonts/SIMYOU.TTF","/home/jason/work/01-img/car/out");vector<License> License_ROI;locate.Get_License_ROI(src, License_ROI);vector<vector<License>> Character_ROI;locate.Get_Character_ROI(License_ROI, Character_ROI,src, true);vector<vector<int>> result_index;locate.License_Recognition(Character_ROI,result_index);locate.Draw_Result(src, License_ROI,Character_ROI, result_index);imshow("车牌识别结果", src);waitKey();return 0;
}

想要模板图片文件和标签文件可以在评论区留言或者私信我,上传在CSDN还得是VIP你们才能下载。

三、项目总结

代码思路:

  1. 获取整个车牌  (这里部分涉及预处理很有意思)
  2. 对车牌进行切割,获得7个字符
  3. 将获得的车牌字符与模板匹配

项目不足:

  1. 本项目仅仅对车牌字符为白色的车牌有用
  2. 未对车牌作旋转矫正【p1, p2】,透视矫正,这两个因素影响很大,后面有空再补上

ps: 这个项目做了好几天,cpp文件干到了500行,原文才300行,增加近一半代码,短时间不想改了

OpenCV实战5 车牌号识别相关推荐

  1. 用python写一个车牌号识别系统

    写车牌号识别系统需要用到计算机视觉技术,具体的实现方法如下: 图像预处理:对图像进行预处理,包括灰度化.二值化.边缘检测等,以得到图像中车牌的区域. 区域分割:对图像进行分割,得到车牌区域. 文字识别 ...

  2. Android扫车牌号识别技术SDK

    Android扫车牌号识别技术SDK Android扫车牌号识别技术SDK描述 Android扫车牌号识别技术SDK是我公司开发的基于移动平台的车牌识别软件开发包,支持android.iOS等多种主流 ...

  3. 【机器学习】 - 作业4: 基于K-近邻的车牌号识别

    课程链接: 清华大学驭风计划 代码仓库:Victor94-king/MachineLearning: MachineLearning basic introduction (github.com) 驭 ...

  4. halcon学习笔记-车牌号识别

    1.读取图像 快捷键:ctrl+r,以这张车牌为例: 2.图像三通道分割 由于图像中颜色区分明显,尤其是车牌号与背景之间的色差较大,用颜色特征进行分割比较合适.通过三通道分割,将RGB图分成三层独立的 ...

  5. 通过百度API实现图片车牌号识别

    本代码功能是通过调用百度API实现的,所有你需要去百度API官网申请下你的API Key 以及Secret Key才能使用它的功能哦! 首先导入maven依赖 <dependency>&l ...

  6. 基于python车牌号识别_如何用Python提取和识别车牌号?

    下面是一个关于如何解决你的问题的粗略想法.你可以在此基础上再接再厉.您需要从图像中提取车牌号,然后将图像发送到您的tesseract.阅读代码注释以了解我正在尝试做什么.在import numpy a ...

  7. spring boot + maven + opencv 车牌识别系统,包含车牌检测、车牌号识别训练

    yx-image-recognition 介绍 这是一个基于spring boot + maven + opencv 实现的图像识别及训练的Demo项目 包含车牌识别.人脸识别等功能,贯穿样本处理.模 ...

  8. OpenCV实战(二)——答题卡识别判卷

    代码见 https://github.com/skyerhxx/Answer-card-recognition-and-judgment 答题卡识别判卷 识别出考生选择的答案并能自动判分 Python ...

  9. 基于谷歌街景多位数字识别技术:TensorFlow的车牌号识别系统

    向AI转型的程序员都关注了这个号

最新文章

  1. 控制器框架Struts与策略模式那点事
  2. Linux内核探讨-- 第六章
  3. “贩卖”国潮新鲜感的花西子、完美日记们,能炒多久?
  4. hihocder 1181 : 欧拉路·二
  5. 【Python】卸载 PyCharm!这才是 Python 小白的最理想的 IDE
  6. JVM性能调优中的命令总结
  7. linux下面的浏览器不停自动打开新网页
  8. WPF多线程UI更新
  9. 【Python】jieba库的使用
  10. 作为一个软件开发公司如何让自己的技术落地应用产生价值呢?
  11. PDF超过6000页,OMG,学它
  12. 图片剪裁控件——ClipImageView
  13. 分布式会议系统中的服务器,多功能会议系统分配服务器质量过硬
  14. 主机-配件-接口-整机-3c-2
  15. Python 数值四舍五入碰到遇5不进
  16. 笔记:python 绘图进阶
  17. 未能将文件 *** \bin\Release\**.dll 复制到 \obj\Release\Package\PackageTmp\bin\***.dll VS发布程序报错 解决办法
  18. Word文档丢失找回之没有保存Word文档就关闭了怎么解决
  19. 在Win32程序中创建OpenGL渲染环境
  20. 何恺明 matlab,[论文复现]何恺明博士CVPR2009去雾算法(1)

热门文章

  1. 函数的length代表什么
  2. Python+GDAL面数据中心点提取为单独shape文件,并复制属性数据
  3. 【什么是渲染目标(render target)】
  4. 技巧---数学分析1:变换积分次序
  5. 在公司三年跌宕起伏的经历
  6. 20155220 吴思其 《网络攻防》 Exp1 PC平台逆向破解(5)M
  7. #visual studio# 运行库MT、MTd、MD、MDd
  8. JSON是个什么东西?
  9. Linux常用文本编辑器,及文本查看摘选的常用命令
  10. 数字化转型的避坑指南:细说数字化转型十二大坑