Обнаружить большое изменение оптического потока в видео - PullRequest
1 голос
/ 10 мая 2019

Мне нужно обнаружить высокую вариацию оптического потока в видео.Например перекресток.Две машины едут, и у них есть некоторое значение оптического потокаЗатем, через некоторое время, они сталкиваются, что приводит к сильному изменению оптического потока.Как это обнаружить?

оптический поток с бинаризацией и маской

optical flow with binarization and mask

ожидание результата для события пожара, когда изменение оптического потока велико

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

как запечатлеть это событие?

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

...