Opencv实现眼睛控制鼠标的案例分析
这篇文章主要讲解了“Opencv实现眼睛控制鼠标的案例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Opencv实现眼睛控制鼠标的案例分析”吧!
在开始项目之前,我们需要引入第三方库。
#Formonitoringwebcameraandperformingimageminipulationsimportcv2#Forperformingarrayoperationsimportnumpyasnp#Forcreatingandremovingdirectoriesimportosimportshutil#Forrecognizingandperformingactionsonmousepressesfrompynput.mouseimportListener
首先让我们了解一下Pynput的Listener工作原理。pynput.mouse.Listener创建一个后台线程,该线程记录鼠标的移动和鼠标的点击。这是一个简化代码,当你们按下鼠标时,它会打印鼠标的坐标:
frompynput.mouseimportListenerdefon_click(x,y,button,pressed):"""Args:x:thex-coordinateofthemousey:they-coordinateofthemousebutton:1or0,dependingonright-clickorleft-clickpressed:1or0,whetherthemousewaspressedorreleased"""ifpressed:print(x,y)withListener(on_click=on_click)aslistener:listener.join()
现在,为了实现我们的目的,让我们扩展这个框架。但是,我们首先需要编写裁剪眼睛边界框的代码。我们稍后将在on_click函数内部调用此函数。我们使用Haar级联对象检测来确定用户眼睛的边界框。你们可以在此处下载检测器文件,让我们做一个简单的演示来展示它是如何工作的:
importcv2#Loadthecascadeclassifierdetectionobjectcascade=cv2.CascadeClassifier("haarcascade_eye.xml")#Turnonthewebcameravideo_capture=cv2.VideoCapture(0)#Readdatafromthewebcamera(gettheframe)_,frame=video_capture.read()#Converttheimagetograyscalegray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)#Predicttheboundingboxoftheeyesboxes=cascade.detectMultiScale(gray,1.3,10)#Filteroutimagestakenfromabadanglewitherrors#Wewanttomakesurebotheyesweredetected,andnothingelseiflen(boxes)==2:eyes=[]forboxinboxes:#Gettherectangleparametersforthedetectedeyex,y,w,h=box#Croptheboundingboxfromtheframeeye=frame[y:y+h,x:x+w]#Resizethecropto32x32eye=cv2.resize(eye,(32,32))#Normalizeeye=(eye-eye.min())/(eye.max()-eye.min())#Furthercroptojustaroundtheeyeballeye=eye[10:-10,5:-5]#Scalebetween[0,255]andconverttointdatatypeeye=(eye*255).astype(np.uint8)#Addthecurrenteyetothelistof2eyeseyes.append(eye)#Concatenatethetwoeyeimagesintooneeyes=np.hstack(eyes)
现在,让我们使用此知识来编写用于裁剪眼睛图像的函数。首先,我们需要一个辅助函数来进行标准化:
defnormalize(x):minn,maxx=x.min(),x.max()return(x-minn)/(maxx-minn)
这是我们的眼睛裁剪功能。如果发现眼睛,它将返回图像。否则,它返回None:
defscan(image_size=(32,32)):_,frame=video_capture.read()gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)boxes=cascade.detectMultiScale(gray,1.3,10)iflen(boxes)==2:eyes=[]forboxinboxes:x,y,w,h=boxeye=frame[y:y+h,x:x+w]eye=cv2.resize(eye,image_size)eye=normalize(eye)eye=eye[10:-10,5:-5]eyes.append(eye)return(np.hstack(eyes)*255).astype(np.uint8)else:returnNone
现在,让我们来编写我们的自动化,该自动化将在每次按下鼠标按钮时运行。(假设我们之前已经root在代码中将变量定义为我们要存储图像的目录):
defon_click(x,y,button,pressed):#IftheactionwasamousePRESS(notaRELEASE)ifpressed:#Croptheeyeseyes=scan()#IfthefunctionreturnedNone,somethingwentwrongifnoteyesisNone:#Savetheimagefilename=root+"{}{}{}.jpeg".format(x,y,button)cv2.imwrite(filename,eyes)
现在,我们可以回忆起pynput的实现Listener,并进行完整的代码实现:
importcv2importnumpyasnpimportosimportshutilfrompynput.mouseimportListenerroot=input("Enterthedirectorytostoretheimages:")ifos.path.isdir(root):resp=""whilenotrespin["Y","N"]:resp=input("Thisdirectoryalreadyexists.Ifyoucontinue,thecontentsoftheexistingdirectorywillbedeleted.Ifyouwouldstillliketoproceed,enter[Y].Otherwise,enter[N]:")ifresp=="Y":shutil.rmtree(root)else:exit()os.mkdir(root)#Normalizationhelperfunctiondefnormalize(x):minn,maxx=x.min(),x.max()return(x-minn)/(maxx-minn)#Eyecroppingfunctiondefscan(image_size=(32,32)):_,frame=video_capture.read()gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)boxes=cascade.detectMultiScale(gray,1.3,10)iflen(boxes)==2:eyes=[]forboxinboxes:x,y,w,h=boxeye=frame[y:y+h,x:x+w]eye=cv2.resize(eye,image_size)eye=normalize(eye)eye=eye[10:-10,5:-5]eyes.append(eye)return(np.hstack(eyes)*255).astype(np.uint8)else:returnNonedefon_click(x,y,button,pressed):#IftheactionwasamousePRESS(notaRELEASE)ifpressed:#Croptheeyeseyes=scan()#IfthefunctionreturnedNone,somethingwentwrongifnoteyesisNone:#Savetheimagefilename=root+"{}{}{}.jpeg".format(x,y,button)cv2.imwrite(filename,eyes)cascade=cv2.CascadeClassifier("haarcascade_eye.xml")video_capture=cv2.VideoCapture(0)withListener(on_click=on_click)aslistener:listener.join()
运行此命令时,每次单击鼠标(如果两只眼睛都在视线中),它将自动裁剪网络摄像头并将图像保存到适当的目录中。图像的文件名将包含鼠标坐标信息,以及它是右击还是左击。
这是一个示例图像。在此图像中,我在分辨率为2560x1440的监视器上在坐标(385,686)上单击鼠标左键:
级联分类器非常准确,到目前为止,我尚未在自己的数据目录中看到任何错误。现在,让我们编写用于训练神经网络的代码,以给定你们的眼睛图像来预测鼠标的位置。
importnumpyasnpimportosimportcv2importpyautoguifromtensorflow.keras.modelsimport*fromtensorflow.keras.layersimport*fromtensorflow.keras.optimizersimport*
现在,让我们添加级联分类器:
cascade=cv2.CascadeClassifier("haarcascade_eye.xml")video_capture=cv2.VideoCapture(0)
正常化:
defnormalize(x):minn,maxx=x.min(),x.max()return(x-minn)/(maxx-minn)
捕捉眼睛:
defscan(image_size=(32,32)):_,frame=video_capture.read()gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)boxes=cascade.detectMultiScale(gray,1.3,10)iflen(boxes)==2:eyes=[]forboxinboxes:x,y,w,h=boxeye=frame[y:y+h,x:x+w]eye=cv2.resize(eye,image_size)eye=normalize(eye)eye=eye[10:-10,5:-5]eyes.append(eye)return(np.hstack(eyes)*255).astype(np.uint8)else:returnNone
让我们定义显示器的尺寸。你们必须根据自己的计算机屏幕的分辨率更改以下参数:
#Notethatthereareactually2560x1440pixelsonmyscreen#Iamsimplyrecordingoneless,sothatwhenwedividebythese#numbers,wewillnormalizebetween0and1.Notethatmouse#coordinatesarereportedstartingat(0,0),not(1,1)width,height=2559,1439
现在,让我们加载数据(同样,假设你们已经定义了root)。我们并不在乎是单击鼠标右键还是单击鼠标左键,因为我们的目标只是预测鼠标的位置:
filepaths=os.listdir(root)X,Y=[],[]forfilepathinfilepaths:x,y,_=filepath.split('')x=float(x)/widthy=float(y)/heightX.append(cv2.imread(root+filepath))Y.append([x,y])X=np.array(X)/255.0Y=np.array(Y)print(X.shape,Y.shape)
让我们定义我们的模型架构:
model=Sequential()model.add(Conv2D(32,3,2,activation='relu',input_shape=(12,44,3)))model.add(Conv2D(64,2,2,activation='relu'))model.add(Flatten())model.add(Dense(32,activation='relu'))model.add(Dense(2,activation='sigmoid'))model.compile(optimizer="adam",loss="mean_squared_error")model.summary()
这是我们的摘要:
接下来的任务是训练模型。我们将在图像数据中添加一些噪点:
epochs=200forepochinrange(epochs):model.fit(X,Y,batch_size=32)
现在让我们使用我们的模型来实时移动鼠标。请注意,这需要大量数据才能正常工作。但是,作为概念证明,你们会注意到,实际上只有200张图像,它确实将鼠标移到了你们要查看的常规区域。当然,除非你们拥有更多的数据,否则这是不可控的。
whileTrue:eyes=scan()ifnoteyesisNone:eyes=np.expand_dims(eyes/255.0,axis=0)x,y=model.predict(eyes)[0]pyautogui.moveTo(x*width,y*height)
这是一个概念证明的例子。请注意,在进行此屏幕录像之前,我们只训练了很少的数据。这是我们的鼠标根据眼睛自动移动到终端应用程序窗口的视频。就像我说的那样,这很容易,因为数据很少。有了更多的数据,它有望稳定到足以以更高的特异性进行控制。仅用几百张图像,你们就只能将其移动到注视的整个区域内。另外,如果在整个数据收集过程中,你们在屏幕的特定区域(例如边缘)都没有拍摄任何图像,则该模型不太可能在该区域内进行预测。
感谢各位的阅读,以上就是“Opencv实现眼睛控制鼠标的案例分析”的内容了,经过本文的学习后,相信大家对Opencv实现眼睛控制鼠标的案例分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。