You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

api.py 13 kB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. from api.model.model import PicoDet
  2. import time
  3. import cv2
  4. import json
  5. import datetime
  6. import os
  7. import sys
  8. from utils.utils import send_notifycation
  9. import collections
  10. from utils.utils import doNotMove,mouseClick
  11. def getFile(ruleFile):
  12. if getattr(sys, 'frozen', False):
  13. absPath = os.path.dirname(os.path.abspath(sys.executable))
  14. elif __file__:
  15. absPath = os.path.dirname(os.path.abspath(__file__))
  16. else:
  17. absPath = ''
  18. return os.path.join(absPath,ruleFile)
  19. def get_settings_status_name(data, settings,setting_name):
  20. # 访问指定 "setting" 的信息
  21. for setting in data[settings]:
  22. if setting["name"] == setting_name:
  23. # 使用 filter() 和 map() 函数提取信息
  24. names = list(map(lambda x: x["name"], filter(lambda x: x["status"], setting["status"])))
  25. return names[0]
  26. def get_settings_status_root(data, settings):
  27. # 访问指定 "setting" 的信息
  28. names = list(map(lambda x: x["name"], filter(lambda x: x["status"], data[settings])))
  29. return names[0]
  30. def get_setting_status(data, settings,setting_name):
  31. # 使用 filter() 和 map() 函数提取信息
  32. status = list(map(lambda x: x["status"], filter(lambda x: x["name"] == setting_name, data[settings])))
  33. return status[0]
  34. def get_photo(cap):
  35. # cap = cv2.VideoCapture(0) # 开启摄像头
  36. f, frame = cap.read() # 将摄像头中的一帧图片数据保存
  37. return frame
  38. # print('开始咯!')
  39. # while cv2.waitKey(1)==-1:
  40. # #计时
  41. def get_photo_detect(cap,net):
  42. '''
  43. 输入{图像,网络模型},输出[预测时间,预测结果]
  44. '''
  45. result = net.detect_img(get_photo(cap),show_result=False)
  46. return result
  47. def get_photo_detect_img(cap,net):
  48. '''
  49. 输入{图像,网络模型},输出[预测时间,预测图片]
  50. '''
  51. start = time.time()
  52. [result,img] = net.detect_img(get_photo(cap),show_result=True)
  53. # cv2.imshow('Video Cam', result)
  54. # # print(result)
  55. end = time.time()
  56. # print('time:',end-start)
  57. # cap.release() # 关闭摄像头
  58. # # cv2.destroyAllWindows()
  59. return [end-start,result,img]
  60. def get_photo_base64(cap):
  61. import base64
  62. # import numpy as np
  63. img = get_photo(cap)
  64. image = cv2.imencode('.jpg',img)[1]
  65. image_code = str(base64.b64encode(image))[2:-1]
  66. return image_code
  67. def mat2base64(frame):
  68. import base64
  69. # import numpy as np
  70. image = cv2.imencode('.jpg',frame)[1]
  71. image_code = str(base64.b64encode(image))[2:-1]
  72. return image_code
  73. def getModelSetting(args):
  74. import requests
  75. url = 'https://gitee.com/JiangNoah/emc/raw/master/model.json'
  76. r = requests.get(url)
  77. model_dict = (r.json())["models"]
  78. #将get_settings_status_name(args,"ModelSetting","模型版本设置")在model_dict的list中对应的status设置为true
  79. for model in model_dict:
  80. if model["name"] == get_settings_status_name(args,"ModelSetting","模型版本设置"):
  81. model["status"] = True
  82. else:
  83. model["status"] = False
  84. args["ModelSetting"][0]["status"] = model_dict
  85. return args
  86. def checkAction(queue,type,action,tip):
  87. print(type,action,queue[2]["time"]-queue[0]["time"])
  88. # 输入一个长度为3的队列,根据情况判断是否执行动作
  89. if(queue[0]["status"]==0 and queue[1]["status"]==1 and queue[2]["status"]==0 and type=="张开持续1S" and (queue[2]["time"]-queue[0]["time"])>1):
  90. if(action=="悬停鼠标"):
  91. doNotMove()
  92. if(tip):
  93. send_notifycation("触发悬停鼠标","EMC")
  94. elif(action=="单击按钮"):
  95. mouseClick()
  96. if(tip):
  97. send_notifycation("触发单击按钮","EMC")
  98. return True
  99. elif(queue[0]["status"]==1 and queue[1]["status"]==0 and queue[2]["status"]==1 and type=="闭上持续1S" and (queue[2]["time"]-queue[0]["time"])>1):
  100. if(action=="悬停鼠标"):
  101. doNotMove()
  102. if(tip):
  103. send_notifycation("触发悬停鼠标","EMC")
  104. elif(action=="单击按钮"):
  105. mouseClick()
  106. if(tip):
  107. send_notifycation("触发单击按钮","EMC")
  108. return True
  109. return False
  110. class API:
  111. '''本地API,供前端JS调用'''
  112. window = None
  113. net = None
  114. cap = None
  115. args = None
  116. # 状态队列
  117. queue = None
  118. def __init__(self):
  119. with open(getFile("config.json"),'r',encoding='utf8')as fp:
  120. self.args = json.load(fp)
  121. self.args = getModelSetting(self.args)
  122. self.net = PicoDet(
  123. get_settings_status_name(self.args,"ModelSetting","模型版本设置"),
  124. self.args['classfile'],
  125. prob_threshold=float(get_setting_status(self.args,"ModelSetting",'confThreshold')),
  126. iou_threshold=float(get_setting_status(self.args,"ModelSetting",'nmsThreshold')))
  127. # net.detect_folder(args['img_fold'], args['result_fold'])
  128. # 调用摄像头拍摄照片
  129. self.cap = cv2.VideoCapture(0) # 开启摄像头
  130. # cv2.namedWindow('Video Cam', cv2.WINDOW_NORMAL)
  131. if(self.args['toggle'] and self.args['tip']):
  132. send_notifycation("EMC程序已启动","EMC")
  133. self.queue = collections.deque(maxlen=3)
  134. def detectThreading(self):
  135. if self.args['toggle']==False:
  136. pass
  137. result = get_photo_detect(self.cap,self.net)
  138. eye = -1
  139. mouth = -1
  140. for i in result:
  141. if i["classid"] == "closed_eye":
  142. eye = 0
  143. elif i["classid"] == "open_eye":
  144. eye = 1
  145. elif i["classid"] == "closed_mouth":
  146. mouth = 0
  147. elif i["classid"] == "open_mouth":
  148. mouth = 1
  149. status = -1
  150. if get_settings_status_root(self.args,"control") == "嘴控":
  151. if(mouth==0):
  152. status = 0
  153. elif(mouth==1):
  154. status = 1
  155. elif get_settings_status_root(self.args,"control") == "眼控":
  156. if(eye==0):
  157. status = 0
  158. elif(eye==1):
  159. status = 1
  160. elif get_settings_status_root(self.args,"control") == "嘴/眼控":
  161. if(mouth==0 or eye==0):
  162. status = 0
  163. elif(mouth==1 or eye==1):
  164. status = 1
  165. if(status!=-1):
  166. if(len(self.queue)<3 or status!=self.queue[-1]["status"]):
  167. self.queue.append({"status":status,"time":time.time()})
  168. if(len(self.queue)==3):
  169. if(checkAction(self.queue,get_settings_status_name(self.args,"ControlSetting","控制设置"),get_settings_status_name(self.args,"ControlSetting","控制功能"),self.args['tip'])):
  170. self.queue.clear()#执行动作则清空队列
  171. else:
  172. self.queue[-1]["time"]=time.time()
  173. print(self.queue)
  174. def getPrimaryImg(self,type="不裁剪"):
  175. # 三种处理图片的方式:不裁剪、居中裁剪成224*224、居中裁剪成320*320。
  176. if(type=="不裁剪"):
  177. return get_photo_base64(self.cap)
  178. elif(type=="居中裁剪成224*224"):
  179. img = get_photo(self.cap)
  180. height=len(img)
  181. width=len(img[0])
  182. if(height>224 and width>224):
  183. y0 = height//2
  184. x0 = width//2
  185. x1 = x0-112
  186. y1 = y0-112
  187. x2 = x0+112
  188. y2 = y0+112
  189. img = img[y1:y2, x1:x2]
  190. return mat2base64(img)
  191. elif(type=="居中裁剪成320*320"):
  192. img = get_photo(self.cap)
  193. height=len(img)
  194. width=len(img[0])
  195. if(height>320 and width>320):
  196. y0 = height//2
  197. x0 = width//2
  198. x1 = x0-160
  199. y1 = y0-160
  200. x2 = x0+160
  201. y2 = y0+160
  202. img = img[y1:y2, x1:x2]
  203. return mat2base64(img)
  204. def getDetectImg(self):
  205. [time,result,img] = get_photo_detect_img(self.cap,self.net)
  206. return [time,result,mat2base64(img)]#AttributeError: 'InferenceSession' object has no attribute 'detect'
  207. def getIndexSetting(self):
  208. toggle = self.args['toggle']
  209. tip = self.args['tip']
  210. control = self.args['control']
  211. return [toggle,tip,control]
  212. def getAdvanceSetting(self):
  213. return [self.args['ControlSetting'], self.args['ModelSetting'], self.args['otherSetting']]
  214. def changeSetting(self,data):
  215. self.args.update(data)
  216. with open(getFile("config.json"),'w',encoding='utf8')as fp:
  217. json.dump(self.args,fp,ensure_ascii=False,indent=4)
  218. def getPersonalizationPrimaryImg(self):
  219. #判断是否存在"primary_img"文件夹
  220. if(os.path.exists(getFile("primary_img"))==False):
  221. #不存在则创建
  222. os.mkdir(getFile("primary_img"))
  223. #返回该文件夹下jpg文件的数量和列表
  224. return [len(os.listdir(getFile("primary_img"))),os.listdir(getFile("primary_img"))]
  225. def setPersonalizationPrimaryImg(self,type="不裁剪"):
  226. #判断是否存在"primary_img"文件夹
  227. if(os.path.exists(getFile("primary_img"))==False):
  228. #不存在则创建
  229. os.mkdir(getFile("primary_img"))
  230. #保存图片
  231. # 图片名字是当前时间
  232. # 三种处理图片的方式:不裁剪、居中裁剪成224*224、居中裁剪成320*320。
  233. if(type=="不裁剪"):
  234. cv2.imwrite(getFile("primary_img")+"/"+time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())+".jpg",get_photo(self.cap))
  235. elif(type=="居中裁剪成224*224"):
  236. img = get_photo(self.cap)
  237. height=len(img)
  238. width=len(img[0])
  239. if(height>224 and width>224):
  240. y0 = height//2
  241. x0 = width//2
  242. x1 = x0-112
  243. y1 = y0-112
  244. x2 = x0+112
  245. y2 = y0+112
  246. img = img[y1:y2, x1:x2]
  247. cv2.imwrite(getFile("primary_img")+"/"+time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())+".jpg",img)
  248. elif(type=="居中裁剪成320*320"):
  249. img = get_photo(self.cap)
  250. height=len(img)
  251. width=len(img[0])
  252. if(height>320 and width>320):
  253. y0 = height//2
  254. x0 = width//2
  255. x1 = x0-160
  256. y1 = y0-160
  257. x2 = x0+160
  258. y2 = y0+160
  259. img = img[y1:y2, x1:x2]
  260. cv2.imwrite(getFile("primary_img")+"/"+time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())+".jpg",img)
  261. #返回该文件夹下jpg文件的数量和列表
  262. return [len(os.listdir(getFile("primary_img"))),os.listdir(getFile("primary_img"))]
  263. def openPrimaryImgFiles(self):
  264. #判断是否存在"primary_img"文件夹
  265. if(os.path.exists(getFile("primary_img"))==False):
  266. #不存在则创建
  267. os.mkdir(getFile("primary_img"))
  268. #打开文件夹
  269. os.startfile(getFile("primary_img"))
  270. def getPrimaryListImg(self,img_name):
  271. #判断是否存在"primary_img"文件夹
  272. if(os.path.exists(getFile("primary_img"))==False):
  273. #不存在则创建
  274. os.mkdir(getFile("primary_img"))
  275. #读取图片
  276. img = cv2.imread(getFile("primary_img")+"/"+img_name)
  277. #返回图片
  278. return mat2base64(img)
  279. def saveAnnotationData(self,data,dataset):
  280. #判断是否存在"annotation_data"文件夹
  281. if(os.path.exists(getFile("annotation_data"))==False):
  282. #不存在则创建
  283. os.mkdir(getFile("annotation_data"))
  284. #保存COCO数据集
  285. with open(getFile("annotation_data")+"/"+"dataset.json",'w',encoding='utf8')as fp:
  286. json.dump(dataset,fp,ensure_ascii=False,indent=4)
  287. #保存标注数据
  288. with open(getFile("annotation_data")+"/"+"data.json",'w',encoding='utf8')as fp:
  289. json.dump(data,fp,ensure_ascii=False,indent=4)
  290. def getAnnotationData(self):
  291. #判断是否存在"annotation_data"文件夹
  292. if(os.path.exists(getFile("annotation_data"))==False):
  293. #不存在则创建
  294. os.mkdir(getFile("annotation_data"))
  295. #判断是否存在"dataset.json"文件
  296. if(os.path.exists(getFile("annotation_data")+"/"+"dataset.json")):
  297. #存在则读取
  298. with open(getFile("annotation_data")+"/"+"dataset.json",'r',encoding='utf8')as fp:
  299. dataset = json.load(fp)
  300. else:
  301. #不存在则创建
  302. return {}
  303. #判断是否存在"data.json"文件
  304. if(os.path.exists(getFile("annotation_data")+"/"+"data.json")):
  305. #存在则读取
  306. with open(getFile("annotation_data")+"/"+"data.json",'r',encoding='utf8')as fp:
  307. data = json.load(fp)
  308. else:
  309. #不存在则创建
  310. return {}
  311. #返回数据
  312. return {"mergeData":dataset,"annotationData":data}