1

I need to detect the high variation of the optical flow in the video. For example the crossroads. Two cars are driving and they have some value of optical flow. Next, in some time period, they have collision, so it will produce a high variation of optical flow. How to detect it?

optical flow with binarization and mask

optical flow with binarization and mask

expecting the result to fire event when the variation of the optical flow high

expecting the result to fire event when the variation of the optical flow high

how to capture this event?

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()

nathancy
  • 42,661
  • 14
  • 115
  • 137
Dmitry
  • 31
  • 5

0 Answers0