openvino_infer.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. import cv2
  2. import matplotlib.pyplot as plt
  3. import numpy as np
  4. from openvino.runtime import Core
  5. import os
  6. import time
  7. import copy
  8. from PIL import Image, ImageDraw, ImageFont
  9. import argparse
  10. def cv_imread(path):
  11. img=cv2.imdecode(np.fromfile(path,dtype=np.uint8),-1)
  12. return img
  13. def allFilePath(rootPath,allFIleList):
  14. fileList = os.listdir(rootPath)
  15. for temp in fileList:
  16. if os.path.isfile(os.path.join(rootPath,temp)):
  17. # if temp.endswith("jpg"):
  18. allFIleList.append(os.path.join(rootPath,temp))
  19. else:
  20. allFilePath(os.path.join(rootPath,temp),allFIleList)
  21. mean_value,std_value=((0.588,0.193))#识别模型均值标准差
  22. plateName=r"#京沪津渝冀晋蒙辽吉黑苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云藏陕甘青宁新学警港澳挂使领民航危0123456789ABCDEFGHJKLMNPQRSTUVWXYZ险品"
  23. def rec_pre_precessing(img,size=(48,168)): #识别前处理
  24. img =cv2.resize(img,(168,48))
  25. img = img.astype(np.float32)
  26. img = (img/255-mean_value)/std_value
  27. img = img.transpose(2,0,1)
  28. img = img.reshape(1,*img.shape)
  29. return img
  30. def decodePlate(preds): #识别后处理
  31. pre=0
  32. newPreds=[]
  33. preds=preds.astype(np.int8)[0]
  34. for i in range(len(preds)):
  35. if preds[i]!=0 and preds[i]!=pre:
  36. newPreds.append(preds[i])
  37. pre=preds[i]
  38. plate=""
  39. for i in newPreds:
  40. plate+=plateName[int(i)]
  41. return plate
  42. def load_model(onnx_path):
  43. ie = Core()
  44. model_onnx = ie.read_model(model=onnx_path)
  45. compiled_model_onnx = ie.compile_model(model=model_onnx, device_name="CPU")
  46. output_layer_onnx = compiled_model_onnx.output(0)
  47. return compiled_model_onnx,output_layer_onnx
  48. def get_plate_result(img,rec_model,rec_output):
  49. img =rec_pre_precessing(img)
  50. # time_b = time.time()
  51. res_onnx = rec_model([img])[rec_output]
  52. # time_e= time.time()
  53. index =np.argmax(res_onnx,axis=-1) #找出最大概率的那个字符的序号
  54. plate_no = decodePlate(index)
  55. # print(f'{plate_no},time is {time_e-time_b}')
  56. return plate_no
  57. def get_split_merge(img): #双层车牌进行分割后识别
  58. h,w,c = img.shape
  59. img_upper = img[0:int(5/12*h),:]
  60. img_lower = img[int(1/3*h):,:]
  61. img_upper = cv2.resize(img_upper,(img_lower.shape[1],img_lower.shape[0]))
  62. new_img = np.hstack((img_upper,img_lower))
  63. return new_img
  64. def order_points(pts):
  65. rect = np.zeros((4, 2), dtype = "float32")
  66. s = pts.sum(axis = 1)
  67. rect[0] = pts[np.argmin(s)]
  68. rect[2] = pts[np.argmax(s)]
  69. diff = np.diff(pts, axis = 1)
  70. rect[1] = pts[np.argmin(diff)]
  71. rect[3] = pts[np.argmax(diff)]
  72. return rect
  73. def four_point_transform(image, pts):
  74. rect = order_points(pts)
  75. (tl, tr, br, bl) = rect
  76. widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
  77. widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
  78. maxWidth = max(int(widthA), int(widthB))
  79. heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
  80. heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
  81. maxHeight = max(int(heightA), int(heightB))
  82. dst = np.array([
  83. [0, 0],
  84. [maxWidth - 1, 0],
  85. [maxWidth - 1, maxHeight - 1],
  86. [0, maxHeight - 1]], dtype = "float32")
  87. M = cv2.getPerspectiveTransform(rect, dst)
  88. warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
  89. # return the warped image
  90. return warped
  91. def my_letter_box(img,size=(640,640)):
  92. h,w,c = img.shape
  93. r = min(size[0]/h,size[1]/w)
  94. new_h,new_w = int(h*r),int(w*r)
  95. top = int((size[0]-new_h)/2)
  96. left = int((size[1]-new_w)/2)
  97. bottom = size[0]-new_h-top
  98. right = size[1]-new_w-left
  99. img_resize = cv2.resize(img,(new_w,new_h))
  100. img = cv2.copyMakeBorder(img_resize,top,bottom,left,right,borderType=cv2.BORDER_CONSTANT,value=(114,114,114))
  101. return img,r,left,top
  102. def xywh2xyxy(boxes):
  103. xywh =copy.deepcopy(boxes)
  104. xywh[:,0]=boxes[:,0]-boxes[:,2]/2
  105. xywh[:,1]=boxes[:,1]-boxes[:,3]/2
  106. xywh[:,2]=boxes[:,0]+boxes[:,2]/2
  107. xywh[:,3]=boxes[:,1]+boxes[:,3]/2
  108. return xywh
  109. def my_nms(boxes,iou_thresh):
  110. index = np.argsort(boxes[:,4])[::-1]
  111. keep = []
  112. while index.size >0:
  113. i = index[0]
  114. keep.append(i)
  115. x1=np.maximum(boxes[i,0],boxes[index[1:],0])
  116. y1=np.maximum(boxes[i,1],boxes[index[1:],1])
  117. x2=np.minimum(boxes[i,2],boxes[index[1:],2])
  118. y2=np.minimum(boxes[i,3],boxes[index[1:],3])
  119. w = np.maximum(0,x2-x1)
  120. h = np.maximum(0,y2-y1)
  121. inter_area = w*h
  122. union_area = (boxes[i,2]-boxes[i,0])*(boxes[i,3]-boxes[i,1])+(boxes[index[1:],2]-boxes[index[1:],0])*(boxes[index[1:],3]-boxes[index[1:],1])
  123. iou = inter_area/(union_area-inter_area)
  124. idx = np.where(iou<=iou_thresh)[0]
  125. index = index[idx+1]
  126. return keep
  127. def restore_box(boxes,r,left,top):
  128. boxes[:,[0,2,5,7,9,11]]-=left
  129. boxes[:,[1,3,6,8,10,12]]-=top
  130. boxes[:,[0,2,5,7,9,11]]/=r
  131. boxes[:,[1,3,6,8,10,12]]/=r
  132. return boxes
  133. def detect_pre_precessing(img,img_size):
  134. img,r,left,top=my_letter_box(img,img_size)
  135. # cv2.imwrite("1.jpg",img)
  136. img =img[:,:,::-1].transpose(2,0,1).copy().astype(np.float32)
  137. img=img/255
  138. img=img.reshape(1,*img.shape)
  139. return img,r,left,top
  140. def post_precessing(dets,r,left,top,conf_thresh=0.3,iou_thresh=0.5):#检测后处理
  141. choice = dets[:,:,4]>conf_thresh
  142. dets=dets[choice]
  143. dets[:,13:15]*=dets[:,4:5]
  144. box = dets[:,:4]
  145. boxes = xywh2xyxy(box)
  146. score= np.max(dets[:,13:15],axis=-1,keepdims=True)
  147. index = np.argmax(dets[:,13:15],axis=-1).reshape(-1,1)
  148. output = np.concatenate((boxes,score,dets[:,5:13],index),axis=1)
  149. reserve_=my_nms(output,iou_thresh)
  150. output=output[reserve_]
  151. output = restore_box(output,r,left,top)
  152. return output
  153. def rec_plate(outputs,img0,rec_model,rec_output):
  154. dict_list=[]
  155. for output in outputs:
  156. result_dict={}
  157. rect=output[:4].tolist()
  158. land_marks = output[5:13].reshape(4,2)
  159. roi_img = four_point_transform(img0,land_marks)
  160. label = int(output[-1])
  161. if label==1: #代表是双层车牌
  162. roi_img = get_split_merge(roi_img)
  163. plate_no = get_plate_result(roi_img,rec_model,rec_output) #得到车牌识别结果
  164. result_dict['rect']=rect
  165. result_dict['landmarks']=land_marks.tolist()
  166. result_dict['plate_no']=plate_no
  167. result_dict['roi_height']=roi_img.shape[0]
  168. dict_list.append(result_dict)
  169. return dict_list
  170. def cv2ImgAddText(img, text, left, top, textColor=(0, 255, 0), textSize=20):
  171. if (isinstance(img, np.ndarray)): #判断是否OpenCV图片类型
  172. img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
  173. draw = ImageDraw.Draw(img)
  174. fontText = ImageFont.truetype(
  175. "fonts/platech.ttf", textSize, encoding="utf-8")
  176. draw.text((left, top), text, textColor, font=fontText)
  177. return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)
  178. def draw_result(orgimg,dict_list):
  179. result_str =""
  180. for result in dict_list:
  181. rect_area = result['rect']
  182. x,y,w,h = rect_area[0],rect_area[1],rect_area[2]-rect_area[0],rect_area[3]-rect_area[1]
  183. padding_w = 0.05*w
  184. padding_h = 0.11*h
  185. rect_area[0]=max(0,int(x-padding_w))
  186. rect_area[1]=min(orgimg.shape[1],int(y-padding_h))
  187. rect_area[2]=max(0,int(rect_area[2]+padding_w))
  188. rect_area[3]=min(orgimg.shape[0],int(rect_area[3]+padding_h))
  189. height_area = result['roi_height']
  190. landmarks=result['landmarks']
  191. result = result['plate_no']
  192. result_str+=result+" "
  193. # for i in range(4): #关键点
  194. # cv2.circle(orgimg, (int(landmarks[i][0]), int(landmarks[i][1])), 5, clors[i], -1)
  195. if len(result)>=6:
  196. cv2.rectangle(orgimg,(rect_area[0],rect_area[1]),(rect_area[2],rect_area[3]),(0,0,255),2) #画框
  197. orgimg=cv2ImgAddText(orgimg,result,rect_area[0]-height_area,rect_area[1]-height_area-10,(0,255,0),height_area)
  198. # print(result_str)
  199. return orgimg
  200. def get_second(capture):
  201. if capture.isOpened():
  202. rate = capture.get(5) # 帧速率
  203. FrameNumber = capture.get(7) # 视频文件的帧数
  204. duration = FrameNumber/rate # 帧速率/视频总帧数 是时间,除以60之后单位是分钟
  205. return int(rate),int(FrameNumber),int(duration)
  206. if __name__=="__main__":
  207. parser = argparse.ArgumentParser()
  208. parser.add_argument('--detect_model',type=str, default=r'weights/plate_detect.onnx', help='model.pt path(s)') #检测模型
  209. parser.add_argument('--rec_model', type=str, default='weights/plate_rec.onnx', help='model.pt path(s)')#识别模型
  210. parser.add_argument('--image_path', type=str, default='imgs', help='source')
  211. parser.add_argument('--img_size', type=int, default=640, help='inference size (pixels)')
  212. parser.add_argument('--output', type=str, default='result1', help='source')
  213. opt = parser.parse_args()
  214. file_list=[]
  215. file_folder=opt.image_path
  216. allFilePath(file_folder,file_list)
  217. rec_onnx_path =opt.rec_model
  218. detect_onnx_path=opt.detect_model
  219. rec_model,rec_output=load_model(rec_onnx_path)
  220. detect_model,detect_output=load_model(detect_onnx_path)
  221. count=0
  222. img_size=(opt.img_size,opt.img_size)
  223. begin=time.time()
  224. save_path=opt.output
  225. if not os.path.exists(save_path):
  226. os.mkdir(save_path)
  227. for pic_ in file_list:
  228. count+=1
  229. print(count,pic_,end=" ")
  230. img=cv2.imread(pic_)
  231. time_b = time.time()
  232. if img.shape[-1]==4:
  233. img = cv2.cvtColor(img,cv2.COLOR_BGRA2BGR)
  234. img0 = copy.deepcopy(img)
  235. img,r,left,top = detect_pre_precessing(img,img_size) #检测前处理
  236. # print(img.shape)
  237. det_result = detect_model([img])[detect_output]
  238. outputs = post_precessing(det_result,r,left,top) #检测后处理
  239. time_1 = time.time()
  240. result_list=rec_plate(outputs,img0,rec_model,rec_output)
  241. time_e= time.time()
  242. print(f'耗时 {time_e-time_b} s')
  243. ori_img = draw_result(img0,result_list)
  244. img_name = os.path.basename(pic_)
  245. save_img_path = os.path.join(save_path,img_name)
  246. cv2.imwrite(save_img_path,ori_img)
  247. print(f"总共耗时{time.time()-begin} s")
  248. # video_name = r"plate.mp4"
  249. # capture=cv2.VideoCapture(video_name)
  250. # fourcc = cv2.VideoWriter_fourcc(*'MP4V')
  251. # fps = capture.get(cv2.CAP_PROP_FPS) # 帧数
  252. # width, height = int(capture.get(cv2.CAP_PROP_FRAME_WIDTH)), int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 宽高
  253. # out = cv2.VideoWriter('2result.mp4', fourcc, fps, (width, height)) # 写入视频
  254. # frame_count = 0
  255. # fps_all=0
  256. # rate,FrameNumber,duration=get_second(capture)
  257. # # with open("example.csv",mode='w',newline='') as example_file:
  258. # # fieldnames = ['车牌', '时间']
  259. # # writer = csv.DictWriter(example_file, fieldnames=fieldnames, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
  260. # # writer.writeheader()
  261. # if capture.isOpened():
  262. # while True:
  263. # t1 = cv2.getTickCount()
  264. # frame_count+=1
  265. # ret,img=capture.read()
  266. # if not ret:
  267. # break
  268. # # if frame_count%rate==0:
  269. # img0 = copy.deepcopy(img)
  270. # img,r,left,top = detect_pre_precessing(img,img_size) #检测前处理
  271. # # print(img.shape)
  272. # det_result = detect_model([img])[detect_output]
  273. # outputs = post_precessing(det_result,r,left,top) #检测后处理
  274. # result_list=rec_plate(outputs,img0,rec_model,rec_output)
  275. # ori_img = draw_result(img0,result_list)
  276. # t2 =cv2.getTickCount()
  277. # infer_time =(t2-t1)/cv2.getTickFrequency()
  278. # fps=1.0/infer_time
  279. # fps_all+=fps
  280. # str_fps = f'fps:{fps:.4f}'
  281. # out.write(ori_img)
  282. # cv2.putText(ori_img,str_fps,(20,20),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),2)
  283. # cv2.imshow("haha",ori_img)
  284. # cv2.waitKey(1)
  285. # # current_time = int(frame_count/FrameNumber*duration)
  286. # # sec = current_time%60
  287. # # minute = current_time//60
  288. # # for result_ in result_list:
  289. # # plate_no = result_['plate_no']
  290. # # if not is_car_number(pattern_str,plate_no):
  291. # # continue
  292. # # print(f'车牌号:{plate_no},时间:{minute}分{sec}秒')
  293. # # time_str =f'{minute}分{sec}秒'
  294. # # writer.writerow({"车牌":plate_no,"时间":time_str})
  295. # # out.write(ori_img)
  296. # else:
  297. # print("失败")
  298. # capture.release()
  299. # out.release()
  300. # cv2.destroyAllWindows()
  301. # print(f"all frame is {frame_count},average fps is {fps_all/frame_count}")