介绍最近在目标检测中对小东西的研究。需要抓取桌面的实时图像,获取图像后进行检测,达到实时桌面目标检测的目的,所以写了一段小代码来实现这个功能,实际测试速度是非常快,满足我的需求。特此记录。代码importargparseimporttimeimportcv2importkeyboardimportmssimportnumpyasnpimportwin32com.clientimportwin32conimportwin32guiclassScreenCapture:"""parameters----------screen_frame:Tuple[int,int]屏幕宽高,分别为x,y区域:Tuple[float,float]实际截图范围,分别为x,y,(1.0,1.0)表示全屏检测,检测范围越低,检测范围越小(始终保持屏幕中心为中心)window_name:str显示窗口名称exit_key:int结束窗口退出键值为键盘上每个键对应的ASCII码值,默认为ESC键"""def__init__(self,screen_frame=(1920,1080),region=(0.5,0.5),window_name='test',exit_key=0x1B):self.parser=argparse.ArgumentParser()self.parser.add_argument('--region',type=tuple,default=region,帮助='截屏范围;分别为x,y,(1.0,1.0)表示全屏检测,检测范围越低,smaller检测范围(始终保持屏幕中心为中心)')self.parser_args=self.parser.parse_args()self.cap=mss.mss(mon=-1,optimize=True)#示例mss,并使用高效模式self.screen_width=screen_frame[0]#屏幕的宽self.screen_height=screen_frame[1]#屏幕的高self.mouse_x,self.mouse_y=self.screen_width//2,self.screen_height//2#屏幕中心点坐标#截图区域self.GAME_WIDTH,self.GAME_HEIGHT=int(self.screen_width*self.parser_args.region[0]),int(self.screen_height*self.parser_args.region[1])#宽高self.GAME_LEFT,self.GAME_TOP=int(0+self.screen_width//2*(1.-self.parser_args.region[0])),int(0+1080//2*(1.-self.parser_args.region[1]))#原点self.RESZIE_WIN_WIDTH,self.RESIZE_WIN_HEIGHT=self.screen_width//4,self.screen_height//4#显示窗口大self.mointor={'left':self.GAME_LEFT,'top':self.GAME_TOP,'width':self.GAME_WIDTH,'height':self.GAME_HEIGHT}self.window_name=window_nameself.Exit_key=exit_keyself.img=Nonedefgrab_screen_mss(self,monitor):#cap.grab截取图片,np.array将图片转化为数组,cvtColor将BRGA转化为BRG,去除透明通道返回cv2.cvtColor(np.array(self.cap.grab(monitor)),cv2.COLOR_BGRA2BGR)defupdate_img(self,img):self.img=imgdefget_img(self):returnself.imgdefrun(self):SetForegroundWindow_f=0#判断是否设置置顶窗口whileTrue:#判断是否按下ctrl+U窗口总是Topifkeyboard.is_pressed('ctrl+U'):whilekeyboard.is_pressed('ctrl+U'):continueifSetForegroundWindow_f==0:SetForegroundWindow_f=1time.sleep(1)continueelse:SetForegroundWindow_f=0如果是自己。imgisNone:img=self.grab_screen_mss(self.mointor)cv2.namedWindow(self.window_name,cv2.WINDOW_NORMAL)#cv2.WINDOW_NORMAL根据窗口大小设置图像大小cv2.resizeWindow(self.window_name,self.RESZIE_WIN_WIDTH,self.调整大小_WIN_HEIGHT)cv2.imshow(self.window_name,img)如果SetForegroundWindow_f==1:shell=win32com.client.Dispatch("WScript.Shell")shell.SendKeys('%')win32gui.SetForegroundWindow(win32gui.FindWindow(None,self.window_name))win32gui.ShowWindow(win32gui.FindWindow(None,self.window_name),win32con.SW_SHOW)ifcv2.waitKey(1)&0XFF==self.Exit_key:#Default:ESCcv2.destroyAllWindows()exit(《完》)代码讲解功能实现思路主要是利用mss库进行截图,利用opencv库进行图像显示和处理。首先使用argparse库解析传入的参数,设置检测范围的大小。然后,使用mss库实例化一个屏幕截图对象cap。接下来设置屏幕的宽高,计算屏幕中心点的坐标。之后根据传入的参数计算出游戏中截图区域的宽高和原点坐标,保存在变量mointor中。定义一个函数grab_screen_mss,使用cap.grab抓取图片,使用np.array将图片转成数组,然后使用cvtColor将BRGA转BRG,去除透明通道。定义了一个run函数,不断循环判断是否按下ctrl+U。如果按下,窗口将始终在顶部。然后调用grab_screen_mss函数获取截图,使用cv2库进行图片显示,设置显示窗口的大小。如果窗口需要置顶,使用win32com库和win32gui库来保持窗口置顶。最后使用cv2库的waitKey函数等待用户操作,按ESC键退出程序。调用示例sc=ScreenCapture()sc.run()参数说明:screen_frame:Tuple[int,int]屏幕宽高,分别为x,yregion:Tuple[float,float]实际截图范围,分别为x,y,(1.0,1.0)表示全屏检测,检测范围越低,检测范围越小(始终保持以屏幕中心为中心)window_name:str显示窗口名exit_key:int结束窗口的退出键值,是键盘上每个键对应的ASCII码值,默认是ESC键和其他键盘按键对应的ASCII码值(0x指十六进制,删除键的ascii码值为0x2e,即0x1鼠标左键0x2鼠标右键0x3取消键0x4鼠标中键0x8BACKSPACE键0x9TAB键0xCCLEAR键0xDENTER键0x10SHIFT键0x11CTRL键0x12MENU键0x13PAUSE键0x14CAPSLOCK键0x1BESC键0x20空格键0x21PAGEUP键0x22PAGEDOWN键0x23END键0x2MEHO键0x20x26UPARROW键0x27RIGHTARROW键0x28DOWNARROW键0x29SELECT键0x2APRINTSCREEN键0x2BEXECUTE键0x2CSNAPSHOT键0x2DINSERT键0x2EDELETE键0x2FZHELPUMkeyALOCK字母键0x90与IIAS相同:值描述65A键66B键67C键68D键69E键70F键71G键72H键73I键74J键75K键76L键77M键78N键79Okey80Pkey81Qkey82Rkey83Skey84Tkey85Ukey86Vkey87Wkey88Xkey89Ykey90Zkey0to9keysandASCIInumbers0–9代码相同:值说明480键491键502键513键524键535键546键557键568键579键以下常量表示数字键盘上的键:值说明0x600键0x611键0x622键0x633键0x644键0x655键0x666键0x677键0x688键0x699键0x6A乘号(*)键0x6B加号(+)键0x6C回车键0x6D减号键(-)键0x6E小数点(.)键0x6F分号(/)键以下常量表示功能键:数值说明0x70F1键0x71F2键0x72F3键0x73F4键0x74F5键0x75F6键0x76F7键0x77F8键0x78F9键0x79F10键0x7AF11键0x7BF12键0x7CF13键0x7DF14键0x7EF15键0x7FF16键
