你好!这里是风筝的博客,

欢迎和我一起交流。


之前说到,把车牌区域提前出来后,就可以着手识别程序了。先使用SVM判断是不是车牌。这里为了提高运行速度,板子资源有限,程序里我把svm训练部分注释掉了,假设每次都能找到车牌,实际使用时,还是要加上svm的。
      然后对图像进行分割,我们的分类器只能对数字一个一个地识别,所以把每个数字分割出来,每个字符归一化为20*20的字符。
      基本思想是先用findContours()函数把基本轮廓找出来,然后通过简单验证以确认是否为数字的轮廓。对于那些通过验证的轮廓,接下去会用boundingRect()找出它们的包围盒。
      分割完后就可以进行识别了,字符识别使用ANN算法采用三层神经网络,识别需要用到一些xml文件,这些文件需要用分类器和大量样本做训练,提取他们的特征、,让机器去“学习”(利用训练好的XML文件去预测图像中车牌 ),我找的这三个xml数据集,说实话,不太好用,准确率一般般,有兴趣的可以自己训练。

完整程序如下,里面有详细注释了:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <string>
#include <cvaux.h>
#include <stdio.h>
#include <opencv2/gpu/gpu.hpp>
#include <opencv2/ml/ml.hpp>using namespace cv;
using namespace std;//车牌宽高比为520/110=4.727272左右,误差不超过40%
//车牌高度范围在15~125之间,视摄像头距离而定(图像大小)
bool verifySizes_closeImg(const RotatedRect & candidate)
{float error = 0.4;//误差40%const float aspect = 4.7272;//44/14; //长宽比int min = 15*aspect*15;//20*aspect*20; //面积下限,最小区域int max = 125*aspect*125;//180*aspect*180;  //面积上限,最大区域float rmin = aspect - aspect*error; //考虑误差后的最小长宽比float rmax = aspect + aspect*error; //考虑误差后的最大长宽比int area = candidate.size.height * candidate.size.width;//计算面积float r = (float)candidate.size.width/(float)candidate.size.height;//计算宽高比if(r <1)r = 1/r;if( (area < min || area > max) || (r< rmin || r > rmax)  )//满足条件才认为是车牌候选区域return false;elsereturn true;
}void RgbConvToGray(const Mat& inputImage,Mat & outpuImage)  //g = 0.3R+0.59G+0.11B
{outpuImage = Mat(inputImage.rows ,inputImage.cols ,CV_8UC1);  for (int i = 0 ;i<inputImage.rows ;++ i){uchar *ptrGray = outpuImage.ptr<uchar>(i); const Vec3b * ptrRgb = inputImage.ptr<Vec3b>(i);for (int j = 0 ;j<inputImage.cols ;++ j){ptrGray[j] = 0.3*ptrRgb[j][2]+0.59*ptrRgb[j][1]+0.11*ptrRgb[j][0];  }}
}void normal_area(Mat &intputImg, vector<RotatedRect> &rects_optimal, vector <Mat>& output_area )
{float r,angle;for (int i = 0 ;i< rects_optimal.size() ; ++i){//旋转区域angle = rects_optimal[i].angle;r = (float)rects_optimal[i].size.width / (float) (float)rects_optimal[i].size.height;if(r<1)angle = 90 + angle;//旋转图像使其得到长大于高度图像。Mat rotmat = getRotationMatrix2D(rects_optimal[i].center , angle,1);//获得变形矩阵对象Mat img_rotated;warpAffine(intputImg ,img_rotated,rotmat, intputImg.size(),CV_INTER_CUBIC);imwrite("car_rotated.jpg",img_rotated);//得到旋转图像//裁剪图像Size rect_size = rects_optimal[i].size;if(r<1)swap(rect_size.width, rect_size.height); //交换高和宽Mat  img_crop;getRectSubPix(img_rotated ,rect_size,rects_optimal[i].center , img_crop );//图像切割//用光照直方图调整所有裁剪得到的图像,使具有相同宽度和高度,适用于训练和分类Mat resultResized;//别人写的:/*resultResized.create(33,144,CV32FC1);resize(img_crop , resultResized,resultResized.size() , 0,0,INTER_CUBIC);resultResized.convertTo(resultResized, CV32FC1);resultResized = resultResized.reshape(1,1);*/resultResized.create(33,144,CV_8UC3);//CV32FC1????resize(img_crop , resultResized,resultResized.size() , 0,0,INTER_CUBIC);Mat grayResult;RgbConvToGray(resultResized ,grayResult);//blur(grayResult ,grayResult,Size(3,3));equalizeHist(grayResult,grayResult);output_area.push_back(grayResult);}
}bool char_verifySizes(const RotatedRect & candidate)
{float aspect = 45.0f/77.0f;//45.0f/90.0f;float width,height;if (candidate.size.width >=candidate.size.height){width = (float) candidate.size.height;height = (float) candidate.size.width;}else {width = (float) candidate.size.width;height  = (float)candidate.size.height;}//这样确定是了高比宽要高float charAspect = (float) width/ (float)height;//宽高比float error = 0.35;//0.5;float minHeight = 15;  //最小高度11float maxHeight = 28;//33;  //最大高度33float minAspect = 0.15;//0.05;  //考虑到数字1,最小长宽比为0.15float maxAspect = 1.0;if( charAspect > minAspect && charAspect <= 1.0&&  height>= minHeight && height< maxHeight) //非0像素maxAspect长宽比、高度需满足条件return true;elsereturn false;
}void char_sort(vector <RotatedRect > & in_char ) //对字符区域进行排序
{vector <RotatedRect >  out_char;const int length = 7;           //7个字符int index[length] = {0,1,2,3,4,5,6};float centerX[length];for (int i=0;i < length ; ++ i){centerX[i] = in_char[i].center.x;}for (int j=0;j <length;j++) {for (int i=length-2;i >= j;i--)if (centerX[i] > centerX[i+1]){float t=centerX[i];centerX[i]=centerX[i+1];centerX[i+1]=t;int tt = index[i];index[i] = index[i+1];index[i+1] = tt;}}for(int i=0;i<length ;i++)out_char.push_back(in_char[(index[i])]);in_char.clear();     //清空in_charin_char = out_char; //将排序好的字符区域向量重新赋值给in_char
}void char_segment(const Mat & inputImg,vector <Mat>& dst_mat)//得到20*20的标准字符分割图像
{Mat img_threshold;threshold(inputImg ,img_threshold , 180,255 ,CV_THRESH_BINARY );//二值化//Mat element = getStructuringElement(MORPH_RECT ,Size(3 ,3));  //闭形态学的结构元素//morphologyEx(img_threshold ,img_threshold,CV_MOP_CLOSE,element);  //形态学处理//imshow ("img_thresho00ld",img_threshold);//waitKey();Mat img_contours;img_threshold.copyTo(img_contours);if (!clearLiuDing(img_contours)){std::cout << "不是车牌" << endl;}else{//imshow("img_cda",img_contours);//waitKey();Mat result2;inputImg.copyTo(result2);vector < vector <Point> > contours;findContours(img_contours ,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);vector< vector <Point> > ::iterator itc = contours.begin();vector<RotatedRect> char_rects;drawContours(result2,contours,-1, Scalar(0,255,255), 1); while( itc != contours.end()){RotatedRect minArea = minAreaRect(Mat( *itc )); //返回每个轮廓的最小有界矩形区域Point2f vertices[4];minArea.points(vertices);if(!char_verifySizes(minArea))  //判断矩形轮廓是否符合要求{itc = contours.erase(itc);}else     {++itc; char_rects.push_back(minArea);     }   }/*imshow("char1",char_rects[1]);imshow("char2",char_rects[2]);imshow("char3",char_rects[3]);imshow("char4",char_rects[4]);imshow("char5",char_rects[5]);imshow("char6",char_rects[6]);imshow("char7",char_rects[0]);waitKey();*/char_sort(char_rects); //对字符排序vector <Mat> char_mat;for (int i = 0; i<char_rects.size() ;i++ ){char_mat.push_back(Mat(img_threshold,char_rects[i].boundingRect()));}//imshow("char_mat1",char_mat[0]);//imshow("char_mat2",char_mat[1]);//imshow("char_mat3",char_mat[2]);//imshow("char_mat4",char_mat[3]);//imshow("char_mat5",char_mat[4]);//imshow("char_mat6",char_mat[5]);//imshow("char_mat7",char_mat[6]);//waitKey();Mat train_mat(2,3,CV_32FC1);int length ;dst_mat.resize(7);Point2f srcTri[3];  Point2f dstTri[3];for (int i = 0; i==0;i++){srcTri[0] = Point2f( 0,0 );  srcTri[1] = Point2f( char_mat[i].cols - 1, 0 );  srcTri[2] = Point2f( 0, char_mat[i].rows - 1 );length = char_mat[i].rows > char_mat[i].cols?char_mat[i].rows:char_mat[i].cols;dstTri[0] = Point2f( 0.0, 0.0 );  dstTri[1] = Point2f( length, 0.0 );  dstTri[2] = Point2f( 0.0, length ); train_mat = getAffineTransform( srcTri, dstTri );dst_mat[i]=Mat::zeros(length,length,char_mat[i].type());      warpAffine(char_mat[i],dst_mat[i],train_mat,dst_mat[i].size(),INTER_LINEAR,BORDER_CONSTANT,Scalar(0));//resize(dst_mat[i],dst_mat[i],Size(20,20),0,0,CV_INTER_CUBIC);  //尺寸调整为20*20resize(dst_mat[i],dst_mat[i],Size(20,20));//每个字符归一化为20*20的字符}for (int i = 1; i< char_mat.size();++i){srcTri[0] = Point2f( 0,0 );  srcTri[1] = Point2f( char_mat[i].cols - 1, 0 );  srcTri[2] = Point2f( 0, char_mat[i].rows - 1 );length = char_mat[i].rows > char_mat[i].cols?char_mat[i].rows:char_mat[i].cols;dstTri[0] = Point2f( 0.0, 0.0 );  dstTri[1] = Point2f( length, 0.0 );  dstTri[2] = Point2f( 0.0, length ); train_mat = getAffineTransform( srcTri, dstTri );dst_mat[i]=Mat::zeros(length,length,char_mat[i].type());      warpAffine(char_mat[i],dst_mat[i],train_mat,dst_mat[i].size(),INTER_LINEAR,BORDER_CONSTANT,Scalar(0));//resize(dst_mat[i],dst_mat[i],Size(20,20),0,0,CV_INTER_CUBIC);  //尺寸调整为20*20resize(dst_mat[i],dst_mat[i],Size(20,20));//每个字符归一化为20*20的字符}}
}void features(const Mat & in , Mat & out ,int sizeData)
{// 分别在水平方向和垂直方向上 创建累积直方图Mat vhist = projectHistogram(in , 1); //水平直方图Mat hhist = projectHistogram(in , 0);  //垂直直方图// 低分辨率图像// 低分辨率图像中的每一个像素都将被保存在特征矩阵中Mat lowData;resize(in , lowData ,Size(sizeData ,sizeData ));//特征矩阵的列数int numCols = vhist.cols + hhist.cols + lowData.cols * lowData.cols;out = Mat::zeros(1, numCols , CV_32F);// 向特征矩阵赋值int j = 0;for (int i =0 ;i<vhist.cols ; ++i)// 首先把水平方向累积直方图的值,存到特征矩阵中{out.at<float>(j) = vhist.at<float>(i);j++;}for (int i=0 ; i < hhist.cols ;++i)// 然后把竖直方向累积直方图的值,存到特征矩阵中{out.at<float>(j) = hhist.at<float>(i);}for(int x =0 ;x<lowData.rows ;++x)// 最后把低分辨率图像的像素值,存到特征矩阵中{for (int y =0 ;y < lowData.cols ;++ y){out.at<float>(j) = (float)lowData.at<unsigned char>(x,y);j++;}}
}void ann_train(CvANN_MLP &ann ,int numCharacters, int nlayers, string str)//http://blog.csdn.net/yiqiudream/article/details/51712497
{Mat trainData ,classes;FileStorage fs;fs.open(str, FileStorage::READ);//str是文件名字fs["TrainingData"] >>trainData;fs["classes"] >>classes;//CvANN_MLP bp;   //Set up BPNetwork's parameters  //CvANN_MLP_TrainParams params;  //params.train_method=CvANN_MLP_TrainParams::BACKPROP;  //params.bp_dw_scale=0.1;  //params.bp_moment_scale=0.1; Mat layerSizes(1,3,CV_32SC1);layerSizes.at<int>( 0 ) = trainData.cols;layerSizes.at<int>( 1 ) = nlayers; //隐藏神经元数,可设为3layerSizes.at<int>( 2 ) = numCharacters; //样本类数为34//layerSizes.at<int>( 3 ) = numCharacters ;ann.create(layerSizes , CvANN_MLP::SIGMOID_SYM );  //初始化annMat trainClasses;trainClasses.create(trainData.rows , numCharacters ,CV_32FC1);for (int i =0;i< trainData.rows; i++){for (int k=0 ; k< trainClasses.cols ; k++ ){if ( k == (int)classes.at<uchar> (i)){trainClasses.at<float>(i,k)  = 1 ;}elsetrainClasses.at<float>(i,k)  = 0;         }       }Mat weights(1 , trainData.rows , CV_32FC1 ,Scalar::all(1) );ann.train( trainData ,trainClasses , weights);
}void svm_train(CvSVM & svmClassifier)
{FileStorage fs;fs.open("SVM.xml" , FileStorage::READ);Mat SVM_TrainningData;Mat SVM_Classes; fs["TrainingData"] >>SVM_TrainningData;fs["classes"] >>SVM_Classes;CvSVMParams SVM_params;SVM_params.kernel_type = CvSVM::LINEAR;svmClassifier.train(SVM_TrainningData,SVM_Classes ,Mat(),Mat(),SVM_params); //SVM训练模型fs.release();
}int main(int argc, char* argv[])
{Mat img_input= imread("./car.jpg");//加载图片if(img_input.empty())//如果读入图像失败{cout << "Can not load image" << endl;return -1;}Mat hsvImg ;cvtColor(img_input,hsvImg,CV_BGR2HSV);//RGB模型转换成HSV模型imwrite("car_hsv.jpg",hsvImg);//看下hsv效果vector <Mat> hsvSplit;split(hsvImg,hsvSplit);//将图像的各个通道分离equalizeHist(hsvSplit[2],hsvSplit[2]);//直方图均衡化,提高图像的质量merge(hsvSplit,hsvImg);//将分离的多个单通道合成一幅多通道图像imwrite("car_hsv1.jpg",hsvImg);//看下处理效果const int min_blue =100;//最小蓝车区域const int max_blue =240;//最大蓝车区域int avg_h = (min_blue+max_blue)/2;int channels = hsvImg.channels();int nRows = hsvImg.rows;//图像数据列需要考虑通道数的影响;int nCols = hsvImg.cols * channels;if (hsvImg.isContinuous())//连续存储的数据,按一行处理{nCols *= nRows;nRows = 1;}int i, j;unsigned char* p;const float  minref_sv = 64; //参考的S V的值const float max_sv = 255; // S V 的最大值for (i = 0; i < nRows; ++i)//根据蓝色在HSV在的区域每个通道的取值范围将此作为阈值,提取出图片中蓝色部分作为备选区域{p = hsvImg.ptr<uchar>(i);//有效提高了车牌和车色颜色在不相差较大的情况下的识别率for (j = 0; j < nCols; j += 3)//致命问题:蓝色的车和蓝色的牌照?{int H = int(p[j]); //0-180int S = int(p[j + 1]);  //0-255int V = int(p[j + 2]);  //0-255bool colorMatched = false;if (H > min_blue && H < max_blue){int Hdiff = 0;float Hdiff_p = float(Hdiff) / 40;float min_sv = 0;if (H > avg_h){Hdiff = H - avg_h;}   else{Hdiff = avg_h - H;}min_sv = minref_sv - minref_sv / 2 * (1 - Hdiff_p);if ((S > 70&& S < 255) &&(V > 70 && V < 255))colorMatched = true;}if (colorMatched == true) {p[j] = 0; p[j + 1] = 0; p[j + 2] = 255;}else {p[j] = 0; p[j + 1] = 0; p[j + 2] = 0;}}}Mat src_grey;Mat img_threshold;vector<Mat> hsvSplit_done;split(hsvImg, hsvSplit_done);src_grey = hsvSplit_done[2];//提取黑色分量imwrite("car_hsvSplit.jpg",src_grey);//查看分离通道出来的车牌vector <RotatedRect>  rects;Mat element = getStructuringElement(MORPH_RECT ,Size(17 ,3));  //闭形态学的结构元素morphologyEx(src_grey ,img_threshold,CV_MOP_CLOSE,element); //闭运算,先膨胀后腐蚀,连通近邻区域(填补白色区域的间隙)morphologyEx(img_threshold,img_threshold,MORPH_OPEN,element);//形态学处理imwrite("car_morphology.jpg",img_threshold);//查看thresholdvector< vector <Point> > contours;//寻找车牌区域的轮廓findContours(img_threshold ,contours,CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);//只检测外轮廓。存储所以轮廓点//绘制轮廓/*for(int find=0; find < contours.size(); find++)drawContours(img_threshold, contours, find, Scalar(255), 2);imwrite("car_contours.jpg",img_threshold);//查看轮廓*///对候选的轮廓进行进一步筛选vector< vector <Point> > ::iterator itc = contours.begin();while( itc != contours.end()){RotatedRect mr = minAreaRect(Mat( *itc )); //返回每个轮廓的最小有界矩形区域if(!verifySizes_closeImg(mr))  //判断矩形轮廓是否符合要求{itc = contours.erase(itc);}else     {rects.push_back(mr);++itc;}      }vector <Mat> output_area;normal_area(img_input ,rects,output_area);  //获得144*33的候选车牌区域output_areaimwrite("car_area.jpg",output_area[0]);//得到候选区域,这里可能会获得多个候选区域,最好使用svm训练一下//(二)添加如下://CvSVM  svmClassifier;//为了运行速度,我就把这里注释掉了,这样会降低准确度//svm_train(svmClassifier);  //使用SVM对正负样本进行训练,为了运行速度,我就把这里注释掉了,这样会降低准确度vector<Mat> plates_svm;   //需要把候选车牌区域output_area图像中每个像素点作为一行特征向量,后进行预测for(int i=0;i< output_area.size(); ++i)//实际情况下应该加上SVM训练,我这里是学习测试{cout << "output " << i << endl;Mat img = output_area[i];Mat p = img.reshape(1,1);p.convertTo(p,CV_32FC1);//int response = (int)svmClassifier.predict( p );//为了运行速度,我就把这里注释掉了,这样会降低准确度//if (response == 1)//为了运行速度,我就把这里注释掉了,这样会降低准确度plates_svm.push_back(output_area[i]);    //保存预测结果}//从SVM预测获取车牌区域分割得到字符区域vector <Mat> char_seg;char_segment(plates_svm[0],char_seg);//对车牌区域中字符进行分割imwrite("char0.jpg",char_seg[0]);//显示七个字符imwrite("char1.jpg",char_seg[1]);imwrite("char2.jpg",char_seg[2]);imwrite("char3.jpg",char_seg[3]);imwrite("char4.jpg",char_seg[4]);imwrite("char5.jpg",char_seg[5]);imwrite("char6.jpg",char_seg[6]);//获得7个字符矩阵的相应特征矩阵vector <Mat> char_feature;char_feature.resize(7);for (int i =0;i<char_seg.size() ;++ i)features(char_seg[i], char_feature[i],5);//神经网络训练CvANN_MLP ann_classify;//对字母和数字ann_train(ann_classify,34,20,"ann_xml.xml");//输入层经元数(离线训练数据集的行数),隐藏层的神经元数,文件名字CvANN_MLP ann_classify1;//对第一个汉字进行分类建模ann_train(ann_classify1,3,20,"ann_xml_character.xml");//字符预测vector<int>  char_result;//classify(ann_classify,char_feature,char_result);char_result.resize(char_feature.size());for (int i=0;i<char_feature.size(); ++i){if (i==0)//对汉字{Mat output(1 ,34, CV_32FC1); //1*34矩阵    //ann.predict(char_feature[i] ,output);ann_classify1.predict(char_feature[i],output);//对每个字符运用ANN.predict函数得出1*类别数的数据组(数据组中是记录这个字符跟每个类别的“相似度”)Point maxLoc;double maxVal;minMaxLoc(output , 0 ,&maxVal , 0 ,&maxLoc);//找出最大概率的类别char_result[i] =  maxLoc.x;}else//对字母和数字{Mat output(1 ,34, CV_32FC1); //1*34矩阵//ann.predict(char_feature[i] ,output);ann_classify.predict(char_feature[i],output);//预测Point maxLoc;double maxVal;minMaxLoc(output , 0 ,&maxVal , 0 ,&maxLoc);char_result[i] =  maxLoc.x;}}if(plates_svm.size() != 0)  {cout << "create a image" << endl;imwrite("car_opencv_final.jpg",output_area[0]);     //正确预测的话,就只有一个结果plates_svm[0]    }else{std::cout<<"定位失败";return -1;}cout<<"该车牌后7位为:";char  s[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z'};//现在添加了京cout<<'\n';   string chinese[]={"湘","鄂","粤","甘","贵","桂","黑","沪","冀","津","京","吉","辽","鲁","蒙","闵","宁","青","琼","陕","苏","晋","皖","湘","浙","豫","渝","粤","云"};for (int w=0;w<char_result.size(); w++)   //第一位是汉字,这里没实现对汉字的预测{     if (w==0){cout<<chinese[char_result[w]];//可以对汉字京的识别cout<<'\t';}else{cout<< s[char_result[w]];cout<<'\t';}}return 0;
}

源代码和xml文件下载:https://download.csdn.net/download/guet_kite/10930196
代码大部分都是抄网上一篇文章的,文章地址我找不到了…
不过给出几个参考链接,可以看看里面的。
参考:
[1]:使用opencv的SVM和神经网络实现车牌识别
[2]:OpenCV自学笔记17. 基于SVM和神经网络的车牌识别
[3]:OpenCV实现车牌识别,OCR分割,ANN神经网络

在ARM-Linux下实现车牌识别(二)------车牌识别相关推荐

  1. ARM Linux下UPnP使用

    ARM Linux下UPnP使用   一.UPnP简介   UPnP(Universal Plug and Play)技术是一种屏蔽各种数字设备的硬件和操作系统的通信协议.它是一种数字网络中间件技术, ...

  2. linux pfn,ARM Linux下的page和pfn之间转换的宏。

    ARM Linux下的page和pfn之间转换的宏如下: 1)page_to_pfn 2)pfn_to_page 这两个宏依赖于内核编译时,选择的内存模型.在include/asm-generic/m ...

  3. linux-arm下如何开启tftp传输,arm linux 下移植busybox 的tftp

    (1)进入busybox目录,make menuconfig ,然后在networking中勾选tftp项跟tftpd项. (2)配置/etc/inetd.conf 中关于tftp的选项(此部未验证, ...

  4. [2021]Linux下C语言qrencode二维码生成库的基本使用和ARM开发板移植

    文章目录 一.前言 二.准备所用到的环境以及版本信息 1.Ubuntu和内核版本 2.gcc和g++版本 3.交叉编译gcc和g++版本 4.开发板信息 三.开发环境编译&安装qrencode ...

  5. arm linux下交叉编译valgrind工具进行内存泄露检测和性能分析

    C/C++等底层语言在提供强大功能及性能的同时,其灵活的内存访问也带来了各种纠结的问题.如果crash的地方正是内存使用错误的地方,说明你人品好.如果crash的地方内存明显不是consistent的 ...

  6. PL2303在ARM Linux下驱动的问题及解决方法

    问题描述:项目需要用ARM板驱动金笛wavecom GSM模块发短信,该GSM模块为USB接口,内部采用PL2303HX芯片转为RS232接口实现AT指令协议. 将GSM模块插入ARM板的USB口,发 ...

  7. easypr arm linux,arm linux下交叉編譯EasyPR中文車牌識別系統開發(一)

    EasyPR中文車牌識別系統開發(一),我主要介紹如何使用開源的EasyPR中文車牌識別系統,當然后面我會介紹訓練機器學習 SVM 支持向量機和 ANN 人工神經網絡模型在車牌識別的應用. 目錄: 一 ...

  8. 你知道不同U盘在ARM+Linux下的读写速率吗?

    优秀的产品离不开完善的测试,即使一个简单的USB接口也要确保稳定性及兼容性.不同的U盘在ARM+Linux板卡下的兼容性.速率怎么样呢?本文将为大家提供测试参考数据及详细测试步骤! 1. 测试准备 主 ...

  9. arm linux下看门狗应用,arm linux watchdog 看门狗

    目前手上有个项目需要设计看门狗,是arm+CPLD 方式.由于对看门狗要求很高,打算做一个双看门狗,arm CPLD互相为 对方的看门狗.理论上CPLD是不需要看门狗的,还是这么去设计了.接下来对看门 ...

  10. 4G通信模块在嵌入式ARM Linux下的应用

        4G通信模块是连接物与物的重要载体,是终端设备接入物联网的核心部件之一.4G通信模块把频率接收器和信号增幅器等部件全都整合在一起,实现了一体化.随着工业发展,嵌入式设备接入网络的需求日益增多, ...

最新文章

  1. matlab图像处理——分水岭法
  2. conda pip安装在哪里_TensorFlow 2.0 安装指南
  3. JUC多线程:创建线程的四种方式
  4. idea 启动tomcat 工程_如何在IDEA中创建web项目并且部署到Tomcat中
  5. python 艺术照片滤镜_Python实现PS滤镜Fish lens图像扭曲效果示例
  6. mysql join 与 cross join 效率_浅析Mysql Join语法以及性能优化
  7. 做生意,没亏过钱,自然也没赚过钱
  8. AbortController 中止一个或多个Web请求
  9. 用php解决钱币组合问题,关于若干数组组合的问题 PHP
  10. 网络计算机自动显示,怎么设置电脑断网后自动报警提醒?
  11. 使用Silvaco设计构建NMOS晶体管、PNP、NPN双极型晶体管并提取各项工艺及器件参数:半导体器件和工艺模拟
  12. android 汉字拼音排序,Android实现中文按拼音排序方法
  13. 虚拟手游服务器,自己搭建手机游戏服务器
  14. 全新原装 SD3337C SOP8 丝印HXN 升压DC/DC转换器恒流白光LED驱动
  15. 北京信息科技大学第十二届程序设计竞赛暨ACM选拔赛
  16. 6096. 咒语和药水的成功对数
  17. 计算机毕业设计springbootiMeli在线彩妆店铺
  18. Java简单知识点小结
  19. officemix安装 0x80091007 哈希数值不正确
  20. Html form表单验证

热门文章

  1. videoPlayer 无法播放视频
  2. 矩阵的基本运算(一)
  3. ubuntu 12.04 用后感
  4. IGN评史上最佳100 RPG
  5. 百度html删除,百度推广记录如何删除?
  6. oppo修改无线网服务器,简单小修改,你的OPPO手机wifi信号会马上提升
  7. 覆盖20个主流Niche高DA可投稿的谷歌博客外链分享
  8. (1.2)bark-ml
  9. 药到痰出——喉咙不再有痰
  10. Visual C++中error spawning cl.exe错误的两种解决方法