使用opencv从侧视图检测马的眨眼
Detecting blinks of a horse from side view with opencv
这是一个理论问题,而不是要求具体的代码问题。
我已经使用 Haar Cascades 完成了一些面部标志检测,但这次我手上有不同类型的视频。这是马眼的侧视图(摄像头安装在头部的一侧),所以基本上我看到的是一只巨大的眼睛。我尝试使用 Haar Cascades,但没用,因为我的视频中没有检测到人脸。
我想知道在这匹马身上检测眼睛和眨眼的最佳方法是什么?我是否尝试自定义 dlib 面部标记检测器?我没有找到太多关于动物地标的信息。
提前致谢! :)
在第一帧围绕眼睛绘制边界框后,我使用对象跟踪器继续定位眼睛。
我创建了一个设置宽度和高度的边界框,因为我们可以粗略地假设眼睛相对于相机没有变大或变小。在为跟踪器绘制边界框时,我们不仅要包括眼睛,否则它会在眨眼时失去对物体的追踪。
我在每帧中寻找边界区域的饱和度是否低于阈值,以检查它们是否眨眼。蓝色框是跟踪器返回的边界框,绿色框是我正在裁剪并检查饱和度的区域。
这是视频过程中的饱和度图表
你可以清楚地看到他们眨眼的区域
这是结果的 gif(经过大量压缩以达到 2mb 的限制)
import cv2
import numpy as np
import math
# tuplifies things for opencv
def tup(p):
return (int(p[0]), int(p[1]));
# returns the center of the box
def getCenter(box):
x = box[0];
y = box[1];
x += box[2] / 2.0;
y += box[3] / 2.0;
return [x,y];
# rescales image by percent
def rescale(img, scale):
h,w = img.shape[:2];
h = int(h*scale);
w = int(w*scale);
return cv2.resize(img, (w,h));
# load video
cap = cv2.VideoCapture("blinking.mov");
scale = 0.5;
# font stuff
font = cv2.FONT_HERSHEY_SIMPLEX;
org = (50, 50);
fontScale = 1;
font_color = (255, 255, 0);
thickness = 2;
# set up tracker
tracker = cv2.TrackerCSRT_create(); # I'm using OpenCV 3.4
backup = cv2.TrackerCSRT_create();
# grab the first frame
_, frame = cap.read();
frame = rescale(frame, scale);
# init tracker
box = cv2.selectROI(frame, False);
tracker.init(frame, box);
backup.init(frame, box);
cv2.destroyAllWindows();
# set center bounds
width = 75;
height = 60;
# save numbers
file_index = 0;
# blink counter
blinks = 0;
blink_thresh = 35;
blink_trigger = True;
# show video
done = False;
while not done:
# get frame
ret, frame = cap.read();
if not ret:
break;
frame = rescale(frame, scale);
# choose a color space
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV);
h,s,v = cv2.split(hsv);
channel = s;
# grab tracking box
ret, box = tracker.update(frame);
if ret:
# get the center
center = getCenter(box);
x, y = center;
# make box on center
tl = [x - width, y - height];
br = [x + width, y + height];
tl = tup(tl);
br = tup(br);
# get top left and bottom right
p1 = [box[0], box[1]];
p2 = [p1[0] + box[2], p1[1] + box[3]];
p1 = tup(p1);
p2 = tup(p2);
# draw a roi around the image
cv2.rectangle(frame, p1, p2, (255,0,0), 3);
cv2.rectangle(frame, tl, br, (0,255,0), 3);
cv2.circle(frame, tup(center), 6, (0,0,255), -1);
# get the channel average in the box
slc = channel[tl[1]:br[1], tl[0]:br[0]];
ave = np.mean(slc);
# if it dips below a set value, then trigger a blink
if ave < blink_thresh:
if blink_trigger:
blinks += 1;
blink_trigger = False;
else:
blink_trigger = True;
# draw blink count
frame = cv2.putText(frame, "Blinks: " + str(blinks), org, font, fontScale,
font_color, thickness, cv2.LINE_AA);
# show
cv2.imshow("Frame", frame);
key = cv2.waitKey(1);
# check keypress
done = key == ord('q');
这是一个理论问题,而不是要求具体的代码问题。
我已经使用 Haar Cascades 完成了一些面部标志检测,但这次我手上有不同类型的视频。这是马眼的侧视图(摄像头安装在头部的一侧),所以基本上我看到的是一只巨大的眼睛。我尝试使用 Haar Cascades,但没用,因为我的视频中没有检测到人脸。
我想知道在这匹马身上检测眼睛和眨眼的最佳方法是什么?我是否尝试自定义 dlib 面部标记检测器?我没有找到太多关于动物地标的信息。
提前致谢! :)
在第一帧围绕眼睛绘制边界框后,我使用对象跟踪器继续定位眼睛。
我创建了一个设置宽度和高度的边界框,因为我们可以粗略地假设眼睛相对于相机没有变大或变小。在为跟踪器绘制边界框时,我们不仅要包括眼睛,否则它会在眨眼时失去对物体的追踪。
我在每帧中寻找边界区域的饱和度是否低于阈值,以检查它们是否眨眼。蓝色框是跟踪器返回的边界框,绿色框是我正在裁剪并检查饱和度的区域。
这是视频过程中的饱和度图表
你可以清楚地看到他们眨眼的区域
这是结果的 gif(经过大量压缩以达到 2mb 的限制)
import cv2
import numpy as np
import math
# tuplifies things for opencv
def tup(p):
return (int(p[0]), int(p[1]));
# returns the center of the box
def getCenter(box):
x = box[0];
y = box[1];
x += box[2] / 2.0;
y += box[3] / 2.0;
return [x,y];
# rescales image by percent
def rescale(img, scale):
h,w = img.shape[:2];
h = int(h*scale);
w = int(w*scale);
return cv2.resize(img, (w,h));
# load video
cap = cv2.VideoCapture("blinking.mov");
scale = 0.5;
# font stuff
font = cv2.FONT_HERSHEY_SIMPLEX;
org = (50, 50);
fontScale = 1;
font_color = (255, 255, 0);
thickness = 2;
# set up tracker
tracker = cv2.TrackerCSRT_create(); # I'm using OpenCV 3.4
backup = cv2.TrackerCSRT_create();
# grab the first frame
_, frame = cap.read();
frame = rescale(frame, scale);
# init tracker
box = cv2.selectROI(frame, False);
tracker.init(frame, box);
backup.init(frame, box);
cv2.destroyAllWindows();
# set center bounds
width = 75;
height = 60;
# save numbers
file_index = 0;
# blink counter
blinks = 0;
blink_thresh = 35;
blink_trigger = True;
# show video
done = False;
while not done:
# get frame
ret, frame = cap.read();
if not ret:
break;
frame = rescale(frame, scale);
# choose a color space
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV);
h,s,v = cv2.split(hsv);
channel = s;
# grab tracking box
ret, box = tracker.update(frame);
if ret:
# get the center
center = getCenter(box);
x, y = center;
# make box on center
tl = [x - width, y - height];
br = [x + width, y + height];
tl = tup(tl);
br = tup(br);
# get top left and bottom right
p1 = [box[0], box[1]];
p2 = [p1[0] + box[2], p1[1] + box[3]];
p1 = tup(p1);
p2 = tup(p2);
# draw a roi around the image
cv2.rectangle(frame, p1, p2, (255,0,0), 3);
cv2.rectangle(frame, tl, br, (0,255,0), 3);
cv2.circle(frame, tup(center), 6, (0,0,255), -1);
# get the channel average in the box
slc = channel[tl[1]:br[1], tl[0]:br[0]];
ave = np.mean(slc);
# if it dips below a set value, then trigger a blink
if ave < blink_thresh:
if blink_trigger:
blinks += 1;
blink_trigger = False;
else:
blink_trigger = True;
# draw blink count
frame = cv2.putText(frame, "Blinks: " + str(blinks), org, font, fontScale,
font_color, thickness, cv2.LINE_AA);
# show
cv2.imshow("Frame", frame);
key = cv2.waitKey(1);
# check keypress
done = key == ord('q');