我需要检测视频中光流的高度变化。例如,十字路口。两辆汽车在行驶,它们具有一定的光通量值。接下来,在一定时间段内,它们会发生碰撞,因此会产生较大的光流变化。如何检测?
具有二值化和遮罩的光学流
当光流的变化较大时,期望着火结果
如何捕获此事件?
def label_flows(flows):
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 10, 1.0)
flags = cv.KMEANS_RANDOM_CENTERS
h, w = flows.shape[:2]
labeled_flows = []
flows = flows.reshape(h*w, -1)
comp, labels, centers = cv.kmeans(flows, 2, None, criteria, 10, flags)
n = np.sum(labels == 1)
camera_motion_label = np.argmax([labels.size-n, n])
labeled = np.uint8(255*(labels.reshape(h, w) == camera_motion_label))
return labeled
def find_target_in_labeled_flow(labeled_flow):
labeled_flow = cv2.bitwise_not(labeled_flow)
bw = 10
h, w = labeled_flow.shape[:2]
border_cut = labeled_flow[bw:h-bw, bw:w-bw]
conncomp, stats = cv2.connectedComponentsWithStats(border_cut, connectivity=8)[1:3]
target_label = np.argmax(stats[1:, cv2.CC_STAT_AREA]) + 1
img = np.zeros_like(labeled_flow)
img[bw:h-bw, bw:w-bw] = 255*(conncomp == target_label)
return img
def put_optical_flow_arrows_on_image(image, optical_flow_image, threshold=2.0, skip_amount=30):
image = image.copy()
if len(image.shape) == 2:
image = np.stack((image,)*3, axis=2)
flow_start = np.stack(np.meshgrid(range(optical_flow_image.shape[1]), range(optical_flow_image.shape[0])), 2)
flow_end = (optical_flow_image[flow_start[:,:,1],flow_start[:,:,0],:1]*3 + flow_start).astype(np.int32)
norm = np.linalg.norm(flow_end - flow_start, axis=2)
norm[norm < threshold] = 0
nz = np.nonzero(norm)
for i in range(0, len(nz[0]), skip_amount):
y, x = nz[0][i], nz[1][i]
cv.arrowedLine(image,
pt1=tuple(flow_start[y,x]),
pt2=tuple(flow_end[y,x]),
color=(0, 255, 0),
thickness=1,
tipLength=.2)
return image
if __name__ =='__main__':
cap = cv.VideoCapture("video.mp4")
ret, first_frame = cap.read()
prev_gray = cv.cvtColor(first_frame, cv.COLOR_BGR2GRAY)
mask = np.zeros_like(first_frame)
mask[..., 1] = 255
cv.namedWindow('input',cv.WINDOW_NORMAL)
cv.namedWindow('binarized',cv.WINDOW_NORMAL)
cv.namedWindow('dense_optical_flow',cv.WINDOW_NORMAL)
cv.namedWindow('color', cv.WINDOW_NORMAL)
while(cap.isOpened()):
ret, frame = cap.read()
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
flow = cv.calcOpticalFlowFarneback(prev_gray, gray, None, 0.5, 3, 15, 3, 5, 1.2, 0)
magnitude, angle = cv.cartToPolar(flow[..., 0], flow[..., 1])
mask[..., 0] = angle * 180 / np.pi / 2
mask[..., 2] = cv.normalize(magnitude, None, 0, 255, cv.NORM_MINMAX)
rgb = cv.cvtColor(mask, cv.COLOR_HSV2BGR)
binary_flow = label_flows(flow)
optical_flow_arrows = put_optical_flow_arrows_on_image(gray, flow)
hsv = cv.cvtColor(optical_flow_arrows, cv.COLOR_BGR2HSV)
mask_green = cv.inRange(hsv, (36, 25, 25), (70, 255,255))
imask = mask_green>0
green = np.zeros_like(optical_flow_arrows, np.uint8)
green[imask] = optical_flow_arrows[imask]
# Here I need to calculate the variation of the optical flow
# Any ideas about how to do it?
cv.imshow("binarized", binary_flow)
cv.imshow("dense_optical_flow", optical_flow_arrows)
cv.imshow('color', green)
prev_gray = gray
if cv.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv.destroyAllWindows()