Python 如何使用numpy阵列切片从图像中获取非矩形形状

Python 如何使用numpy阵列切片从图像中获取非矩形形状,python,numpy,cv2,dlib,eye-detection,Python,Numpy,Cv2,Dlib,Eye Detection,对于一个个人项目,我期待着项目只是眼睛从一个网络摄像头到背景直播流。目前,我已经成功地提取了一个包含眼睛的正方形,并通过在图像上使用numPy切片将其放置在不同的背景上,如本例所示(梅西图像): 我曾经考虑过使用一个面具来只留下眼睛,因为在我的代码中,我确实有一个凸面外壳来描述眼睛的形状。这种方法的问题是,我不希望眼睛处于视频流中的同一位置。我的目标是将眼睛投射到任意背景中的任意位置 理想情况下,我会使用前面提到的多声子坐标切片方法,这样我的问题就可以解决了,但我不确定这是否可行,因为我还没有在

对于一个个人项目,我期待着项目只是眼睛从一个网络摄像头到背景直播流。目前,我已经成功地提取了一个包含眼睛的正方形,并通过在图像上使用numPy切片将其放置在不同的背景上,如本例所示(梅西图像):

我曾经考虑过使用一个面具来只留下眼睛,因为在我的代码中,我确实有一个凸面外壳来描述眼睛的形状。这种方法的问题是,我不希望眼睛处于视频流中的同一位置。我的目标是将眼睛投射到任意背景中的任意位置

理想情况下,我会使用前面提到的多声子坐标切片方法,这样我的问题就可以解决了,但我不确定这是否可行,因为我还没有在互联网上找到它

# python detect_blinks.py --shape-predictor shape_predictor_68_face_landmarks.dat --video blink_detection_demo.mp4
# python detect_blinks.py --shape-predictor shape_predictor_68_face_landmarks.dat

# import the necessary packages
from scipy.spatial import distance as dist
from imutils.video import VideoStream
from imutils import face_utils
import numpy as np
import argparse
import imutils
import time
import dlib
import cv2

def eye_aspect_ratio(eye):
   # compute the euclidean distances between the two sets of
   # vertical eye landmarks (x, y)-coordinates
   A = dist.euclidean(eye[1], eye[5])
   B = dist.euclidean(eye[2], eye[4])

   # compute the euclidean distance between the horizontal
   # eye landmark (x, y)-coordinates
   C = dist.euclidean(eye[0], eye[3])

   # compute the eye aspect ratio
   ear = (A + B) / (2.0 * C)

   # return the eye aspect ratio
   return ear

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-p", "--shape-predictor", required=True,
   help="path to facial landmark predictor")
ap.add_argument("-v", "--video", type=str, default="",
   help="path to input video file")
args = vars(ap.parse_args())

# define two constants, one for the eye aspect ratio to indicate
# blink and then a second constant for the number of consecutive
# frames the eye must be below the threshold
EYE_AR_THRESH = 0.3
EYE_AR_CONSEC_FRAMES = 2

# initialize the frame counters and the total number of blinks
COUNTER = 0
TOTAL = 0

# initialize dlib's face detector (HOG-based) and then create
# the facial landmark predictor
print("[INFO] loading facial landmark predictor...")
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(args["shape_predictor"])

# grab the indexes of the facial landmarks for the left and
# right eye, respectively
(lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
(rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]


# start the video stream thread
print("[INFO] starting video stream thread...")

#fileStream = True
vs = VideoStream(src=0).start()
# vs = VideoStream(usePiCamera=True).start()
fileStream = False
time.sleep(1.0)

# loop over frames from the video stream
while True:
   # if this is a file video stream, then we need to check if
   # there any more frames left in the buffer to process
   if fileStream and not vs.more():
       break

   # grab the frame from the threaded video file stream, resize
   # it, and convert it to grayscale
   # channels)
   frame = vs.read()
   frame = imutils.resize(frame, width=1080)
   gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

   # detect faces in the grayscale frame
   rects = detector(gray, 0)

   # loop over the face detections
   for rect in rects:
       # determine the facial landmarks for the face region, then
       # convert the facial landmark (x, y)-coordinates to a NumPy
       # array
       shape = predictor(gray, rect)
       shape = face_utils.shape_to_np(shape)

       # extract the left and right eye coordinates, then use the
       # coordinates to compute the eye aspect ratio for both eyes
       leftEye = shape[lStart:lEnd]
       rightEye = shape[rStart:rEnd]
       leftEAR = eye_aspect_ratio(leftEye)
       rightEAR = eye_aspect_ratio(rightEye)

       # average the eye aspect ratio together for both eyes
       ear = (leftEAR + rightEAR) / 2.0

       # compute the convex hull for the left and right eye, then
       # visualize each of the eyes
       leftEyeHull = cv2.convexHull(leftEye)
       rightEyeHull = cv2.convexHull(rightEye)
       #mask = np.zeros(shape), dtype=np.uint8)
       cv2.drawContours(frame, ([leftEyeHull]), -1, (255), 1)
       cv2.drawContours(frame, ([rightEyeHull]), -1, (255), 1)
       print('right:', rightEyeHull)

       # mask = np.ones((1000, 2000))  # (height, width)
       # myROI = [(750, 0), (900, 1000), (1000, 1000), (1500, 0)]  # (x, y)
       # cv2.fillConvexPoly(mask, [np.array(myROI)], 0)

       # myROI = [(750, 0), (900, 1000), (1000, 1000), (1500, 0)]
       # # [[[454 380]]    [[470 372]] [[487 371]] [[504 379]]  [[487 383]] [[470 384]]]
       # rEyeX = np.array([i[0] for i in rightEyeHull[:, :, 1]])
       # ROIright = np.array([(i[0]) for i in rightEyeHull[:, :, :]])
       # print('ROIright:', ROIright)

       # check to see if the eye aspect ratio is below the blink
       # threshold, and if so, increment the blink frame counter
       if ear < EYE_AR_THRESH:
           COUNTER += 1

       # otherwise, the eye aspect ratio is not below the blink
       # threshold
       else:
           # if the eyes were closed for a sufficient number of
           # then increment the total number of blinks
           if COUNTER >= EYE_AR_CONSEC_FRAMES:
               TOTAL += 1

           # reset the eye frame counter
           COUNTER = 0


       # draw the total number of blinks on the frame along with
       # the computed eye aspect ratio for the frame


       blackframe = cv2.imread("black-background kopie.jpg")

       rEyeX = np.array([i[0] for i in rightEyeHull[:,:,1]])
       rEyeY = np.array([i[0] for i in rightEyeHull[:,:,0]])
       lEyeX = np.array([i[0] for i in leftEyeHull[:, :, 1]])
       lEyeY = np.array([i[0] for i in leftEyeHull[:, :, 0]])

       rEyeSquare = frame[min(rEyeX):max(rEyeX), min(rEyeY):max(rEyeY)]
       lEyeSquare = frame[min(lEyeX):max(lEyeX), min(lEyeY):max(lEyeY)]

       blackframe[min(rEyeX):max(rEyeX), min(rEyeY):max(rEyeY)] = rEyeSquare
       blackframe[min(lEyeX):max(lEyeX), min(lEyeY):max(lEyeY)] = lEyeSquare

       cv2.putText(blackframe, "Blinks: {}".format(TOTAL), (10, 30),
                   cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
       cv2.putText(blackframe, "EAR: {:.2f}".format(ear), (300, 30),
                   cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

   # show the frame
   cv2.imshow("Frame", blackframe)
   key = cv2.waitKey(1) & 0xFF

   # if the `q` key was pressed, break from the loop
   if key == ord("q"):
       break

# do a bit of cleanup
cv2.destroyAllWindows()
vs.stop()```
#python detect_blinks.py--shape predictor shape_predictor_68_face_landmarks.dat--video blink_demo.mp4
#python detect_blinks.py--形状预测器形状预测器面部地标.dat
#导入必要的包
从scipy.spatial导入距离作为距离
从imutils.video导入视频流
从imutils导入面\u utils
将numpy作为np导入
导入argparse
导入imutils
导入时间
导入dlib
进口cv2
def眼宽比(眼):
#计算两组数据之间的欧几里德距离
#垂直眼地标(x,y)-坐标
A=距离欧几里德(眼睛[1],眼睛[5])
B=距离欧几里德(眼睛[2],眼睛[4])
#计算水平线之间的欧氏距离
#眼睛地标(x,y)-坐标
C=距离欧几里德(眼睛[0],眼睛[3])
#计算眼睛的纵横比
ear=(A+B)/(2.0*C)
#返回眼睛纵横比
回音耳
#构造参数并解析参数
ap=argparse.ArgumentParser()
ap.add_参数(“-p”,“--shape predictor”,required=True,
help=“面部地标预测器路径”)
ap.add_参数(“-v”,”--video),type=str,default=“”,
help=“输入视频文件的路径”)
args=vars(ap.parse_args())
#定义两个常数,一个用于表示眼睛纵横比
#闪烁,然后第二个常数表示连续闪烁的次数
#帧眼睛必须低于阈值
眼距阈值=0.3
眼睛连续帧=2
#初始化帧计数器和总闪烁次数
计数器=0
总数=0
#初始化dlib的人脸检测器(基于HOG),然后创建
#面部标志预测器
打印(“[INFO]正在加载面部地标预测器…”)
探测器=dlib.获取正面探测器()
predictor=dlib.shape\u predictor(args[“shape\u predictor”])
#抓取左右两侧面部标志的索引
#分别是右眼
(lStart,lEnd)=面部特征。面部标志物[“左眼”]
(rStart,rEnd)=面部特征。面部标志物[“右眼”]
#启动视频流线程
打印(“[INFO]正在启动视频流线程…”)
#fileStream=True
vs=VideoStream(src=0).start()
#vs=VideoStream(usePiCamera=True).start()
fileStream=False
时间。睡眠(1.0)
#循环播放视频流中的帧
尽管如此:
#如果这是一个文件视频流,那么我们需要检查
#缓冲区中还有更多要处理的帧吗
如果fileStream而非vs.more():
打破
#从线程视频文件流中抓取帧,调整大小
#并将其转换为灰度
#渠道)
frame=vs.read()
frame=imutils.resize(frame,width=1080)
灰色=cv2.CVT颜色(边框,cv2.COLOR\u BGR2GRAY)
#检测灰度帧中的面
rects=检测器(灰色,0)
#环面检测
对于矩形中的矩形:
#确定面部区域的面部地标,然后
#将面部地标(x,y)-坐标转换为NumPy
#排列
形状=预测器(灰色、矩形)
形状=面形状。形状到形状(形状)
#提取左眼和右眼坐标,然后使用
#用于计算双眼的眼睛纵横比的坐标
leftEye=形状[lStart:lEnd]
右眼=形状[rStart:rEnd]
左眼=眼睛与纵横比(左眼)
右眼=眼睛与纵横比(右眼)
#平均双眼的眼睛长宽比
ear=(左耳+右耳)/2.0
#计算左眼和右眼的凸包,然后
#想象每一只眼睛
leftEyeHull=cv2.convexHull(左眼)
右眼外壳=cv2.凸面外壳(右眼)
#掩码=np.0(形状),数据类型=np.uint8)
cv2.图纸轮廓(框架,([leftEyeHull]),-1,(255),1)
cv2.图纸轮廓(框架,([rightEyeHull]),-1,(255),1)
打印('right:',rightEyeHull)
#掩模=np.ones((10002000))#(高度、宽度)
#我的投资回报率=[(750,0),(900,1000),(1000,1000),(1500,0)]#(x,y)
#cv2.fillConvexPoly(掩模,[np.array(myROI)],0)
#myROI=[(750,0)、(900,1000)、(1000,1000)、(1500,0)]
# # [[[454 380]]    [[470 372]] [[487 371]] [[504 379]]  [[487 383]] [[470 384]]]
#rEyeX=np.array([i[0]表示rightEyeHull[:,:,1]]中的i)
#ROIright=np.数组([(i[0]),用于rightEyeHull[:,:,:]中的i)
#打印('ROIright:',ROIright)
#检查眼睛纵横比是否低于眨眼
#阈值,如果是,则增加闪烁帧计数器
如果耳朵<眼睛>耳朵>脱粒:
计数器+=1
#否则,眼睛纵横比不低于眨眼
#门槛
其他:
#如果闭上眼睛的时间足够长
#然后增加闪烁的总次数
如果计数器>=眼睛连续帧:
总数+=1
#重置眼框计数器
计数器=0
#绘制帧上闪烁的总次数以及
#计算的帧的眼睛纵横比
blackframe=cv2.imread(“黑色背景kopie.jpg”)
rEyeX=np.array([i[0]表示右边的i