How to stack colored images together with binary images using OpenCV, NumPy, and Python?

Viewed 497

I am making a motion detection program which first gets a reference frame from a live video feed and detects if anything changes from the reference frame it took when the program was started.

Variables:

refFrame = 3 dimensional image which is the colored frame you get from the webcam feed when the program is started. (Still image which is the first frame the webcam captured)

myFrame = 3 dimensional video feed which reflects the real time video feed of your webcam (Actual real time video feed directly from the webcam)

diffFrame = 2 dimensional binary video feed which displays the difference of the current video feed vs the reference image frame it took when you started the program. (Black and white video feed)

threshFrame = 2 dimensional binary video feed which displays the threshold format of the video live feed of diffFrame. (Black and white video feed in different format)

My goal is to stack all the 4 frames together in a 4x4 format using vstack as I have successfully stacked both 3 dimensional and 2 dimensional images together horizontally. Currently, I'm having a problem stacking the 4 images because of their dimension differences. How can I possibly stack these 4 images together?

        # stack 'em
        picsStack1 = np.hstack((refFrame,myFrame))
        picsStack2 = np.hstack((diffFrame,threshFrame))

        # show video frame
        cv.imshow('Hidden Cam',np.vstack((picsStack1, picsStack2)))     
1 Answers

We'll split the tasks into 3 functions:

  1. Define a function that will take in an image array. If the array is 2D, meaning it's in grayscale, convert it to 3D and return the 3D array. Otherwise, return the original array.

  2. Define a function that will take in a list of image arrays, and return the greatest width and height among the images.

  3. Define a function that will take in a list of image arrays, and return a list of images with each image from the original list, only broadcasted to a black canvas. The black canvas should get its dimensions from the canvas_size function.

The code might look something like this:

import cv2
import numpy as np

def convert_channels(img):
    if img.ndim == 2:
        return cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
    return img

def canvas_size(imgs):
    h_max = 0
    w_max = 0
    for img in imgs:
        h, w, _ = img.shape
        if h > h_max:
            h_max = h
        if w > w_max:
            w_max = w
    return w_max, h_max

def padded_imgs(imgs):
    max_w, max_h = canvas_size(imgs)
    imgs_new = []
    for img in map(convert_channels, imgs):
        h, w, _ = img.shape
        canvas = np.zeros((max_h, max_w, 3)).astype("uint8")
        canvas[:h, :w] = img
        imgs_new.append(canvas)
    return imgs_new

while True:
    # Your code here
    refFrame, myFrame, diffFrame, threshFrame = padded_imgs([refFrame, myFrame, diffFrame, threshFrame])

    picsStack1 = np.hstack((refFrame, myFrame))
    picsStack2 = np.hstack((diffFrame, threshFrame))

    cv.imshow('Hidden Cam',np.vstack((picsStack1, picsStack2)))  
    # Your code here
Related