python-3.xopencvchromakey

error with openCV2


I am new in coding. Using this script:

from PIL import Image
from PIL.ImageChops import subtract
import numpy, math, time, glob, sys, os, logging, requests, random

def GreenScreen(infile, inbg ,outfile='output.png', keyColor=None,tolerance=None):
    """
    http://gc-films.com/chromakey.html
    http://www.cs.utah.edu/~michael/chroma/
    :param infile:      Greenscreen image location
    :param inbg:        Background image location
    :param outfile:     Output file location
    :param keyColor:    greenscreen color; it can be any singular color
    :param tolerance:   tolerance of cleaning
    :return:
    """

    if not keyColor:
        keyColor = [151,44,21] #Y,Cb, and Cr values of the greenscreen

    if not tolerance:
        tolerance = [100,130] #Allowed Distance from Values

    #open files
    inDataFG = Image.open('/home/leonardo/Scrivania/in/KVfnt.png').convert('YCbCr')
    Path = '/home/leonardo/Scrivania/background/'
    FullPath = os.path.join(Path, random.choice(os.listdir(Path)))
    BG = Image.open(FullPath).convert('RGB')
    [Y_key, Cb_key, Cr_key] = keyColor
    [tola, tolb]= tolerance

    (x,y) = inDataFG.size #get dimensions
    foreground = numpy.array(inDataFG.getdata()) #make array from image
    maskgen = numpy.vectorize(colorclose) #vectorize masking function


    alphaMask = maskgen(foreground[:,1],foreground[:,2] ,Cb_key, Cr_key, tola, tolb) #generate mask
    alphaMask.shape = (y,x) #make mask dimensions of original image
    imMask = Image.fromarray(numpy.uint8(alphaMask))#convert array to image
    invertMask = Image.fromarray(numpy.uint8(255-255*(alphaMask/255))) #create inverted mask with extremes

    #create images for color mask
    colorMask = Image.new('RGB',(x,y),tuple([0,0,0]))
    allgreen = Image.new('YCbCr',(x,y),tuple(keyColor))

    colorMask.paste(allgreen,invertMask) #make color mask green in green values on image
    inDataFG = inDataFG.convert('RGB') #convert input image to RGB for ease of working with
    cleaned = subtract(inDataFG,colorMask) #subtract greens from input
    BG.paste(cleaned,imMask)#paste masked foreground over background

    # BG.show() #display cleaned image
    BG.save(outfile, "JPEG") #save cleaned image

def colorclose(Cb_p,Cr_p, Cb_key, Cr_key, tola, tolb):
    temp = math.sqrt((Cb_key-Cb_p)**2+(Cr_key-Cr_p)**2)
    if temp < tola:
        z = 0.0
    elif temp < tolb:
        z = ((temp-tola)/(tolb-tola))
    else:
        z = 1.0
    return 255.0*z

def check_folders(logger):
    if not os.path.exists('out/'):
        os.mkdir('out/')
    if not os.path.exists('background/'):
        os.mkdir('background/')
        logger.error("Place background images in background/")
        sys.exit()
    if not os.path.exists('in/'):
        os.mkdir('in/')
        logger.error("Place input files in in/")
        sys.exit()

def begin_greenbox(logger):
    """
    For all backgrounds loop through all input files into the out file
    """
    for bg in glob.glob('background/*'):
            continue
    bg_name = bg.split('/')[-1].lower().strip('.jpg').strip('.png').strip('.jpeg')
    for picture in glob.glob('in/*'):
                continue
    pic_name = picture.split('/')[-1].lower().strip('.JPG').strip('.png').strip('.jpeg')
    output_file = 'out/' + bg_name + ' ' + pic_name + '.jpg'

    one_pic = time.time()
    GreenScreen(infile=picture ,inbg=bg, outfile=output_file)
    one_pic_time_done = time.time()

    time_arr.append(one_pic_time_done-one_pic)
    logger.info(time_arr)
    logger.info('done : %s' % pic_name)

def start_logging():
    logging.basicConfig()
    logger = logging.getLogger('greenbox')
    logger.setLevel(logging.INFO)
    return logger

if __name__ == '__main__':
    time_start = time.time()
    time_arr = []
    logger = start_logging()
    logger.info("Start time: %s" % time_start)
    check_folders(logger)    
    begin_greenbox(logger)
    time_end = time.time()
    logger.info("End time: %s" % time_end)

Everything is okay and the image is saved in the /out folder. Using this code:

from cv2 import *
# initialize the camera
cam = VideoCapture(0)   # 0 -> index of camera
s, img = cam.read()
if s:    # frame captured without any errors
    namedWindow("cam-test",WINDOW_AUTOSIZE)
    imwrite('/home/leonardo/Scrivania/in/KVfnt.png',img) #save image 

Everything is okay and the image is captured from the camera and saved in /in folder. If I add the second code to the first one:

from PIL import Image
from PIL.ImageChops import subtract
import numpy, math, time, glob, sys, os, logging, requests, random
from cv2 import *

# initialize the camera
cam = VideoCapture(0)   # 0 -> index of camera
s, img = cam.read()
if s:    # frame captured without any errors
    namedWindow("cam-test",WINDOW_AUTOSIZE)
    imwrite('/home/leonardo/Scrivania/in/KVfnt.png',img) #save image 
def GreenScreen(infile, inbg ,outfile='output.png', keyColor=None,tolerance=None):
    """
    http://gc-films.com/chromakey.html
    http://www.cs.utah.edu/~michael/chroma/
    :param infile:      Greenscreen image location
    :param inbg:        Background image location
    :param outfile:     Output file location
    :param keyColor:    greenscreen color; it can be any singular color
    :param tolerance:   tolerance of cleaning
    :return:
    """

    if not keyColor:
        keyColor = [151,44,21] #Y,Cb, and Cr values of the greenscreen

    if not tolerance:
        tolerance = [100,130] #Allowed Distance from Values

    #open files
    inDataFG = Image.open('/home/leonardo/Scrivania/in/KVfnt.png').convert('YCbCr')
    Path = '/home/leonardo/Scrivania/background/'
    FullPath = os.path.join(Path, random.choice(os.listdir(Path)))
    BG = Image.open(FullPath).convert('RGB')
    [Y_key, Cb_key, Cr_key] = keyColor
    [tola, tolb]= tolerance

    (x,y) = inDataFG.size #get dimensions
    foreground = numpy.array(inDataFG.getdata()) #make array from image
    maskgen = numpy.vectorize(colorclose) #vectorize masking function


    alphaMask = maskgen(foreground[:,1],foreground[:,2] ,Cb_key, Cr_key, tola, tolb) #generate mask
    alphaMask.shape = (y,x) #make mask dimensions of original image
    imMask = Image.fromarray(numpy.uint8(alphaMask))#convert array to image
    invertMask = Image.fromarray(numpy.uint8(255-255*(alphaMask/255))) #create inverted mask with extremes

    #create images for color mask
    colorMask = Image.new('RGB',(x,y),tuple([0,0,0]))
    allgreen = Image.new('YCbCr',(x,y),tuple(keyColor))

    colorMask.paste(allgreen,invertMask) #make color mask green in green values on image
    inDataFG = inDataFG.convert('RGB') #convert input image to RGB for ease of working with
    cleaned = subtract(inDataFG,colorMask) #subtract greens from input
    BG.paste(cleaned,imMask)#paste masked foreground over background

    # BG.show() #display cleaned image
    BG.save(outfile, "JPEG") #save cleaned image

def colorclose(Cb_p,Cr_p, Cb_key, Cr_key, tola, tolb):
    temp = math.sqrt((Cb_key-Cb_p)**2+(Cr_key-Cr_p)**2)
    if temp < tola:
        z = 0.0
    elif temp < tolb:
        z = ((temp-tola)/(tolb-tola))
    else:
        z = 1.0
    return 255.0*z

def check_folders(logger):
    if not os.path.exists('out/'):
        os.mkdir('out/')
    if not os.path.exists('background/'):
        os.mkdir('background/')
        logger.error("Place background images in background/")
        sys.exit()
    if not os.path.exists('in/'):
        os.mkdir('in/')
        logger.error("Place input files in in/")
        sys.exit()

def begin_greenbox(logger):
    """
    For all backgrounds loop through all input files into the out file
    """
    for bg in glob.glob('background/*'):
            continue
    bg_name = bg.split('/')[-1].lower().strip('.jpg').strip('.png').strip('.jpeg')
    for picture in glob.glob('in/*'):
                continue
    pic_name = picture.split('/')[-1].lower().strip('.JPG').strip('.png').strip('.jpeg')
    output_file = 'out/' + bg_name + ' ' + pic_name + '.jpg'

    one_pic = time.time()
    GreenScreen(infile=picture ,inbg=bg, outfile=output_file)
    one_pic_time_done = time.time()

    time_arr.append(one_pic_time_done-one_pic)
    logger.info(time_arr)
    logger.info('done : %s' % pic_name)

def start_logging():
    logging.basicConfig()
    logger = logging.getLogger('greenbox')
    logger.setLevel(logging.INFO)
    return logger

if __name__ == '__main__':
    time_start = time.time()
    time_arr = []
    logger = start_logging()
    logger.info("Start time: %s" % time_start)
    check_folders(logger)    
    begin_greenbox(logger)
    time_end = time.time()
    logger.info("End time: %s" % time_end)

I obtain this error:

  File "chromakey+upload.py", line 116, in <module>
    begin_greenbox(logger)
  File "chromakey+upload.py", line 97, in begin_greenbox
    GreenScreen(infile=picture ,inbg=bg, outfile=output_file)
  File "chromakey+upload.py", line 56, in GreenScreen
    cleaned = subtract(inDataFG,colorMask) #subtract greens from input
TypeError: src1 is not a numpy array, neither a scalar

What is the problem? Thank you for your answers.


Solution

  • As the error says:

    src1 is not a numpy array, neither a scalar

    Perhaps, you should try:

    cleaned = subtract(numpy.array(inDataFG.getdata()),numpy.array(colorMask.getdata()))
    

    Edit

    There is a 'conflict' on subtract:

    from PIL.ImageChops import subtract # first subtract
    from cv2 import * # OpenCV has a subtract too
    

    This is one of the reasons to use namespaces on your calls.

    If your main image lib is PIL, maybe you should do import cv2 and use cv2.* when needed.