Home > Enterprise >  Creating multiple ROI on webcam video
Creating multiple ROI on webcam video

Time:04-06

Im trying to create multiple ROIs over my webcam stream. Ive used this library called roipoly (https://github.com/jdoepfert/roipoly.py)

I modified the example code (examples/multi_roi_example.py) to work on webcam , which now looks like this

import logging
import cv2
import numpy as np
from matplotlib import pyplot as plt

from roipoly import MultiRoi

logging.basicConfig(format='%(levelname)s ''%(processName)-10s : %(asctime)s '
                           '%(module)s.%(funcName)s:%(lineno)s %(message)s',
                    level=logging.INFO)

cap = cv2.VideoCapture(1)

while cap.isOpened():

# Create image
    val,img =cap.read()

#img = np.ones((100, 100)) * range(0, 100)

# Show the image
    fig = plt.figure()
    plt.imshow(img, interpolation='nearest', cmap="Greys")
    plt.title("Click on the button to add a new ROI")

# Draw multiple ROIs
    multiroi_named = MultiRoi(roi_names=['My first ROI', 'My second ROI'])

# Draw all ROIs
    plt.imshow(img, interpolation='nearest', cmap="Greys")
    roi_names = []
    for name, roi in multiroi_named.rois.items():
        roi.display_roi()
        roi.display_mean(img)
        roi_names.append(name)
    plt.legend(roi_names, bbox_to_anchor=(1.2, 1.05))
    plt.show()
    # Let OpenCV manage window events
    key = cv2.waitKey(50)
    # If ESCAPE key pressed, stop
    if key == 27:
        cap.release()

But the issue is that after drawing the ROI, the video stream remains paused and never continues. How to resume the webcam stream along with the ROI on top of it

CodePudding user response:

I see few problems.

Main problem is that plt.show() is waiting until you close window and this is blocking rest of code.

It needs plt.show(block=False) and this needs also plt.pause(0.001) so it would have time to update image in window.

    plt.show(block=False)    
    plt.pause(0.001)

Other problem is that you run ROI in every loop - so you would have to use some boolean variable to skip it after selecting

select_roi = True

while cap.isOpened():

    # ... code ...

    if select_roi:
        fig = plt.figure()
        plt.imshow(img, interpolation='nearest', cmap="Greys")
        plt.title("Click on the button to add a new ROI")

        # Draw multiple ROIs
        multiroi_named = MultiRoi(roi_names=['My first ROI', 'My second ROI'])
        
        select_roi = False  

    # ... code ...

or you should select ROI before loop

fig = plt.figure()
plt.imshow(img, interpolation='nearest', cmap="Greys")
plt.title("Click on the button to add a new ROI")

# Draw multiple ROIs
multiroi_named = MultiRoi(roi_names=['My first ROI', 'My second ROI'])

while cap.isOpened():

     # ... code ...

Other problem is waitKey which works only if you display image with cv2.imshow(...) but you don't use it so waitKey will not get keys.

Other problem is that cv2 gives image in colors BGR but matplotlib needs RGB - so you have to convert it.

img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

Full working code:

version with boolean variable select_roi

import cv2
from matplotlib import pyplot as plt
from roipoly import MultiRoi

#cap = cv2.VideoCapture(0)  # my built-in webcam
cap = cv2.VideoCapture(1)

select_roi = True   # default value as start

while cap.isOpened():

    val, img = cap.read()

    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

    if select_roi:
        # Show the image
        fig = plt.figure()
        plt.imshow(img, interpolation='nearest', cmap="Greys")
        plt.title("Click on the button to add a new ROI")

        # Draw multiple ROIs
        multiroi_named = MultiRoi(roi_names=['My first ROI', 'My second ROI'])
        
        select_roi = False
   
    # --- after if ---
 
    # Draw all ROIs
    plt.imshow(img, interpolation='nearest', cmap="Greys")
    
    roi_names = []
    for name, roi in multiroi_named.rois.items():
        roi.display_roi()
        #roi.display_mean(img)
        roi_names.append(name)
        
    plt.legend(roi_names, bbox_to_anchor=(1.2, 1.05))
    plt.show(block=False)    
    plt.pause(0.001)

version with ROI before loop

import cv2
from matplotlib import pyplot as plt
from roipoly import MultiRoi

#cap = cv2.VideoCapture(0)  # my built-in webcam
cap = cv2.VideoCapture(1)

val, img = cap.read()

img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

# Show the image
fig = plt.figure()
plt.imshow(img, interpolation='nearest', cmap="Greys")
plt.title("Click on the button to add a new ROI")

# Draw multiple ROIs
multiroi_named = MultiRoi(roi_names=['My first ROI', 'My second ROI'])

while cap.isOpened():

    val, img = cap.read()

    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

    # Draw all ROIs
    plt.imshow(img, interpolation='nearest', cmap="Greys")
    
    roi_names = []
    for name, roi in multiroi_named.rois.items():
        roi.display_roi()
        #roi.display_mean(img)
        roi_names.append(name)
        
    plt.legend(roi_names, bbox_to_anchor=(1.2, 1.05))
    plt.show(block=False)    
    plt.pause(0.001)

BTW: if you need rectangle ROI then there is cv2.selectROI() to select one region and cv2.cv2.selectROIs() to select many regions

results = cv2.selectROIs('image', img)

and it doesn't need to convert from BGR to RGB.

  • Related