700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > opencv人脸识别以及自定义物体识别系统

opencv人脸识别以及自定义物体识别系统

时间:2022-05-16 16:48:30

相关推荐

opencv人脸识别以及自定义物体识别系统

目录

一、简介:

二、软硬件应用:

三、模块介绍:

(一)人脸识别:

(二)、自定义物体识别:

(三)、图片展示:

(四)、python框架:

(五)、执行器--单片机:

四、效果展示:

五、总结 :

一、简介:

现如今机器视觉的应用可谓是遍地开花,人脸识别更可谓是随处可见。opencv作为视觉库被普遍应用,此项目正是基于opencv设计的一个既可以识别人脸也可以识别自定义物体的系统。

二、软硬件应用:

pycharm(python版本3.10)

opencv-contrib-python()

opencv3.4.8(这个自带训练分类器的exe--opencv_createsamples.exe,opencv_traincascade.exe)

kile5

正点原子STM32F103mini

pc(在我的笔记本进行项目)

摄像头(我的笔记本上没有内置摄像头,所以用了一个外置摄像头)

三、模块介绍:

(一)人脸识别:

这个项目中我分别体验了face_recognition和opencv自带的Haar特征分类器。

对于face_recognition:单个人的时候face_recognition准确度很可靠,但是有一个明显的缺点就是太慢(可能是我代码的问题),检测的帧率只有3次/秒。如果检测多个人,并且两个人很相似时准确度就有点说不过去了(血和泪的经历,项目写到一半发现实在太慢,才决定狼狈地重写人脸识别代码)。

对于opencv自带的Haar特征分类器:准确度虽不如face_recognition但还可以,他的速度很快,我的摄像头时30帧的,它检测的帧率可以达到20次/秒(我已经感到满足了)

人脸识别部分使用了opencv自带的Haar特征分类器--haarcascade_frontalface_alt2.xml ,相较于其他几个,这个我感觉很好。下面是我的代码,

check_time=0def face_Detector(img,ser):gary=cv.cvtColor(img,cv.COLOR_BGR2GRAY)face_detect=cv.CascadeClassifier('C:/opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')#haarcascade_frontalface_default.xmlface=face_detect.detectMultiScale(gary,1.1,5,cv.CASCADE_SCALE_IMAGE,(100,100),(300,300))for x,y,w,h in face:cv.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2)ids,confidence = recognizer.predict(gary[y:y+h,x:x+w])if confidence<80:global check_timecheck_time += 1if check_time > 36:check_time = 0# save人员信息save(name[ids-1])ser.write('1'.encode())cv.putText(img, name[ids-1]+str(confidence), (x + 10, y - 10), cv.FONT_HERSHEY_COMPLEX, 0.75, (0, 255, 0), 1)else:ser.write('0'.encode())cv.putText(img, 'Unknown' , (x + 10, y - 10), cv.FONT_HERSHEY_COMPLEX, 0.75, (0, 255, 0),1)

这个过程中遇到了pycharm中opencv不提示代码的问题。

整了半天,才在这个大佬的文章中找到解决方案,/sQdN3

(二)、自定义物体识别:

在这个模块中我使用了自己训练的分类器

这是我的正样本 :

这是我的负样本 :

这是我最后的成果cascade.xml文件,也就是可以用的分类器:

自己训练分类器时,我用opencv4.5.3版本,借鉴网上网上大佬发的文章自己实践,结果发现只有opencv_createsamples.exe可以勉强编译出来,但opencv_traincascade.exe确实编译不出来,为此我不得不又下载了opencv3.4.8的版本,使用其自带的那两个可执行程序进行训练。

我使用了240张正样本,720张负样本,(正:负)==(1:3)(负样本一定要比正样本多,正负样本数量比例可以在1:3到1:5之间)。虽说样本数量不是很多,但效果还能接受。

下面是我的正样本描述文件,说一下文件里面1 0 0 40 40 后缀的含义。

我的正样本图片统一处理成了40*40,所以这里的1是指正样本图片中只有一个自定义的物体, 0 0 40 40的意思是覆盖整张图片

网上相关自己训练分类器的文章很多,具体的实现过程我也不在此过多地赘述了。

分类器训练完了之后,就可以直接使用了,下面展示我的代码:

def object_Detector(image):gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)bottle_cascade = cv.CascadeClassifier('C:/opencv/Object/xml/cascade.xml')bottle = bottle_cascade.detectMultiScale(gray,1.1,5,cv.CASCADE_SCALE_IMAGE,(50,50),(300,300))num = len(bottle)for x,y,w,h in bottle :cv.circle(image,center=(x+w//2,y+h//2),radius=w//2,color=(0,255,0),thickness=1)cv.putText(image,str(num),(20,20),cv.FONT_HERSHEY_COMPLEX, 0.75, (0, 0, 255),1)

(三)、图片展示:

由于项目要求,我的项目中opencv处理后的图片需要再我的单片机上显示,但这方面有点力不从心,所以我使用了socket实现opencv处理后的图片从客户端上传用服务端接受并展示。

这是客户端代码,从opencv中不断获取处理后的图片,进行编码、发送

#从客户端向服务端发送处理后的re_img图片def SendVideo():global re_img, ret, state# IP地址和端口号IP = '127.0.0.1'PORT = 8002try:# 实例化:AF_INET:ip协议,SOCK_STREAM:tcp协议dataSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 开始连接dataSocket.connect((IP, PORT))# 错误处理except socket.error as msg:print(msg)sys.exit(1)# 压缩参数,对于jpeg来说,15代表图像质量,越高代表图像质量越好为 0-100,默认95encod_param = [int(cv.IMWRITE_JPEG_QUALITY), 15]while ret:# 停止0.05秒,防止发送过快服务的处理不过来time.sleep(0.05)# 将图片格式编码成流数据,方便网络传输# result:True/False# imgencode:numpy.ndarray类型的图像文件内容result, imgencode = cv.imencode('.jpg', re_img,encod_param)# 建立矩阵data = np.array(imgencode)# 将numpy矩阵转换成字符形式,以便在网络中传输stringData = data.tobytes()# ljust() 方法返回一个原字符串左对齐,并使用空格填充至指定长度的新字符串dataSocket.send(str.encode(str(len(stringData)).ljust(16)))# 发送数据dataSocket.send(stringData)if state == True:breakdataSock.close()

这是服务端代码,不断从客户端里获取流数据,再进行一系列的转化、解码,最后展示到笔记本上

def ReceiveVideo():global state# ip地址'0.0.0.0'绑定本机所有IP地址IP = '0.0.0.0'# 端口号PORT = 8002# 实例化listenSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 进行IP和端口号的绑定# 元组方式写入# 可以啊address=('0.0.0.0',50000)listenSocket.bind((IP, PORT))# 最多接受1个客户端listenSocket.listen(1)# 消息边界def recallbyt(sock, cnt):byt = b'' # byt是一个byte类型,用于接受流数据。(传输的数据就是byte类型的)while cnt:newbyt = sock.recv(cnt)if not newbyt: return Nonebyt += newbytcnt -= len(newbyt)return bytdataSocket, addr = listenSocket.accept()print('连接到:' + str(addr))while True:# 获得图片文件长度,16代表获取长度length = recallbyt(dataSocket, 16)# 根据获取的文件长度,获取图片文件StringData = recallbyt(dataSocket, int(length))# 将流数据转换成numpy 1维数组数据data = np.frombuffer(StringData, np.uint8)# 将数组数据进行解码,形成图像deco_img = cv.imdecode(data, cv.IMREAD_COLOR)cv.imshow('SERVER', deco_img)# 按键检测if cv.waitKey(1) == 81:dataSocket.close()state = TruelistenSocket.close()cv.destroyAllWindows()break

(四)、python框架:

整体采用了多线程的运行方式,并且在最开始通过一个判断来选择进行人脸识别模式还是自定义模块识别模式

thread_Rec = threading.Thread(target=ReceiveVideo)thread_Sen = threading.Thread(target=SendVideo)thread_take = threading.Thread(target=teak_img)'''*************************模式判断*************************'''mode = input('请选择模式:')if mode == '1':thread_face = threading.Thread(target=face_det)thread_face.start()elif mode == '2':thread_obj = threading.Thread(target=object_det)thread_obj.start()'''**************************************************'''thread_take.start()thread_Rec.start()thread_Sen.start()

因为想在一个python程序上就集成两个模式,对多线程的学习还没有很深入所以不得已做成这样的判断,来识别需要运行的模式

(五)、执行器--单片机:

项目中,单片机通过串口与python程序相通,进行判断是否是数据库中的人,从而进行显示通过或失败。

void USART2_IRQHandler(void){u8 i,ret;if (USART_GetITStatus (USART2,USART_IT_RXNE )){ret = USART_ReceiveData(USART2);if (ret == '1' && (sate == 'N' || sate == 'E')){LCD_Clear (WHITE);POINT_COLOR=GREEN;for(i=0;i<8;i++){LCD_Draw_Circle( 120, 160, 102-i);}LCD_Fill( 110, 120 , 130,220 , GREEN);for (i=0;i<25;i++){LCD_DrawLine(80+i, 160,120, 110+i);}for (i=0;i<25;i++){LCD_DrawLine(160-i, 160,120, 110+i);}POINT_COLOR=BLACK;LCD_ShowString (65,20,200,16,16,"KnwonPass");LCD_ShowString(80,280,200,16,16,"/7/24");sate = 'Y';}else if (ret == '0' && (sate == 'Y' || sate == 'E')){LCD_Clear (WHITE);POINT_COLOR=RED;for(i=0;i<8;i++){LCD_Draw_Circle( 120, 160, 102-i);}for (i=0;i<25;i++){LCD_DrawLine(70+i, 210,146+i, 110);}for (i=0;i<25;i++){LCD_DrawLine(70+i, 110,146+i, 210);}LCD_ShowString (65,20,200,16,16,"Unknown fail");LCD_ShowString(80,280,200,16,16,"/7/24");sate = 'N';}}}

四、效果展示:

LCD上其实还有一些字 ,只是亮度太高,看不见了

五、总结 :

这次的项目由于开始后的前两天一直在整face_recognition的代码到后来转到opencv自带的Haar特征分类器时有点“狼狈”,时间很紧张,来不及做其他的执行器模块。

这个项目对我来说最难的是画面展示的部分,因为电脑和单片机之间的通信我不太熟悉,问了一下我的师兄其他方法,随后了解到flask可以将视频传输到网页上,但是整了两天也没整会如何将网页上的视频流信息捕捉回来,到了结束的前一天才了解到socket可以进行服务端和客户端的信息传输,就赶紧听课、学习、写代码。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。