By kaboomfox

2012-12-28 00:26:20 8 Comments

Hi I am creating a program that replaces a face in a image with someone else's face. However, I am stuck on trying to insert the new face into the original, larger image. I have researched ROI and addWeight(needs the images to be the same size) but I haven't found a way to do this in python. Any advise is great. I am new to opencv.

I am using the following test images:


enter image description here


enter image description here

Here is my Code so far... a mixer of other samples:

import cv2
import as cv
import sys
import numpy

def detect(img, cascade):
    rects = cascade.detectMultiScale(img, scaleFactor=1.1, minNeighbors=3, minSize=(10, 10), flags = cv.CV_HAAR_SCALE_IMAGE)
    if len(rects) == 0:
        return []
    rects[:,2:] += rects[:,:2]
    return rects

def draw_rects(img, rects, color):
    for x1, y1, x2, y2 in rects:
        cv2.rectangle(img, (x1, y1), (x2, y2), color, 2)

if __name__ == '__main__':
    if len(sys.argv) != 2:                                         ## Check for error in usage syntax

    print "Usage : python <image_file>"

    img = cv2.imread(sys.argv[1],cv2.CV_LOAD_IMAGE_COLOR)  ## Read image file

    if (img == None):                                     
        print "Could not open or find the image"
        cascade = cv2.CascadeClassifier("haarcascade_frontalface_alt.xml")
        gray = cv2.cvtColor(img, cv.CV_BGR2GRAY)
        gray = cv2.equalizeHist(gray)

        rects = detect(gray, cascade)

        ## Extract face coordinates         
        x1 = rects[0][3]
        y1 = rects[0][0]
        x2 = rects[0][4]
        y2 = rects[0][5]
        ## Extract face ROI
        faceROI = gray[x1:x2, y1:y2]

        ## Show face ROI
        cv2.imshow('Display face ROI', faceROI)
        small = cv2.imread("average_face.png",cv2.CV_LOAD_IMAGE_COLOR)  
        print "here"
        small=cv2.resize(small, (x, y))
        cv2.namedWindow('Display image')          ## create window for display
        cv2.imshow('Display image', small)          ## Show image in the window

        print "size of image: ", img.shape        ## print size of image


@Nadav B 2018-10-10 14:29:26

Here it is:

def put4ChannelImageOn4ChannelImage(back, fore, x, y):
    rows, cols, channels = fore.shape    
    trans_indices = fore[...,3] != 0 # Where not transparent
    overlay_copy = back[y:y+rows, x:x+cols] 
    overlay_copy[trans_indices] = fore[trans_indices]
    back[y:y+rows, x:x+cols] = overlay_copy

background = np.zeros((1000, 1000, 4), np.uint8)
background[:] = (127, 127, 127, 1)
overlay = cv2.imread('imagee.png', cv2.IMREAD_UNCHANGED)
put4ChannelImageOn4ChannelImage(background, overlay, 5, 5)

@guilhermeh2m 2018-10-05 13:26:19

For just add an alpha channel to s_img I just use cv2.addWeighted before the line l_img[y_offset:y_offset+s_img.shape[0], x_offset:x_offset+s_img.shape[1]] = s_img

as following:
s_img=cv2.addWeighted(l_img[y_offset:y_offset+s_img.shape[0], x_offset:x_offset+s_img.shape[1]],0.5,s_img,0.5,0)

@Torantula 2018-02-17 19:49:11

If anyone, like me, gets the error:

ValueError: assignment destination is read-only

when attempting to write to the destination image using any of these answers above.

A quick dirty fix is to set the WRITEABLE flag to true:


@Mateen Ulhaq 2017-07-15 12:06:35

Using @fireant's idea, I wrote up a function to handle overlays. This works well for any position argument (including negative positions).

def overlay_image_alpha(img, img_overlay, pos, alpha_mask):
    """Overlay img_overlay on top of img at the position specified by
    pos and blend using alpha_mask.

    Alpha mask must contain values within the range [0, 1] and be the
    same size as img_overlay.

    x, y = pos

    # Image ranges
    y1, y2 = max(0, y), min(img.shape[0], y + img_overlay.shape[0])
    x1, x2 = max(0, x), min(img.shape[1], x + img_overlay.shape[1])

    # Overlay ranges
    y1o, y2o = max(0, -y), min(img_overlay.shape[0], img.shape[0] - y)
    x1o, x2o = max(0, -x), min(img_overlay.shape[1], img.shape[1] - x)

    # Exit if nothing to do
    if y1 >= y2 or x1 >= x2 or y1o >= y2o or x1o >= x2o:

    channels = img.shape[2]

    alpha = alpha_mask[y1o:y2o, x1o:x2o]
    alpha_inv = 1.0 - alpha

    for c in range(channels):
        img[y1:y2, x1:x2, c] = (alpha * img_overlay[y1o:y2o, x1o:x2o, c] +
                                alpha_inv * img[y1:y2, x1:x2, c])

Usage is:

                    img_small[:, :, 0:3],
                    (x, y),
                    img_small[:, :, 3] / 255.0)

@Schütze 2018-08-08 01:44:34

IndexError: index 3 is out of bounds for axis 2 with size 3 is the error one gets with this.

@Alok Subedi 2018-08-09 08:37:31

how do i overlay the larger image's centroid with the smaller image's centroid? I have the centroids of both the images already. I used the function above, but the smaller image's leftmost pixel is automatically overlayed on the larger image.

@fireant 2012-12-31 13:07:58

A simple way to achieve what you want:

import cv2
s_img = cv2.imread("smaller_image.png")
l_img = cv2.imread("larger_image.jpg")
l_img[y_offset:y_offset+s_img.shape[0], x_offset:x_offset+s_img.shape[1]] = s_img

the result image


I suppose you want to take care of the alpha channel too. Here is a quick and dirty way of doing so:

s_img = cv2.imread("smaller_image.png", -1)

y1, y2 = y_offset, y_offset + s_img.shape[0]
x1, x2 = x_offset, x_offset + s_img.shape[1]

alpha_s = s_img[:, :, 3] / 255.0
alpha_l = 1.0 - alpha_s

for c in range(0, 3):
    l_img[y1:y2, x1:x2, c] = (alpha_s * s_img[:, :, c] +
                              alpha_l * l_img[y1:y2, x1:x2, c])

result image with alpha

@Jonathan Crowe 2016-06-25 17:54:24

I know this is an ancient question but would you mind adding an explanation of what is going on in the alpha channel example? I'm getting into cv2 and python and this stuff is still a huge question mark for me

@Adib 2016-06-30 05:56:12

Seconding Jonathan's request. I want to know what the math is doing so I can better debug the problem

@fireant 2016-07-14 18:58:42

@JonathanCrowe to overlay image1 over imag2, [result-image::rgb channel] = [image1::rgb-channel] * [imag1::alpha-channel] + [image2::rgb-channel] * (1.0-[imag1::alpha-channel]).

@fireant 2016-07-14 18:58:57

@Adib see the above comment

@GuySoft 2016-08-03 14:22:03

Hey, in the update your line is cut: l_img[y_offset:y_offset+s_img.shape[0], x_offset:x_offset+s_img.shape[1], c] = What did you mean there?

@Olezt 2017-03-29 16:39:33

It is not cut. The rest is on the next line. Works perfect. :) @GuySoft

@Kurt 2016-11-20 20:32:16

Based on fireant's excellent answer above, here is the alpha blending but a bit more human legible. You may need to swap 1.0-alpha and alpha depending on which direction you're merging (mine is swapped from fireant's answer).

o* == s_img.* b* == b_img.*

for c in range(0,3):
    alpha = s_img[oy:oy+height, ox:ox+width, 3] / 255.0
    color = s_img[oy:oy+height, ox:ox+width, c] * (1.0-alpha)
    beta  = l_img[by:by+height, bx:bx+width, c] * (alpha)

    l_img[by:by+height, bx:bx+width, c] = color + beta

Related Questions

Sponsored Content

26 Answered Questions

25 Answered Questions

[SOLVED] How can I safely create a nested directory in Python?

18 Answered Questions

[SOLVED] Does Python have a string 'contains' substring method?

55 Answered Questions

[SOLVED] Calling an external command in Python

26 Answered Questions

[SOLVED] Difference between append vs. extend list methods in Python

28 Answered Questions

[SOLVED] Finding the index of an item given a list containing it in Python

  • 2008-10-07 01:39:38
  • Eugene M
  • 3082418 View
  • 2544 Score
  • 28 Answer
  • Tags:   python list

32 Answered Questions

[SOLVED] How to get the current time in Python

  • 2009-01-06 04:54:23
  • user46646
  • 2521019 View
  • 2208 Score
  • 32 Answer
  • Tags:   python datetime time

23 Answered Questions

[SOLVED] What is the difference between @staticmethod and @classmethod?

15 Answered Questions

[SOLVED] What are metaclasses in Python?

1 Answered Questions

[SOLVED] openCV: cannot detect small shapes using findContours

  • 2017-10-08 07:40:30
  • Vic
  • 781 View
  • 1 Score
  • 1 Answer
  • Tags:   python opencv

Sponsored Content