|
Esp32-Cam图像识别一、网页显示视频流1、Linux式例程2、MicroPython式例程步骤1、下载Thonny步骤2、烧录Esp32-Cam固件步骤3、运行相应代码3、Arduino式例程步骤1、下载Arduino步骤2、安装Esp32-Cam库步骤3、选择例程步骤4、查看运行结果二、半小时内实现图像识别1、网页视频流2、通过视频流采集目标并训练步骤1、新建Spyder工程步骤2、训练数据获取步骤3、数据处理并建立模型3、生成代码移植到Esp32-Cam(1)将HOG和RF算法转换为可以在Esp32-cam上运行的C++代码(2)创建Arduino项目工程(3)烧录到Esp32-Cam这个项目可以让你在半个小时内实现模型训练和图像识别,非常简单。开始前先放效果视频点击这里一、网页显示视频流现成资源有很多,只要稍微找下然后把程序烧录到Esp32-Cam都可以实现该功能。详细内容前往学习即可,此处不赘述。1、Linux式例程可以学习安信可官网的例程,权威。点击前往教程很详细,有Linux基础的兄弟可以尝试一下,否则就别在这个上面折腾了(比如vim编辑器使用、shell脚本使用、linux配置等,都很费时间,而且寡人也没尝试成功)2、MicroPython式例程这种方式是让Esp32-Cam具备python环境,能够运行py文件。点击前往步骤1、下载Thonny下载地址:https://thonny.org/步骤2、烧录Esp32-Cam固件使用Thonny如果烧录固件后无法显示boot.py文件的话应该是底板有问题,可以去买指定的相应底板,但其实使用USB转ttl,杜邦线对应接5V、GND、TXD和RXD就可以了。步骤3、运行相应代码importsocketimportnetworkimportcameraimporttime#连接wifiwlan=network.WLAN(network.STA_IF)wlan.active(True)ifnotwlan.isconnected():print('connectingtonetwork...')wlan.connect('dongfeiqiu','wangmingdong1225')whilenotwlan.isconnected():passprint('网络配置:',wlan.ifconfig())#摄像头初始化try:camera.init(0,format=camera.JPEG)exceptExceptionase:camera.deinit()camera.init(0,format=camera.JPEG)#其他设置:#上翻下翻camera.flip(1)#左/右camera.mirror(1)#分辨率camera.framesize(camera.FRAME_HVGA)#选项如下:#FRAME_96X96FRAME_QQVGAFRAME_QCIFFRAME_HQVGAFRAME_240X240#FRAME_QVGAFRAME_CIFFRAME_HVGAFRAME_VGAFRAME_SVGA#FRAME_XGAFRAME_HDFRAME_SXGAFRAME_UXGAFRAME_FHD#FRAME_P_HDFRAME_P_3MPFRAME_QXGAFRAME_QHDFRAME_WQXGA#FRAME_P_FHDFRAME_QSXGA#有关详细信息,请查看此链接:https://bit.ly/2YOzizz#特效camera.speffect(camera.EFFECT_NONE)#选项如下:#效果\无(默认)效果\负效果\BW效果\红色效果\绿色效果\蓝色效果\复古效果#EFFECT_NONE(default)EFFECT_NEG\EFFECT_BW\EFFECT_RED\EFFECT_GREEN\EFFECT_BLUE\EFFECT_RETRO#白平衡#camera.whitebalance(camera.WB_HOME)#选项如下:#WB_NONE(default)WB_SUNNYWB_CLOUDYWB_OFFICEWB_HOME#饱和camera.saturation(0)#-2,2(默认为0).-2灰度#-2,2(default0).-2grayscale#亮度camera.brightness(0)#-2,2(默认为0).2亮度#-2,2(default0).2brightness#对比度camera.contrast(0)#-2,2(默认为0).2高对比度#-2,2(default0).2highcontrast#质量camera.quality(10)#10-63数字越小质量越高#socketUDP的创建s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)try:whileTrue:buf=camera.capture()#获取图像数据s.sendto(buf,("192.168.31.53",9090))#向服务器发送图像数据time.sleep(0.1)except:passfinally:camera.deinit()123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384853、Arduino式例程这个也是我发现最简单的实现例程,而且资源也多,涉及的语言主要是C++。点击前往步骤1、下载Arduino下载地址:点击前往步骤2、安装Esp32-Cam库方法一:在IDE安装。(1).文件→首选项→附加开发板管理器网址,修改网址为https://arduino.esp8266.com/stable/package_esp8266com_index.jsonhttps://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json12(2).工具→开发板→开发板管理器,搜索esp32,点击安装即可方法二:github下载zip压缩包作为库下载地址:点击前往下载zip压缩包完成后,项目→包含库→添加.ZIP库步骤3、选择例程工具→开发板→esp32→AIThinkerESP32-CAM在如下位置里边填充wifi和密码constchar*ssid="Yourwifiname";constchar*password="wifipassword";12完整代码截取如下#include"esp_camera.h"#include////WARNING!!!MakesurethatyouhaveeitherselectedESP32WroverModule,//oranotherboardwhichhasPSRAMenabled////Selectcameramodel//#defineCAMERA_MODEL_WROVER_KIT//#defineCAMERA_MODEL_ESP_EYE//#defineCAMERA_MODEL_M5STACK_PSRAM//#defineCAMERA_MODEL_M5STACK_WIDE#defineCAMERA_MODEL_AI_THINKER#include"camera_pins.h"constchar*ssid="Yourwifiname";constchar*password="wifipassword";voidstartCameraServer();voidsetup(){Serial.begin(115200);Serial.setDebugOutput(true);Serial.println();camera_config_tconfig;config.ledc_channel=LEDC_CHANNEL_0;config.ledc_timer=LEDC_TIMER_0;config.pin_d0=Y2_GPIO_NUM;config.pin_d1=Y3_GPIO_NUM;config.pin_d2=Y4_GPIO_NUM;config.pin_d3=Y5_GPIO_NUM;config.pin_d4=Y6_GPIO_NUM;config.pin_d5=Y7_GPIO_NUM;config.pin_d6=Y8_GPIO_NUM;config.pin_d7=Y9_GPIO_NUM;config.pin_xclk=XCLK_GPIO_NUM;config.pin_pclk=PCLK_GPIO_NUM;config.pin_vsync=VSYNC_GPIO_NUM;config.pin_href=HREF_GPIO_NUM;config.pin_sscb_sda=SIOD_GPIO_NUM;config.pin_sscb_scl=SIOC_GPIO_NUM;config.pin_pwdn=PWDN_GPIO_NUM;config.pin_reset=RESET_GPIO_NUM;config.xclk_freq_hz=20000000;config.pixel_format=PIXFORMAT_JPEG;//initwithhighspecstopre-allocatelargerbuffersif(psramFound()){config.frame_size=FRAMESIZE_UXGA;config.jpeg_quality=10;config.fb_count=2;}else{config.frame_size=FRAMESIZE_SVGA;config.jpeg_quality=12;config.fb_count=1;}#ifdefined(CAMERA_MODEL_ESP_EYE)pinMode(13,INPUT_PULLUP);pinMode(14,INPUT_PULLUP);#endif//camerainitesp_err_terr=esp_camera_init(&config);if(err!=ESP_OK){Serial.printf("Camerainitfailedwitherror0x%x",err);return;}sensor_t*s=esp_camera_sensor_get();//initialsensorsareflippedverticallyandcolorsareabitsaturatedif(s->id.PID==OV3660_PID){s->set_vflip(s,1);//flipitbacks->set_brightness(s,1);//uptheblightnessjustabits->set_saturation(s,-2);//lowerthesaturation}//dropdownframesizeforhigherinitialframerates->set_framesize(s,FRAMESIZE_QVGA);#ifdefined(CAMERA_MODEL_M5STACK_WIDE)s->set_vflip(s,1);s->set_hmirror(s,1);#endifWiFi.begin(ssid,password);while(WiFi.status()!=WL_CONNECTED){delay(500);Serial.print(".");}Serial.println("");Serial.println("WiFiconnected");startCameraServer();Serial.print("CameraReady!Use'http://");Serial.print(WiFi.localIP());Serial.println("'toconnect");}voidloop(){//putyourmaincodehere,torunrepeatedly:delay(10000);}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106步骤4、查看运行结果工具→串口监视器,然后按下esp32-cam的复位键复制网址在网页打开,即可看摄像头实时内容了二、半小时内实现图像识别1、网页视频流和前面的Arduino例程相似,但包含的库不是官方库,而是这个:点击这里下载该zip库后在IDE操作包含该库,然后复制下面代码作为一个新工程ino文件。注意:要配置自己的板件,然后改成自己的wifi和密码#include"eloquent.h"#include"eloquent/networking/wifi.h"#include"eloquent/vision/camera/esp32/webserver.h"//把'm5wide'替换成自己的模块,//支持的模块有'aithinker','eye','m5stack','m5wide','wrover'#include"eloquent/vision/camera/aithinker.h"//我用的是aithinkervoidsetup(){Serial.begin(115200);delay(2000);camera.jpeg();camera.qqvga();//改成自己的wifi和密码while(!wifi.connectTo("Abc","12345678"))Serial.println("CannotconnecttoWiFi");while(!camera.begin())Serial.println("Cannotconnecttocamera");webServer.start();Serial.print("Camerawebserverstartedathttp://");Serial.println(WiFi.localIP());}voidloop(){//donothing}1234567891011121314151617181920212223编译烧到esp32-cam板子上后打开串口监视器,获取网址(我的是192.168.1.103),然后在网页打开即可,和常规Arduino的视频流例程差不多。视频窗口设这么小是为了让视频更加流畅。2、通过视频流采集目标并训练训练环境是Python,我这边推荐Anaconda简单介绍就是:数据可视化+JupyterNotebook+Spyder下载用不了多长时间的,然后我们只需要用其中的IDE:Spyder下载好之后安装everywhereml包,打开AnacondaPowershellPrompt输入以下指令,already表示包已经安装好了pipinstalleverywhereml>=0.2.191步骤1、新建Spyder工程project->newproject然后把学习训练模型的Python工程解压添加到工程里,点击获取Python工程然后打开Spyder软件如图显示,左边工程文件栏目里就会显示Python工程,此外派上用场的还有交互界面和数据可视化显示界面步骤2、训练数据获取复制以下代码到交互界面并回车,从视频流中截取目标图片作为模型数据支撑fromloggingimportbasicConfig,INFOfromeverywhereml.dataimportImageDatasetfromeverywhereml.data.collectimportMjpegCollector#给将要存放数据的文件夹命名base_folder='Images_Data'#视频流显示的那个网页地址IP_ADDRESS_OF_ESP='http://192.168.1.103'basicConfig(level=INFO)try:image_dataset=ImageDataset.from_nested_folders(name='Dataset',base_folder=base_folder)exceptFileNotFoundError:mjpeg_collector=MjpegCollector(address=IP_ADDRESS_OF_ESP)image_dataset=mjpeg_collector.collect_many_classes(dataset_name='Dataset',base_folder=base_folder,duration=30)print(image_dataset)123456789101112131415161718192021然后就会弹出让你给创建的类命名,我先什么都不识别所以命名none然后回车,如下图所示之后会显示提示拍了1272张图作为模型训练基础,并询问该类是否okINFO:root:Captured1272imagesIsthisclassok?(y|n)12接着输入y回车,如果是第一次的话会提示建立文件夹Images_Data存数据INFO:root:creatingD:\Esp_Cam\Spyder_Demo\Esp32_Cam\Images_DatafolderINFO:root:creatingD:\Esp_Cam\Spyder_Demo\Esp32_Cam\Images_Data\nonefolderWhichclassareyougoingtocapture?(leaveemptytoexit)123打开对应文件夹就会发现里边存了拍下来的图片数据同样的,我训练了pen、napkin如果不想添加了,不用输入直接回车Whichclassareyougoingtocapture?(leaveemptytoexit)Areyousureyouwanttoexit?(y|n)12然后输入y回车退出,这时候就会显示所训练的类ImageDataset[Dataset](num_images=3704,num_labels=3,labels=['napkin','none','pen'])1步骤3、数据处理并建立模型步骤2获取了纸巾、笔、空白的情况下各一千多张图片作为数据支撑首先对图片进行灰化在交互界面执行image_dataset=image_dataset.gray().uint8()1可以在交互界面执行以下代码预览数据处理情况image_dataset.preview(samples_per_class=10,rows_per_class=2,figsize=(20,10),cmap='gray')1然后使用定向梯度直方图算法进行处理定向梯度直方图(HistogramofOrientedGradients,简称HOG),该算法是轻量级的很适合Esp32-cam使用。在交互界面执行以下代码fromeverywhereml.preprocessing.image.object_detectionimportHogPipelinefromeverywhereml.preprocessing.image.transformimportResizepipeline=HogPipeline(transforms=[Resize(width=40,height=30)#此处的分辨率会影响处理时间和模型建立的准确度,可自行调整])feature_dataset=pipeline.fit_transform(image_dataset)feature_dataset.describe()123456789接着输出由特征向量组成的数据集print(pipeline)1如果想看所提取的特征量信息情况,可以绘制配对图(pairplot)直观感受数据feature_dataset.plot.features_pairplot(n=200,k=8)1可以直观的看到,这3个类(none、napkin、pen)的聚集性质良好,但在某种程度上彼此是有混合的情况。使用降维算法进一步优化使用的降维算法是统一流形逼近与投影(UniformManifoldApproximationandProjection,简称UMAP)feature_dataset.plot.umap()1分析点聚集性质可知,1(none)的模型最理想,0(napkin)和2(pen)的模型相对比较差。总的来说,也算是能够用来表征我们的数据了。最后训练分类器完成模型建立使用的建模方法叫随机森林(RandomForest,简称RF)fromeverywhereml.sklearn.ensembleimportRandomForestClassifierforiinrange(10):clf=RandomForestClassifier(n_estimators=5,max_depth=10)train,test=feature_dataset.split(test_size=0.4,random_state=i)clf.fit(train)print('Scoreontestset:%.2f'%clf.score(test))clf.fit(feature_dataset)1234567现在,我们已经训练并且建好模型了3、生成代码移植到Esp32-Cam(1)将HOG和RF算法转换为可以在Esp32-cam上运行的C++代码HOG算法获取特征向量数据集print(pipeline.to_arduino_file(filename='path-to-sketch/HogPipeline.h',instance_name='hog'))1234RF算法训练分类器print(clf.to_arduino_file(filename='path-to-sketch/HogClassifier.h',instance_name='classifier',class_map=feature_dataset.class_map))12345这时候就会生成两个.h文件在path-to-sketch/目录下(2)创建Arduino项目工程ino文件里替换成以下代码#include"eloquent.h"#include"eloquent/print.h"#include"eloquent/tinyml/voting/quorum.h"//支撑的有'aithinker','eye','m5stack','m5wide','wrover'#include"eloquent/vision/camera/aithinker.h"//我用的是aithinker#include"HogPipeline.h"//Spyder里生成的#include"HogClassifier.h"//Spyder里生成的Eloquent::TinyML::Voting:uorumquorum;voidsetup(){Serial.begin(115200);delay(3000);Serial.println("Begin");camera.qqvga();camera.grayscale();while(!camera.begin())Serial.println("Cannotinitcamera");}voidloop(){if(!camera.capture()){Serial.println(camera.getErrorMessage());delay(1000);return;}hog.transform(camera.buffer);uint8_tprediction=classifier.predict(hog.features);int8_tstablePrediction=quorum.vote(prediction);if(quorum.isStable()){eloquent::print::printf(Serial,"Stableprediction:%s\t(DSP:%dms,Classifier:%dus)\n",classifier.getLabelOf(stablePrediction),hog.latencyInMillis(),classifier.latencyInMicros());}camera.free();}12345678910111213141516171819202122232425262728293031323334353637找到前面生产的两个.h文件,然后包含进工程里(把两个.h文件复制到工程里边)(3)烧录到Esp32-Cam
|
|