Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I having image overlap issues while using PIL's Image.paste in a for loop?

I'm trying to generate 50 random profile images from a grouping of shapes, or attributes. There's groupings of different colored backgrounds, rectangles (placeholder for a body), circles (head), ovals (arms), and then a grouping of numbers. Every image has a transparent background, besides the background images which are solid colors. All images are PNG.

Currently, I'm running a for loop, generating a random number, and using that number to run functions that retrieve a random assortment of attribute images. I'm then using a chain of Image.paste to put the random set of attribute images together and saving to an outside folder.

Problem is, some of the generated images share overlapped attributes from previously generated images. Almost like the variables weren't reassigned. Here's an examples -

enter image description here

Here's the code I'm working with:

body1 = Image.open("test-images/body1.png")

# example of array of images
bodyArr = (body1, body2, body3, body4, body5, body6, body7, body8)

# example of function to select a position in above array
def getBody(num):
    result = int(num[2:4])

    if result < 12:
        return 0
    elif result >= 12 and result < 24:
        return 1
    elif result >= 24 and result < 36:
        return 2
    elif result >= 36 and result < 48:
        return 3
    elif result >= 48 and result < 60:
        return 4
    elif result >= 60 and result < 72:
        return 5
    elif result >= 72 and result < 84:
        return 6
    else:
        return 7

for x in range(0, 50):

    # generate random, 10 digit number
    randomStr = str(randint(100000000000, 999999999999))[1:11]

    # assigning images 
    backgroundImage = bgArr[getBg(randomStr)]
    bodyImage = bodyArr[getBody(randomStr)]
    headImage = headArr[getHead(randomStr)]
    armsImage = armsArr[getArms(randomStr)]
    numImage = numArr[getNum(randomStr)]

    backgroundImage.paste(bodyImage, (0,0), bodyImage)
    backgroundImage.paste(headImage, (0,0), headImage)
    backgroundImage.paste(armsImage, (0,0), armsImage)
    backgroundImage.paste(numImage, (0,0), numImage)

    imgname = f'{dirname}/profile_images/profile{x}.png'
    backgroundImage.save(imgname)

Any idea what could be causing this? I've tried to debug using a number of Image.show() to see where it's going wrong, but setting the "title" parameter in the method isn't working in Preview and it's tough to get a complete timeline.

Thank you for any help!

like image 203
Bruce Rayne Avatar asked Jan 25 '26 07:01

Bruce Rayne


1 Answers

Inside the for loop, your are taking shallow copy of backgroundImage from bgArr[getBg(randomStr)]. This means, your are using same object which might have been modified previously.

would you please try deepcopy?

import copy

# ...

for x in range(0, 50):
    #...
    # assigning images 
    backgroundImage = copy.deepcopy(bgArr[getBg(randomStr)])

From python doc, we see

Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other.

A deep copy constructs a new compound object and then, recursively, inserts copies into it of the objects found in the original.

like image 67
Uzzal Podder Avatar answered Jan 27 '26 21:01

Uzzal Podder



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!