pythonopencvimage-processingvideo-capturehaar-classifier

Set background color outside ROI in OpenCV


I successfully displayed the video feed and am trying to change the background color of the area outside ROI from black to blue but the screen still shows black background. Please help me solve the problem. Any help would be greatly appreciated.

Original code

import numpy as np
from cv2 import cv2
'''
ML object detection algo(haarcascade)used to identify objects. 
the XML file consists of trained Haar Cascade models.
'''
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
#initialize video from the webcam
video = cv2.VideoCapture(1)

while True:
# ret tells if the camera works properly. Frame is an actual frame from the video feed
    ret, frame= video.read()
    # print(cv2.VideoCapture(0).isOpened())
    # make sure port is working and read the image
    if frame is not None and video.isOpened():
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # Detect the faces within the subregions of the image in scales
        faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=6)
        # Draw the rectangle around each face
        for (x, y, w, h) in faces:
            #Use the coordinates to find the center of the face and from that point draw a rectangle of radius w/2 or h/2.
            center_coordinates = x + w // 2, y + h // 2
            radius = w // 2 # or can be h / 2 or can be anything based on your requirements
            #background color(black) 
            mask=np.zeros(frame.shape[:2] , dtype="uint8") 
         
            # Draw the desired region to crop out in white 
            cv2.circle(mask, center_coordinates, radius, (255,255,255),-1)    
            masked=cv2.bitwise_and(frame,frame,mask=mask)
            cv2.imshow('mask applied',masked)
        if cv2.waitKey(30) & 0xff==27:
            break
video.release()
cv2.destroyAllWindows()

The above code detects and displays the face in the circular mask on the black background. But as mentioned above, The background color outside circular ROI should be blue.

I tried replacing mask=np.zeros(frame.shape[:2], dtype="uint8")with the code below and fails. Frame.shape[0:2]doesn't even include channel and I can't figure out how to change the color in the first place.

mask=np.ones(frame.shape[0:2], dtype="uint8")
mask[:,:,0]=255
mask[:,:,1]=0
mask[:,:,2]=0

I also tried creating a circular masked image then place it on another image only to find out it results in the same problem.

import numpy as np
from cv2 import cv2
'''
ML object detection algo(haarcascade)used to identify objects. 
the XML file consists of trained Haar Cascade models.
'''
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
#initialize video from the webcam
video = cv2.VideoCapture(1)
print(cv2.VideoCapture(1).isOpened())

while True:
# ret tells if the camera works properly. Frame is an actual frame from the video feed
    ret, frame= video.read()
    # print(cv2.VideoCapture(0).isOpened())
    # make sure port is working and read the image
    if frame is not None and video.isOpened():
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # Detect the faces within the subregions of the image in scales
        faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=6)
        # Draw the rectangle around each face
        for (x, y, w, h) in faces:
            #Use the coordinates to find the center of the face and from that point draw a rectangle of radius w/2 or h/2.
            center_coordinates = x + w // 2, y + h // 2
            radius = w // 2 # or can be h / 2 or can be anything based on your requirements
            #background color(black) 
            mask=np.zeros(frame.shape[:2] , dtype="uint8") 
            # create blue colored background
            color = np.full_like(frame, (255,0,0))
           
            # Draw the desired region to crop out in white 
            roi=cv2.circle(mask, center_coordinates, radius, (255,255,255),-1)    
            masked=cv2.bitwise_and(frame,frame,mask=mask)
            mask_blue=cv2.bitwise_and(color,color,mask=mask-roi)
            # combine the two masked images
            result = cv2.add(masked,mask_blue)
            cv2.imshow('result',result)
        if cv2.waitKey(30) & 0xff==27:
            break
video.release()
cv2.destroyAllWindows()

Solution

  • I have changed your code as follows according to your requirement. Here i have added an extra line

    masked[np.where((masked==[0,0,0]).all(axis=2))]=[255,0,0]
    

    where you can change pixel values of black region to any specific color.

    import numpy as np
    import cv2
    '''
    ML object detection algo(haarcascade)used to identify objects. 
    the XML file consists of trained Haar Cascade models.
    '''
    face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades +'haarcascade_frontalface_default.xml')
    #initialize video from the webcam
    video = cv2.VideoCapture(0)
    print(cv2.VideoCapture(0).isOpened())
    
    while True:
    # ret tells if the camera works properly. Frame is an actual frame from the video feed
        ret, frame= video.read()
        # print(cv2.VideoCapture(0).isOpened())
        # make sure port is working and read the image
        if frame is not None and video.isOpened():
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            # Detect the faces within the subregions of the image in scales
            faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=6)
            # Draw the rectangle around each face
            for (x, y, w, h) in faces:
                #Use the coordinates to find the center of the face and from that point draw a rectangle of radius w/2 or h/2.
                center_coordinates = x + w // 2, y + h // 2
                radius = w // 2 # or can be h / 2 or can be anything based on your requirements
                #background color(black) 
                mask=np.zeros(frame.shape[:2] , dtype="uint8") 
                
                # Draw the desired region to crop out in white 
                roi=cv2.circle(mask, center_coordinates, radius, (255,255,255),-1)    
                masked=cv2.bitwise_and(frame,frame,mask=mask)
                masked[np.where((masked==[0,0,0]).all(axis=2))]=[255,0,0]
                cv2.imshow('result',masked)
            if cv2.waitKey(30) & 0xff==27:
                break
    video.release()
    cv2.destroyAllWindows()