'''
xgo图形化python库
'''
import cv2
import cv2 as cv
import copy
import argparse
import numpy as np
import mediapipe as mp
import shutil,requests
import urllib.request
import math
import os,sys,time,logging
import spidev as SPI
import LCD_2inch
import onnxruntime
import RPi.GPIO as GPIO
from PIL import Image,ImageDraw,ImageFont
from ctypes import c_void_p
from tensorflow.keras.utils import img_to_array
from keras.preprocessing import image
from pyexpat import model
from keras.models import load_model
import json
from xgolib import XGO
__versinon__ = '1.1.0'
__last_modified__ = '2023/3/30'
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
display = LCD_2inch.LCD_2inch()
display.Init()
display.clear()
splash = Image.new("RGB",(320,240),"black")
display.ShowImage(splash)
#字体载入
font1 = ImageFont.truetype("/home/pi/xgoEdu/Font/msyh.ttc",15)
#情绪识别
face_classifier=cv2.CascadeClassifier('/home/pi/xgoEdu/model/haarcascade_frontalface_default.xml')
classifier = load_model('/home/pi/xgoEdu/model/EmotionDetectionModel.h5')
class_labels=['Angry','Happy','Neutral','Sad','Surprise']
#年纪及性别识别
# 网络模型 和 预训练模型
faceProto = "/home/pi/xgoEdu/model/opencv_face_detector.pbtxt"
faceModel = "/home/pi/xgoEdu/model/opencv_face_detector_uint8.pb"
ageProto = "/home/pi/xgoEdu/model/age_deploy.prototxt"
ageModel = "/home/pi/xgoEdu/model/age_net.caffemodel"
genderProto = "/home/pi/xgoEdu/model/gender_deploy.prototxt"
genderModel = "/home/pi/xgoEdu/model/gender_net.caffemodel"
# 模型均值
MODEL_MEAN_VALUES = (78.4263377603, 87.7689143744, 114.895847746)
ageList = ['(0-2)', '(4-6)', '(8-12)', '(15-20)', '(25-32)', '(38-43)', '(48-53)', '(60-100)']
genderList = ['Male', 'Female']
# 加载网络
ageNet = cv.dnn.readNet(ageModel, ageProto)
genderNet = cv.dnn.readNet(genderModel, genderProto)
# 人脸检测的网络和模型
faceNet = cv.dnn.readNet(faceModel, faceProto)
padding = 20
cap =cv2.VideoCapture(0)
cap.set(3,320)
cap.set(4,240)
'''
人脸检测
'''
def getFaceBox(net, frame, conf_threshold=0.7):
frameOpencvDnn = frame.copy()
frameHeight = frameOpencvDnn.shape[0]
frameWidth = frameOpencvDnn.shape[1]
blob = cv.dnn.blobFromImage(frameOpencvDnn, 1.0, (300, 300), [104, 117, 123], True, False)
net.setInput(blob)
detections = net.forward()
bboxes = []
for i in range(detections.shape[2]):
confidence = detections[0, 0, i, 2]
if confidence > conf_threshold:
x1 = int(detections[0, 0, i, 3] * frameWidth)
y1 = int(detections[0, 0, i, 4] * frameHeight)
x2 = int(detections[0, 0, i, 5] * frameWidth)
y2 = int(detections[0, 0, i, 6] * frameHeight)
bboxes.append([x1, y1, x2, y2])
cv.rectangle(frameOpencvDnn, (x1, y1), (x2, y2), (0, 255, 0), int(round(frameHeight / 150)),8)
return frameOpencvDnn, bboxes
'''
手势识别函数
'''
def hand_pos(angle):
pos = None
# 大拇指角度
f1 = angle[0]
# 食指角度
f2 = angle[1]
# 中指角度
f3 = angle[2]
# 无名指角度
f4 = angle[3]
# 小拇指角度
f5 = angle[4]
if f1 < 50 and (f2 >= 50 and (f3 >= 50 and (f4 >= 50 and f5 >= 50))):
pos = 'Good!'
elif f1 < 50 and (f2 >= 50 and (f3 < 50 and (f4 < 50 and f5 < 50))):
pos = 'Ok!'
elif f1 < 50 and (f2 < 50 and (f3 >= 50 and (f4 >= 50 and f5 < 50))):
pos = 'Rock!'
elif f1 >= 50 and (f2 >= 50 and (f3 >= 50 and (f4 >= 50 and f5 >= 50))):
pos = 'stone'
elif f1 >= 50 and (f2 < 50 and (f3 >= 50 and (f4 >= 50 and f5 >= 50))):
pos = '1'
elif f1 >= 50 and (f2 < 50 and (f3 < 50 and (f4 < 50 and f5 >= 50))):
pos = '3'
elif f1 >= 50 and (f2 < 50 and (f3 < 50 and (f4 < 50 and f5 < 50))):
pos = '4'
elif f1 < 50 and (f2 < 50 and (f3 < 50 and (f4 < 50 and f5 < 50))):
pos = '5'
elif f1 >= 50 and (f2 < 50 and (f3 < 50 and (f4 >= 50 and f5 >= 50))):
pos = '2'
return pos
def color(value):
digit = list(map(str, range(10))) + list("ABCDEF")
value = value.upper()
if isinstance(value, tuple):
string = '#'
for i in value:
a1 = i // 16
a2 = i % 16
string += digit[a1] + digit[a2]
return string
elif isinstance(value, str):
a1 = digit.index(value[1]) * 16 + digit.index(value[2])
a2 = digit.index(value[3]) * 16 + digit.index(value[4])
a3 = digit.index(value[5]) * 16 + digit.index(value[6])
return (a3, a2, a1)
'''
竞赛用
'''
class XgoExtend(XGO):
#def __init__(self, port, screen, button, cap, baud=115200, version='xgomini'):
def __init__(self, port, baud=115200, version='xgomini'):
super().__init__(port, baud, version)
self.reset()
time.sleep(0.5)
self.init_yaw = self.read_yaw()
self.calibration = {}
with open("/home/pi/xgoEdu/model/calibration.json", 'r', encoding='utf-8') as f:
self.k = json.load(f)
self.block_k1 = self.k["BLOCK_k1"]
self.block_k2 = self.k["BLOCK_k2"]
self.block_b = self.k["BLOCK_b"]
self.block_ky = self.k["BLOCK_ky"]
self.block_by = self.k["BLOCK_by"]
self.cup_k1 = self.k["CUP_k1"]
self.cup_k2 = self.k["CUP_k2"]
self.cup_b = self.k["CUP_b"]
def show_img(self, img):
imgok = Image.fromarray(img, mode='RGB')
#self.screen.ShowImage(imgok)
display.ShowImage(imgok)
def check_quit(self):
button = XGOEDU()
if button.xgoButton("b"):
#关闭摄像头并释放对象
#self.cap.release()
cap.release()
#关闭窗口
cv2.destroyAllWindows()
#退出系统
sys.exit()
def move_by(self, distance, vx, vy, k, mintime):
runtime = k * abs(distance) + mintime
self.move_x(math.copysign(vx, distance))
self.move_y(math.copysign(vy, distance))
time.sleep(runtime)
self.move_x(0)
self.move_y(0)
time.sleep(0.2)
def move_x_by(self, distance, vx=18, k=0.035, mintime=0.55):
self.move_by(distance, vx, 0, k, mintime)
pass
def move_y_by(self, distance, vy=18, k=0.0373, mintime=0.5):
self.move_by(distance, 0, vy, k, mintime)
pass
def adjust_x(self, distance, vx=18, k=0.045, mintime=0.6):
self.move_by(distance, vx, 0, k, mintime)
pass
def adjust_y(self, distance, vy=18, k=0.0373, mintime=0.5):
self.move_by(distance, 0, vy, k, mintime)
pass
def adjust_yaw(self, theta, vyaw=16, k=0.08, mintime=0.5):
runtime = abs(theta) * k + mintime
self.turn(math.copysign(vyaw, theta))
time.sleep(runtime)
self.turn(0)
pass
def turn_to(self, theta, vyaw=60, emax=10):
cur_yaw = self.read_yaw()
des_yaw = self.init_yaw + theta
while abs(des_yaw - cur_yaw) >= emax:
self.turn(math.copysign(vyaw, des_yaw - cur_yaw))
cur_yaw = self.read_yaw()
print(cur_yaw)
self.turn(0)
time.sleep(0.2)
pass
def prepare_for_block(self, x, y, angle, des_x=14, emax_x=1.8, emax_y=1.9, emax_yaw=3.5):
e_x = x - des_x
if angle > emax_yaw:
self.adjust_yaw(-angle)
# if y < 4 and x > 16.5:
# time.sleep(0.3)
# self.adjust_y(2)
elif angle < -emax_yaw:
self.adjust_yaw(-angle)
# if y > -4 and x > 16.5:
# time.sleep(0.3)
# self.adjust_y(-2)
else:
if abs(y) > emax_y:
self.adjust_y(-y)
else:
if abs(e_x) > emax_x:
self.adjust_x(e_x)
else:
print("DONE BLOCK")
self.action(0x83)
time.sleep(7)
self.reset()
time.sleep(0.5)
return True
return False
def prepare_for_cup(self, x1, x2, y1, y2, vx_k, des_x=16, emax_y=1.8):
if abs(y1 + y2) > emax_y:
self.adjust_y(-(y1 + y2) / 2)
time.sleep(0.3)
else:
if 23 < (x1 + x2) / 2 < 60: # 过滤掉误识别数据
self.move_x_by((x1 + x2) / 2 - des_x, k=vx_k, mintime=0.65)
print("DONE CUP")
self.action(0x84)
time.sleep(7)
return True
return False
def cal_block(self, s_x, s_y):
# k1 = 0.00323
# k2 = -1.272
# b = 139.5
# # k1 = 0.002875
# # k2 = -1.061
ky = 0.00574
# b = 108.1
# x = k1 * s_x * s_x + k2 * s_x + b
# y = (ky * x + 0.01) * (s_y - 160)
x = self.block_k1 * s_x * s_x + self.block_k2 * s_x + self.block_b
# y = self.block_ky * (s_y - 160) * x + self.block_by
y = (ky * x + 0.01) * (s_y - 160)
return x, y
def cal_cup(self, width1, width2, cup_y1, cup_y2):
kw1 = 1.453e-05
kw2 = - 1.461e-05
kc1 = 0.0146
kc2 = -1.81
ky = 0.006418
by = -0.007943
bc = 77.71
# 横向畸变
# kwidth1 = kw1 * (cup_y1 - 160) * (cup_y1 - 160) - kw2 * abs(cup_y1 - 160) + 1
# kwidth2 = kw1 * (cup_y2 - 160) * (cup_y2 - 160) - kw2 * abs(cup_y2 - 160) + 1
# width1 = width1 / kwidth1
# width2 = width2 / kwidth2
x1 = self.cup_k1 * width1 * width1 + self.cup_k2 * width1 + self.cup_b
x2 = self.cup_k1 * width2 * width2 + self.cup_k2 * width2 + self.cup_b
y1 = (ky * x1 - by) * (cup_y1 - 160)
y2 = (ky * x2 - by) * (cup_y2 - 160)
return x1, x2, y1, y2
def get_color_mask(self, color):
# if color == 'red':
# color_lower = np.array([173, 90, 46])
# color_upper = np.array([183, 255, 255])
# elif color == 'green':
# color_lower = np.array([73, 150, 70])
# color_upper = np.array([88, 255, 255])
# elif color == 'blue':
# color_lower = np.array([100, 100, 50])
# color_upper = np.array([110, 255, 255])
if color == 'red':
color_lower = (0, 145, 132)
color_upper = (255, 255, 255)
elif color == 'green':
color_lower = (40, 0, 130)
color_upper = (220, 110, 230)
elif color == 'blue':
color_lower = (0, 0, 0)
color_upper = (255, 136, 120)
return color_upper, color_lower
def filter_img(self, frame, color):
# if color == 'green':
# frame_gb = cv2.GaussianBlur(frame, (3, 3), 1)
# hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
# color_upper, color_lower = self.get_color_mask(color)
# mask = cv2.inRange(hsv, color_lower, color_upper)
# else:
frame = cv2.GaussianBlur(frame, (3, 3), 1)
color_upper, color_lower = self.get_color_mask(color)
frame_lab = cv2.cvtColor(frame, cv2.COLOR_BGR2LAB)
mask = cv2.inRange(frame_lab, color_lower, color_upper)
img_mask = cv2.bitwise_and(frame, frame, mask=mask)
return img_mask
def detect_contours(self, frame, color):
img_mask = self.filter_img(frame, color)
CANNY_THRESH_1 = 15
CANNY_THRESH_2 = 120
edges = cv2.Canny(img_mask, CANNY_THRESH_1, CANNY_THRESH_2)
edges = cv2.dilate(edges, None, iterations=1)
edges = cv2.erode(edges, None, iterations=1)
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
return contours, img_mask
def detect_block(self, contours):
flag = False
length, width, angle, s_x, s_y = 0, 0, 0, 0, 0
for i in range(0, len(contours)):
if cv2.contourArea(contours[i]) < 20 ** 2:
continue
rect = cv2.minAreaRect(contours[i])
if 0.5 < rect[1][0] / rect[1][1] < 2:
continue
if not flag:
if rect[2] > 45:
length = rect[1][0]
width = rect[1][1]
angle = rect[2] - 90
else:
length = rect[1][1]
width = rect[1][0]
angle = rect[2]
s_x = rect[0][1] # s_代表屏幕坐标系
s_y = rect[0][0]
flag = True
else: # 识别出两个及以上的矩形退出
flag = False
break
return flag, length, width, angle, s_x, s_y
def detect_cup(self, contours):
num = 0
width1, width2, s_y1, s_y2 = 0, 0, 0, 0
index = [0, 0]
flag = True
for i in range(0, len(contours)):
if cv2.contourArea(contours[i]) < 15 ** 2:
continue
rect = cv2.minAreaRect(contours[i])
if 0.5 < rect[1][0] / rect[1][1] < 2:
if num == 2:
flag = False
break
index[num] = i
num += 1
if flag and num == 2:
c1 = contours[index[0]]
c2 = contours[index[1]]
rect1 = cv2.minAreaRect(c1)
rect2 = cv2.minAreaRect(c2)
if rect1[2] > 45:
width1 = rect1[1][1]
else:
width1 = rect1[1][0]
if rect2[2] > 45:
width2 = rect2[1][1]
else:
width2 = rect2[1][0]
s_y1 = rect1[0][0]
s_y2 = rect2[0][0]
else:
flag = False
return flag, width1, width2, s_y1, s_y2
'''
def detect_single_cup(self,contours):
'''
def detect_single_cup(self, contours):
flag = False
length, width, angle, s_x, s_y = 0, 0, 0, 0, 0
for i in range(0, len(contours)):
if cv2.contourArea(contours[i]) < 15 ** 2:
continue
rect = cv2.minAreaRect(contours[i])
if not (0.5 < rect[1][0] / rect[1][1] < 2):
continue
if not flag:
if rect[2] > 45:
length = rect[1][0]
width = rect[1][1]
angle = rect[2] - 90
else:
length = rect[1][1]
width = rect[1][0]
angle = rect[2]
s_x = rect[0][1]
s_y = rect[0][0]
flag = True
else:
flag = False
break
return flag, width, s_y
def search_for_block(self, color, COUNT_MAX=25):
count = 0
length, width, angle, s_x, s_y = 0, 0, 0, 0, 0
x, y = 0, 0
self.attitude('p', 10)
while True:
#ret, frame = self.cap.read()
ret, frame = cap.read()
self.check_quit()
contours, img = self.detect_contours(frame, color)
flag, temp_length, temp_width, temp_angle, temp_s_x, temp_s_y = self.detect_block(contours)
if not flag:
self.show_img(img)
continue
cv2.putText(img, '%4.1f' % temp_s_x, (20, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
cv2.putText(img, '%4.1f' % temp_s_y, (20, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
cv2.putText(img, '%4.1f' % temp_angle, (20, 80), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
cv2.putText(img, '%4.1f' % x, (20, 130), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
cv2.putText(img, '%4.1f' % y, (20, 160), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
self.show_img(img)
count += 1
length = (count - 1) * length / count + temp_length / count
width = (count - 1) * width / count + temp_width / count
angle = (count - 1) * angle / count + temp_angle / count
s_x = (count - 1) * s_x / count + temp_s_x / count
s_y = (count - 1) * s_y / count + temp_s_y / count
if count == COUNT_MAX:
count = 0
x, y = self.cal_block(s_x, s_y)
print("block position x: %4.1f, y: %4.1f" % (x, y))
done = self.prepare_for_block(x, y, angle)
if done:
break
'''
def search_for_block_two_color(self,color1,color2,COUNT_MAX=25):
'''
def search_for_block_two_color(self, color1, color2, COUNT_MAX=25):
count = 0
length, width, angle, s_x, s_y = 0, 0, 0, 0, 0
x, y = 0, 0
self.attitude('p', 10)
while True:
ret, frame = cap.read()
self.check_quit()
contours, img = self.detect_contours(frame, color1)
flag, temp_length, temp_width, temp_angle, temp_s_x, temp_s_y = self.detect_block(contours)
if not flag:
contours, img = self.detect_contours(frame, color2)
flag, temp_length, temp_width, temp_angle, temp_s_x, temp_s_y = self.detect_block(contours)
if not flag:
self.show_img(img)
continue
def search_for_cup(self, color, COUNT_MAX=25, direction=0, k=0.035):
count = 0
width1, width2, s_y1, s_y2 = 0, 0, 0, 0
x1, x2, y1, y2 = 0, 0, 0, 0
while True:
self.check_quit()
#ret, frame = self.cap.read()
ret, frame = cap.read()
contours, img = self.detect_contours(frame, color)
flag, temp_width1, temp_width2, temp_s_y1, temp_s_y2 = self.detect_cup(contours)
if not flag:
self.show_img(img)
continue
# cv2.putText(img, '%4.1f' % temp_width1, (20, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
# cv2.putText(img, '%4.1f' % temp_width2, (90, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
# cv2.putText(img, '%4.1f' % temp_s_y1, (20, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
# cv2.putText(img, '%4.1f' % temp_s_y2, (90, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
cv2.putText(img, '%4.1f' % x1, (20, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
cv2.putText(img, '%4.1f' % x2, (90, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
cv2.putText(img, '%4.1f' % y1, (20, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
cv2.putText(img, '%4.1f' % y2, (90, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
self.show_img(img)
count += 1
width1 = (count - 1) * width1 / count + temp_width1 / count
width2 = (count - 1) * width2 / count + temp_width2 / count
s_y1 = (count - 1) * s_y1 / count + temp_s_y1 / count
s_y2 = (count - 1) * s_y2 / count + temp_s_y2 / count
if count == COUNT_MAX:
count = 0
x1, x2, y1, y2 = self.cal_cup(width1, width2, s_y1, s_y2)
print("x1: %4.2f, x2: %4.2f, y1: %4.2f, y2: %4.2f" % (x1, x2, y1, y2))
done = False
done = self.prepare_for_cup(x1, x2, y1, y2, vx_k=k)
if direction != 0:
self.turn_to(direction, vyaw=30, emax=2)
if done:
break
'''
def search_for_cup_two_color(self,color1,color2,COUNT_MAX=25):
'''
def search_for_cup_two_color(self, color1, color2, COUNT_MAX=25, direction=0, k=0.035):
count = 0
width1, width2, s_y1, s_y2 = 0, 0, 0, 0
x1, x2, y1, y2 = 0, 0, 0, 0
while True:
self.check_quit()
ret, frame = cap.read()
contours, img = self.detect_contours(frame, color1)
flag, temp_width1, temp_width2, temp_s_y1, temp_s_y2 = self.detect_cup(contours)
if not flag:
contours, img = self.detect_contours(frame, color2)
flag, temp_width1, temp_width2, temp_s_y1, temp_s_y2 = self.detect_cup(contours)
if not flag:
self.show_img(img)
continue
cv2.putText(img, '%4.1f' % x1, (20, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
cv2.putText(img, '%4.1f' % x2, (90, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
cv2.putText(img, '%4.1f' % y1, (20, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
cv2.putText(img, '%4.1f' % y2, (90, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
self.show_img(img)
count += 1
width1 = (count - 1) * width1 / count + temp_width1 / count
width2 = (count - 1) * width2 / count + temp_width2 / count
s_y1 = (count - 1) * s_y1 / count + temp_s_y1 / count
s_y2 = (count - 1) * s_y2 / count + temp_s_y2 / count
if count == COUNT_MAX:
count = 0
x1, x2, y1, y2 = self.cal_cup(width1, width2, s_y1, s_y2)
print("x1: %4.2f, x2: %4.2f, y1: %4.2f, y2: %4.2f" % (x1, x2, y1, y2))
done = False
done = self.prepare_for_cup(x1, x2, y1, y2, vx_k=k)
if direction != 0:
self.turn_to(direction, vyaw=30, emax=2)
if done:
break
'''
def search_for_cip_CQ(self,color1,color2,COUNT_MAX=25,direction=0,k=0.035)
'''
def search_for_cup_CQ(self, color1, color2, COUNT_MAX=25, direction=0, k=0.035):
count = 0
width1, width2, s_y1, s_y2 = 0, 0, 0, 0
x1, x2, y1, y2 = 0, 0, 0, 0
while True:
self.check_quit()
ret, frame = cap.read()
contours, img = self.detect_contours(frame, color1)
flag, temp_width1, temp_s_y1 = self.detect_single_cup(contours)
if not flag:
self.show_img(img)
continue
ret, frame = cap.read()
contours, img = self.detect_contours(frame, color2)
flag, temp_width2, temp_s_y2 = self.detect_single_cup(contours)
if not flag:
self.show_img(img)
continue
cv2.putText(img, '%4.1f' % x1, (20, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
cv2.putText(img, '%4.1f' % x2, (90, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
cv2.putText(img, '%4.1f' % y1, (20, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
cv2.putText(img, '%4.1f' % y2, (90, 50), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
self.show_img(img)
count += 1
width1 = (count - 1) * width1 / count + temp_width1 / count
width2 = (count - 1) * width2 / count + temp_width2 / count
s_y1 = (count - 1) * s_y1 / count + temp_s_y1 / count
s_y2 = (count - 1) * s_y2 / count + temp_s_y2 / count
if count == COUNT_MAX:
count = 0
x1, x2, y1, y2 = self.cal_cup(width1, width2, s_y1, s_y2)
print("x1: %4.2f, x2: %4.2f, y1: %4.2f, y2: %4.2f" % (x1, x2, y1, y2))
done = False
done = self.prepare_for_cup(x1, x2, y1, y2, vx_k=k)
if direction != 0:
self.turn_to(direction, vyaw=30, emax=2)
if done:
break
def calibration_block(self, color, COUNT_MAX=25):
count = 0
block_num = 0
state = 0
path = 'calibration.json'
s_x = 0
s_y = 0
s_x_list = [186, 174.5, 163.5, 150.5, 143.5, 138.5, 131.5, 125.6]
x_list = [13, 15, 17, 20, 22, 24, 27, 30]
ky_list = []
y_list = [2.25, 0.25, -1.75, 0.25, 2.25, 0.25, -1.75, 0.25]
kx_list = []
#机器狗俯身
self.attitude('p', 10)
while True:
self.check_quit()
#ret为是否补货成功,frame为捕获的每一帧图像
#ret, frame = self.cap.read()
ret, frame = cap.read()
contours, img = self.detect_contours(frame, color)
if state == 0:
cv2.putText(img, 'Put BLOCK in', (50, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (200, 0, 200), 2)
cv2.putText(img, '- ' + str(block_num + 1) + ' -', (50, 100), cv2.FONT_HERSHEY_SIMPLEX, 2,
(200, 0, 200), 2)
cv2.putText(img, 'Then press D(up right)', (30, 170), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
self.show_img(img)
button = XGOEDU()
if button.xgoButton("d"):
state = 1
time.sleep(0.5)
elif state == 1:
flag, temp_length, temp_width, temp_angle, temp_s_x, temp_s_y = self.detect_block(contours)
if not flag:
self.show_img(img)
continue
cv2.putText(img, 'Detecting......', (30, 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (200, 0, 200), 2)
cv2.putText(img, '%4.1f' % temp_s_x, (30, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
cv2.putText(img, '%4.1f' % temp_s_y, (30, 100), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
self.show_img(img)
count += 1
s_x = s_x * (count - 1) / count + temp_s_x / count
s_y = s_y * (count - 1) / count + temp_s_y / count
if count == COUNT_MAX:
count = 0
s_x_list.append(s_x)
s_x_list.append(s_x)
ky_list.append(y_list[block_num])
kx_list.append((s_y - 160) * (14 + block_num * 3))
x_list.append(14 + block_num * 3)
x_list.append(14 + block_num * 3)
block_num += 1
state = 0
print("Finish" + str(block_num))
if block_num == 8:
z = np.polyfit(s_x_list, x_list, 2)
self.calibration["BLOCK_k1"] = z[0]
self.calibration["BLOCK_k2"] = z[1]
self.calibration["BLOCK_b"] = z[2]
z = np.polyfit(kx_list, ky_list, 1)
self.calibration["BLOCK_ky"] = z[0]
self.calibration["BLOCK_by"] = z[1]
break
def calibration_cup(self, color, COUNT_MAX=25):
count = 0
cap_num = 0
state = 0
path = 'calibration.json'
width1 = 0
width2 = 0
width_list = []
x_list = []
while True:
self.check_quit()
#ret, frame = self.cap.read()
ret, frame = cap.read()
contours, img = self.detect_contours(frame, color)
if state == 0:
cv2.putText(img, 'Put Two Cups In', (50, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (200, 0, 200), 2)
cv2.putText(img, '- ' + str(cap_num + 1) + ' -', (50, 100), cv2.FONT_HERSHEY_SIMPLEX, 2,
(200, 0, 200), 2)
cv2.putText(img, 'Then press D(up right)', (30, 170), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 0, 200), 2)
self.show_img(img)
button = XGOEDU()
if button.xgoButton("d"):
state = 1
time.sleep(0.5)
elif state == 1:
flag, temp_width1, temp_width2, temp_s_y1, temp_s_y2 = self.detect_cup(contours)
if not flag:
self.show_img(img)
continue
cv2.putText(img, 'Detecting......', (30, 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (200, 0, 200), 2)
self.show_img(img)
count += 1
width1 = width1 * (count - 1) / count + temp_width1 / count
width2 = width2 * (count - 1) / count + temp_width2 / count
if count == COUNT_MAX:
count = 0
width_list.append(width1)
width_list.append(width2)
x_list.append(24.7 + cap_num * 2)
x_list.append(24.7 + cap_num * 2)
cap_num += 1
state = 0
print("Finish" + str(cap_num))
if cap_num == 8:
z = np.polyfit(width_list, x_list, 2)
self.calibration["CUP_k1"] = z[0]
self.calibration["CUP_k2"] = z[1]
self.calibration["CUP_b"] = z[2]
with open(path, 'w', encoding='utf-8') as f:
json.dump(self.calibration, f)
break
def calibration_contest(self, color='red'):
self.calibration_block(color)
self.reset()
time.sleep(1)
self.calibration_cup(color)
def show_filter_img(self, color):
while True:
#ret, frame = self.cap.read()
ret, frame = cap.read()
img = self.filter_img(frame, color)
self.show_img(img)
self.check_quit()
class XGOEDU():
def __init__(self):
self.key1=17
self.key2=22
self.key3=23
self.key4=24
GPIO.setup(self.key1,GPIO.IN,GPIO.PUD_UP)
GPIO.setup(self.key2,GPIO.IN,GPIO.PUD_UP)
GPIO.setup(self.key3,GPIO.IN,GPIO.PUD_UP)
GPIO.setup(self.key4,GPIO.IN,GPIO.PUD_UP)
#画布初始化
def lcd_init(self,color):
if color == "black":
splash = Image.new("RGB",(320,240),"black")
elif color == "white":
splash = Image.new("RGB",(320,240),"white")
elif color == "red":
splash = Image.new("RGB",(320,240),"red")
elif color == "green":
splash = Image.new("RGB",(320,240),"green")
elif color == "blue":
splash = Image.new("RGB",(320,240),"blue")
display.ShowImage(splash)
#绘画直线
'''
x1,y1为初始点坐标,x2,y2为终止点坐标
'''
def lcd_line(self,x1,y1,x2,y2):
draw = ImageDraw.Draw(splash)
draw.line([(x1,y1),(x2,y2)],fill = "WHITE",width = 2)
display.ShowImage(splash)
#绘画圆
'''
x1,y1,x2,y2为定义给定边框的两个点,angle0为初始角度,angle1为终止角度
'''
def lcd_circle(self,x1,y1,x2,y2,angle0,angle1):
draw = ImageDraw.Draw(splash)
draw.arc((x1,y1,x2,y2),angle0,angle1,fill=(255,255,255),width = 2)
display.ShowImage(splash)
#绘画矩形
'''
x1,y1为初始点坐标,x2,y2为对角线终止点坐标
'''
def lcd_rectangle(self,x1,y1,x2,y2):
draw = ImageDraw.Draw(splash)
draw.rectangle((x1,y1,x2,y2),fill = None,outline = "WHITE",width = 2)
display.ShowImage(splash)
#清除屏幕
def lcd_clear(self):
splash = Image.new("RGB",(320,240),"black")
display.ShowImage(splash)
#显示图片
'''
图片的大小为320*240,jpg格式
'''
def lcd_picture(self,filename):
image = Image.open(filename)
display.ShowImage(image)
#显示文字
'''
font1为载入字体,微软雅黑
目前支持英文和数字,暂不支持中文
'''
def lcd_text(self,x1,y1,content):
draw = ImageDraw.Draw(splash)
draw.text((x1,y1),content,fill = "WHITE",font=font1)
display.ShowImage(splash)
#key_value
'''
a左上按键
b右上按键
c左下按键
d右下按键
返回值 0未按下,1按下
'''
def xgoButton(self,Button):
if Button == "a":
last_state_a =GPIO.input(self.key1)
time.sleep(0.02)
return(not last_state_a)
elif Button == "b":
last_state_b=GPIO.input(self.key2)
time.sleep(0.02)
return(not last_state_b)
elif Button == "c":
last_state_c=GPIO.input(self.key3)
time.sleep(0.02)
return(not last_state_c)
elif Button == "d":
last_state_d=GPIO.input(self.key4)
time.sleep(0.02)
return(not last_state_d)
#speaker
'''
filename 文件名 字符串
'''
def xgoSpeaker(self,filename):
os.system("mplayer"+" "+filename)
#audio_record
'''
filename 文件名 字符串
seconds 录制时间S 字符串
'''
def xgoAudioRecord(self,filename,seconds):
command1 = "sudo arecord -D hw:1,0 -d"
command2 = "-f S32_LE -r 16000 -c 2"
os.system(command1+" "+seconds+" "+command2+" "+filename)
'''
开启摄像头
'''
def cameraOn(self):
while True:
success,image = cap.read()
if not success:
print("Ignoring empty camera frame")
continue
#cv2.imshow('frame',image)
b,g,r = cv2.split(image)
image = cv2.merge((r,g,b))
image = cv2.flip(image,1)
imgok = Image.fromarray(image)
display.ShowImage(imgok)
if cv2.waitKey(5) & 0xFF == 27:
XGOEDU.lcd_clear(self)
time.sleep(0.5)
break
if XGOEDU.xgoButton(self,"c"):
XGOEDU.lcd_clear(self)
time.sleep(0.5)
break
'''
开启摄像头并拍照
'''
def takePhoto(self):
while True:
success,image = cap.read()
if not success:
print("Ignoring empty camera frame")
continue
cv2.imshow('frame',image)
cv2.imwrite('/home/pi/xgoEdu/camera/file.jpg',image)
b,g,r = cv2.split(image)
image = cv2.merge((r,g,b))
image = cv2.flip(image,1)
imgok = Image.fromarray(image)
display.ShowImage(imgok)
if cv2.waitKey(5) & 0xFF == 27: # esc 键 推出
XGOEDU.lcd_clear(self)
time.sleep(0.5)
break
if XGOEDU.xgoButton(self,"c"): # 设备C返回键
XGOEDU.lcd_clear(self)
time.sleep(0.5)
break
'''
手势识别
'''
def gestureRecognition(self):
hand = hands(0,2,0.6,0.5)
while True:
success,image = cap.read()
datas = hand.run(image)
cv2.imshow('OpenCV',image)
b,g,r = cv2.split(image)
image = cv2.merge((r,g,b))
image = cv2.flip(image,1)
if not success:
print("Ignoring empty camera frame")
continue
for data in datas:
pos_left = ''
pos_right = ''
rect = data['rect']
right_left = data['right_left']
center = data['center']
dlandmark = data['dlandmark']
hand_angle = data['hand_angle']
XGOEDU.rectangle(self,image,rect,"#33cc00",2)
#XGOEDU.text(self,image,right_left,center,2,"#cc0000",5)
if right_left == 'L':
XGOEDU.text(self,image,hand_pos(hand_angle),(180,80),1.5,"#33cc00",2)
pos_left = hand_pos(hand_angle)
elif right_left == 'R':
XGOEDU.text(self,image,hand_pos(hand_angle),(50,80),1.5,"#ff0000",2)
pos_right = hand_pos(hand_angle)
for i in dlandmark:
XGOEDU.circle(self,image,i,3,"#ff9900",-1)
imgok = Image.fromarray(image)
display.ShowImage(imgok)
if cv2.waitKey(5) & 0xFF == 27:
XGOEDU.lcd_clear(self)
time.sleep(0.5)
break
if XGOEDU.xgoButton(self,"c"):
XGOEDU.lcd_clear(self)
time.sleep(0.5)
break
#return(pos_left,pos_right)
'''
yolo
'''
def yoloFast(self):
yolo = yoloXgo('/home/pi/xgoEdu/model/Model.onnx',
['person','bicycle','car','motorbike','aeroplane','bus','train','truck','boat','traffic light','fire hydrant','stop sign','parking meter','bench','bird','cat','dog','horse','sheep','cow','elephant','bear','zebra','giraffe','backpack','umbrella','handbag','tie','suitcase','frisbee','skis','snowboard','sports ball','kite','baseball bat','baseball glove','skateboard','surfboard','tennis racket','bottle','wine glass','cup','fork','knife','spoon','bowl','banana','apple','sandwich','orange','broccoli','carrot','hot dog','pizza','donut','cake','chair','sofa','pottedplant','bed','diningtable','toilet','tvmonitor','laptop','mouse','remote','keyboard','cell phone','microwave','oven','toaster','sink','refrigerator','book','clock','vase','scissors','teddy bear','hair drier','toothbrush'],
[352,352],0.6)
while True:
success,image = cap.read()
datas = yolo.run(image)
cv2.imshow('OpenCV',image)
b,g,r = cv2.split(image)
image = cv2.merge((r,g,b))
image = cv2.flip(image,1)
if not success:
print("Ignoring empty camera frame")
continue
if datas:
for data in datas:
XGOEDU.rectangle(self,image,data['xywh'],"#33cc00",2)
xy= (data['xywh'][0], data['xywh'][1])
XGOEDU.text(self,image,data['classes'],xy,1,"#ff0000",2)
value_yolo = data['classes']
imgok = Image.fromarray(image)4
display.ShowImage(imgok)
#return(value_yolo)
if cv2.waitKey(5) & 0xFF == 27:
XGOEDU.lcd_clear(self)
time.sleep(0.5)
break
if XGOEDU.xgoButton(self,"c"):
XGOEDU.lcd_clear(self)
time.sleep(0.5)
break
'''
人脸坐标点检测
'''
def face_detect(self):
face = face_detection(0.7)
while True:
success,image = cap.read()
datas = face.run(image)
b,g,r = cv2.split(image)
image = cv2.merge((r,g,b))
image = cv2.flip(image,1)
if not success:
print("Ignoring empty camera frame")
continue
for data in datas:
print(data)
lefteye = str(data['left_eye'])
righteye = str(data['right_eye'])
nose = str(data['nose'])
mouth = str(data['mouth'])
leftear = str(data['left_ear'])
rightear = str(data['right_ear'])
cv2.putText(image,'lefteye',(10,30),cv2.FONT_HERSHEY_SIMPLEX,0.7,(255,0,0),2)
cv2.putText(image,lefteye,(100,30),cv2.FONT_HERSHEY_SIMPLEX,0.7,(255,0,0),2)
cv2.putText(image,'righteye',(10,50),cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,255,0),2)
cv2.putText(image,righteye,(100,50),cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,255,0),2)
cv2.putText(image,'nose',(10,70),cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,0,255),2)
cv2.putText(image,nose,(100,70),cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,0,255),2)
cv2.putText(image,'leftear',(10,90),cv2.FONT_HERSHEY_SIMPLEX,0.7,(255,255,0),2)
cv2.putText(image,leftear,(100,90),cv2.FONT_HERSHEY_SIMPLEX,0.7,(255,255,0),2)
cv2.putText(image,'rightear',(10,110),cv2.FONT_HERSHEY_SIMPLEX,0.7,(200,0,200),2)
cv2.putText(image,rightear,(100,110),cv2.FONT_HERSHEY_SIMPLEX,0.7,(200,0,200),2)
XGOEDU.rectangle(self,image,data['rect'],"#33cc00",2)
#cv2.imshow('OpenCV',image)
imgok = Image.fromarray(image)
display.ShowImage(imgok)
if cv2.waitKey(5) & 0xFF == 27:
XGOEDU.lcd_clear(self)
time.sleep(0.5)
break
if XGOEDU.xgoButton(self,"c"):
XGOEDU.lcd_clear(self)
time.sleep(0.5)
break
'''
情绪识别
'''
def emotion(self):
while True:
success,image=cap.read()
labels=[]
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
faces=face_classifier.detectMultiScale(gray,1.3,5)
label=''
for (x,y,w,h) in faces:
cv2.rectangle(image,(x,y),(x+w,y+h),(255,0,0),2)
roi_gray=gray[y:y+h,x:x+w]
roi_gray=cv2.resize(roi_gray,(48,48),interpolation=cv2.INTER_AREA)
if np.sum([roi_gray])!=0:
roi=roi_gray.astype('float')/255.0
roi=img_to_array(roi)
roi=np.expand_dims(roi,axis=0)
preds=classifier.predict(roi)[0]
label=class_labels[preds.argmax()]
print(label)
label_position=(x,y)
else:
pass
b,g,r = cv2.split(image)
image = cv2.merge((r,g,b))
image = cv2.flip(image, 1)
try:
cv2.putText(image,label,label_position,cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),3)
except:
pass
imgok = Image.fromarray(image)
display.ShowImage(imgok)
if cv2.waitKey(5) & 0xFF == 27:
XGOEDU.lcd_clear(self)
time.sleep(0.5)
break
if XGOEDU.xgoButton(self,"c"):
XGOEDU.lcd_clear(self)
time.sleep(0.5)
break
'''
年纪及性别检测
'''
def agesex(self):
while True:
t = time.time()
hasFrame,image = cap.read()
image = cv.flip(image, 1)
frameFace, bboxes = getFaceBox(faceNet, image)
if not bboxes:
print("No face Detected, Checking next frame")
gender=''
age=''
for bbox in bboxes:
face = image[max(0, bbox[1] - padding):min(bbox[3] + padding, image.shape[0] - 1),
max(0, bbox[0] - padding):min(bbox[2] + padding, image.shape[1] - 1)]
blob = cv.dnn.blobFromImage(face, 1.0, (227, 227), MODEL_MEAN_VALUES, swapRB=False)
genderNet.setInput(blob)
genderPreds = genderNet.forward()
gender = genderList[genderPreds[0].argmax()]
ageNet.setInput(blob)
agePreds = ageNet.forward()
age = ageList[agePreds[0].argmax()]
label = "{},{}".format(gender, age)
cv.putText(frameFace, label, (bbox[0], bbox[1] - 10), cv.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 255), 2,cv.LINE_AA)
b,g,r = cv2.split(frameFace)
frameFace = cv2.merge((r,g,b))
imgok = Image.fromarray(frameFace)
display.ShowImage(imgok)
if cv2.waitKey(5) & 0xFF == 27:
XGOEDU.lcd_clear(self)
time.sleep(0.5)
break
if XGOEDU.xgoButton(self,"c"):
XGOEDU.lcd_clear(self)
time.sleep(0.5)
break
def rectangle(self,frame,z,colors,size):
frame=cv2.rectangle(frame,(int(z[0]),int(z[1])),(int(z[0]+z[2]),int(z[1]+z[3])),color(colors),size)
return frame
def circle(self,frame,xy,rad,colors,tk):
frame=cv2.circle(frame,xy,rad,color(colors),tk)
return frame
def text(self,frame,text,xy,font_size,colors,size):
frame=cv2.putText(frame,text,xy,cv2.FONT_HERSHEY_SIMPLEX,font_size,color(colors),size)
return frame
class hands():
def __init__(self,model_complexity,max_num_hands,min_detection_confidence,min_tracking_confidence):
self.model_complexity = model_complexity
self.max_num_hands = max_num_hands
self.min_detection_confidence = min_detection_confidence
self.min_tracking_confidence = min_tracking_confidence
self.mp_hands = mp.solutions.hands
self.hands = self.mp_hands.Hands(
max_num_hands=self.max_num_hands,
min_detection_confidence=self.min_detection_confidence,
min_tracking_confidence=self.min_tracking_confidence,
)
def run(self,cv_img):
image = cv_img
debug_image = copy.deepcopy(image)
image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
results = self.hands.process(image)
hf=[]
if results.multi_hand_landmarks is not None:
for hand_landmarks, handedness in zip(results.multi_hand_landmarks,
results.multi_handedness):
# 手的重心计算
cx, cy = self.calc_palm_moment(debug_image, hand_landmarks)
# 手的外接矩形计算
rect = self.calc_bounding_rect(debug_image, hand_landmarks)
# 手的个关键点
dlandmark = self.dlandmarks(debug_image,hand_landmarks,handedness)
hf.append({'center':(cx,cy),'rect':rect,'dlandmark':dlandmark[0],'hand_angle':self.hand_angle(dlandmark[0]),'right_left':dlandmark[1]})
return hf
def calc_palm_moment(self, image, landmarks):
image_width, image_height = image.shape[1], image.shape[0]
palm_array = np.empty((0, 2), int)
for index, landmark in enumerate(landmarks.landmark):
landmark_x = min(int(landmark.x * image_width), image_width - 1)
landmark_y = min(int(landmark.y * image_height), image_height - 1)
landmark_point = [np.array((landmark_x, landmark_y))]
if index == 0: # 手首1
palm_array = np.append(palm_array, landmark_point, axis=0)
if index == 1: # 手首2
palm_array = np.append(palm_array, landmark_point, axis=0)
if index == 5: # 人差指:付け根
palm_array = np.append(palm_array, landmark_point, axis=0)
if index == 9: # 中指:付け根
palm_array = np.append(palm_array, landmark_point, axis=0)
if index == 13: # 薬指:付け根
palm_array = np.append(palm_array, landmark_point, axis=0)
if index == 17: # 小指:付け根
palm_array = np.append(palm_array, landmark_point, axis=0)
M = cv.moments(palm_array)
cx, cy = 0, 0
if M['m00'] != 0:
cx = int(M['m10'] / M['m00'])
cy = int(M['m01'] / M['m00'])
return cx, cy
def calc_bounding_rect(self, image, landmarks):
image_width, image_height = image.shape[1], image.shape[0]
landmark_array = np.empty((0, 2), int)
for _, landmark in enumerate(landmarks.landmark):
landmark_x = min(int(landmark.x * image_width), image_width - 1)
landmark_y = min(int(landmark.y * image_height), image_height - 1)
landmark_point = [np.array((landmark_x, landmark_y))]
landmark_array = np.append(landmark_array, landmark_point, axis=0)
x, y, w, h = cv.boundingRect(landmark_array)
return [x, y, w, h]
def dlandmarks(self,image, landmarks, handedness):
image_width, image_height = image.shape[1], image.shape[0]
landmark_point = []
for index, landmark in enumerate(landmarks.landmark):
if landmark.visibility < 0 or landmark.presence < 0:
continue
landmark_x = min(int(landmark.x * image_width), image_width - 1)
landmark_y = min(int(landmark.y * image_height), image_height - 1)
landmark_point.append((landmark_x, landmark_y))
return landmark_point,handedness.classification[0].label[0]
def vector_2d_angle(self, v1, v2):
v1_x = v1[0]
v1_y = v1[1]
v2_x = v2[0]
v2_y = v2[1]
try:
angle_= math.degrees(math.acos((v1_x*v2_x+v1_y*v2_y)/(((v1_x**2+v1_y**2)**0.5)*((v2_x**2+v2_y**2)**0.5))))
except:
angle_ = 180
return angle_
def hand_angle(self,hand_):
angle_list = []
# thumb 大拇指角度
angle_ = self.vector_2d_angle(
((int(hand_[0][0])- int(hand_[2][0])),(int(hand_[0][1])-int(hand_[2][1]))),
((int(hand_[3][0])- int(hand_[4][0])),(int(hand_[3][1])- int(hand_[4][1])))
)
angle_list.append(angle_)
# index 食指角度
angle_ = self.vector_2d_angle(
((int(hand_[0][0])-int(hand_[6][0])),(int(hand_[0][1])- int(hand_[6][1]))),
((int(hand_[7][0])- int(hand_[8][0])),(int(hand_[7][1])- int(hand_[8][1])))
)
angle_list.append(angle_)
# middle 中指角度
angle_ = self.vector_2d_angle(
((int(hand_[0][0])- int(hand_[10][0])),(int(hand_[0][1])- int(hand_[10][1]))),
((int(hand_[11][0])- int(hand_[12][0])),(int(hand_[11][1])- int(hand_[12][1])))
)
angle_list.append(angle_)
# ring 無名指角度
angle_ = self.vector_2d_angle(
((int(hand_[0][0])- int(hand_[14][0])),(int(hand_[0][1])- int(hand_[14][1]))),
((int(hand_[15][0])- int(hand_[16][0])),(int(hand_[15][1])- int(hand_[16][1])))
)
angle_list.append(angle_)
# pink 小拇指角度
angle_ = self.vector_2d_angle(
((int(hand_[0][0])- int(hand_[18][0])),(int(hand_[0][1])- int(hand_[18][1]))),
((int(hand_[19][0])- int(hand_[20][0])),(int(hand_[19][1])- int(hand_[20][1])))
)
angle_list.append(angle_)
return angle_list
class yoloXgo():
def __init__(self,model,classes,inputwh,thresh):
self.session = onnxruntime.InferenceSession(model)
self.input_width=inputwh[0]
self.input_height=inputwh[1]
self.thresh=thresh
self.classes=classes
def sigmoid(self,x):
return 1. / (1 + np.exp(-x))
# tanh函数
def tanh(self,x):
return 2. / (1 + np.exp(-2 * x)) - 1
# 数据预处理
def preprocess(self,src_img, size):
output = cv2.resize(src_img,(size[0], size[1]),interpolation=cv2.INTER_AREA)
output = output.transpose(2,0,1)
output = output.reshape((1, 3, size[1], size[0])) / 255
return output.astype('float32')
# nms算法
def nms(self,dets,thresh=0.45):
# dets:N*M,N是bbox的个数,M的前4位是对应的(x1,y1,x2,y2),第5位是对应的分数
# #thresh:0.3,0.5....
x1 = dets[:, 0]
y1 = dets[:, 1]
x2 = dets[:, 2]
y2 = dets[:, 3]
scores = dets[:, 4]
areas = (x2 - x1 + 1) * (y2 - y1 + 1) # 求每个bbox的面积
order = scores.argsort()[::-1] # 对分数进行倒排序
keep = [] # 用来保存最后留下来的bboxx下标
while order.size > 0:
i = order[0] # 无条件保留每次迭代中置信度最高的bbox
keep.append(i)
# 计算置信度最高的bbox和其他剩下bbox之间的交叉区域
xx1 = np.maximum(x1[i], x1[order[1:]])
yy1 = np.maximum(y1[i], y1[order[1:]])
xx2 = np.minimum(x2[i], x2[order[1:]])
yy2 = np.minimum(y2[i], y2[order[1:]])
# 计算置信度高的bbox和其他剩下bbox之间交叉区域的面积
w = np.maximum(0.0, xx2 - xx1 + 1)
h = np.maximum(0.0, yy2 - yy1 + 1)
inter = w * h
# 求交叉区域的面积占两者(置信度高的bbox和其他bbox)面积和的必烈
ovr = inter / (areas[i] + areas[order[1:]] - inter)
# 保留ovr小于thresh的bbox,进入下一次迭代。
inds = np.where(ovr <= thresh)[0]
# 因为ovr中的索引不包括order[0]所以要向后移动一位
order = order[inds + 1]
output = []
for i in keep:
output.append(dets[i].tolist())
return output
def run(self, img,):
pred = []
# 输入图像的原始宽高
H, W, _ = img.shape
# 数据预处理: resize, 1/255
data = self.preprocess(img, [self.input_width, self.input_height])
# 模型推理
input_name = self.session.get_inputs()[0].name
feature_map = self.session.run([], {input_name: data})[0][0]
# 输出特征图转置: CHW, HWC
feature_map = feature_map.transpose(1, 2, 0)
# 输出特征图的宽高
feature_map_height = feature_map.shape[0]
feature_map_width = feature_map.shape[1]
# 特征图后处理
for h in range(feature_map_height):
for w in range(feature_map_width):
data = feature_map[h][w]
# 解析检测框置信度
obj_score, cls_score = data[0], data[5:].max()
score = (obj_score ** 0.6) * (cls_score ** 0.4)
# 阈值筛选
if score > self.thresh:
# 检测框类别
cls_index = np.argmax(data[5:])
# 检测框中心点偏移
x_offset, y_offset = self.tanh(data[1]), self.tanh(data[2])
# 检测框归一化后的宽高
box_width, box_height = self.sigmoid(data[3]), self.sigmoid(data[4])
# 检测框归一化后中心点
box_cx = (w + x_offset) / feature_map_width
box_cy = (h + y_offset) / feature_map_height
# cx,cy,w,h => x1, y1, x2, y2
x1, y1 = box_cx - 0.5 * box_width, box_cy - 0.5 * box_height
x2, y2 = box_cx + 0.5 * box_width, box_cy + 0.5 * box_height
x1, y1, x2, y2 = int(x1 * W), int(y1 * H), int(x2 * W), int(y2 * H)
pred.append([x1, y1, x2, y2, score, cls_index])
datas=np.array(pred)
data=[]
if len(datas)>0:
boxes=self.nms(datas)
for b in boxes:
obj_score, cls_index = b[4], int(b[5])
x1, y1, x2, y2 = int(b[0]), int(b[1]), int(b[2]), int(b[3])
s={'classes':self.classes[cls_index],'score':'%.2f' % obj_score,'xywh':[x1,y1,x2-x1,y2-y1],}
data.append(s)
return data
else:
return False
class face_detection():
def __init__(self,min_detection_confidence):
self.model_selection = 0
self.min_detection_confidence =min_detection_confidence
self.mp_face_detection = mp.solutions.face_detection
self.face_detection = self.mp_face_detection.FaceDetection(
min_detection_confidence=self.min_detection_confidence,
)
def run(self,cv_img):
image = cv_img
image = cv.cvtColor(image, cv.COLOR_BGR2RGB)
results = self.face_detection.process(cv_img)
face=[]
if results.detections is not None:
for detection in results.detections:
data =self.draw_detection(image,detection)
face.append(data)
return face
def draw_detection(self, image, detection):
image_width, image_height = image.shape[1], image.shape[0]
bbox = detection.location_data.relative_bounding_box
bbox.xmin = int(bbox.xmin * image_width)
bbox.ymin = int(bbox.ymin * image_height)
bbox.width = int(bbox.width * image_width)
bbox.height = int(bbox.height * image_height)
# 位置:右目
keypoint0 = detection.location_data.relative_keypoints[0]
keypoint0.x = int(keypoint0.x * image_width)
keypoint0.y = int(keypoint0.y * image_height)
# 位置:左目
keypoint1 = detection.location_data.relative_keypoints[1]
keypoint1.x = int(keypoint1.x * image_width)
keypoint1.y = int(keypoint1.y * image_height)
# 位置:鼻
keypoint2 = detection.location_data.relative_keypoints[2]
keypoint2.x = int(keypoint2.x * image_width)
keypoint2.y = int(keypoint2.y * image_height)
# 位置:口
keypoint3 = detection.location_data.relative_keypoints[3]
keypoint3.x = int(keypoint3.x * image_width)
keypoint3.y = int(keypoint3.y * image_height)
# 位置:右耳
keypoint4 = detection.location_data.relative_keypoints[4]
keypoint4.x = int(keypoint4.x * image_width)
keypoint4.y = int(keypoint4.y * image_height)
# 位置:左耳
keypoint5 = detection.location_data.relative_keypoints[5]
keypoint5.x = int(keypoint5.x * image_width)
keypoint5.y = int(keypoint5.y * image_height)
data={'id':detection.label_id[0],
'score':round(detection.score[0], 3),
'rect':[int(bbox.xmin),int(bbox.ymin),int(bbox.width),int(bbox.height)],
'right_eye':(int(keypoint0.x),int(keypoint0.y)),
'left_eye':(int(keypoint1.x),int(keypoint1.y)),
'nose':(int(keypoint2.x),int(keypoint2.y)),
'mouth':(int(keypoint3.x),int(keypoint3.y)),
'right_ear':(int(keypoint4.x),int(keypoint4.y)),
'left_ear':(int(keypoint5.x),int(keypoint5.y)),
}
return data