This is the 30th day of my participation in the August Text Challenge.More challenges in August
preface
Some time ago in a friend so got the inspiration, thought can use music playing page as a poster picture. In fact, there is still a gap between what we want to talk about and posters, and the specific implementation is just a simple picture paste, but the effect is still good. The effect picture is as follows, I hope you like it:
On the left is the original image, and on the right is the image that needs to be added to the middle, which is also the main character of the image. In fact, it is very easy to implement the above image directly in PHOTOSHOP, but it is a little tortuous to implement in code, but the implementation process is still very interesting, I hope this blog can let you learn knowledge.
Use the Pillow to create a circle diagram
In the image above, there is a round image in the middle, and the Pillow itself does not provide a way to generate a round image (or MAYBE I did not find it), so I need to implement it myself. To implement this, we install the Pillow module:
pip install pillow
Copy the code
To create a circle image, we first create an RGBA transparent image based on the size of the original image:
This method takes in three parameters, the first is mode, the second is a tuple of size, and the third is color
im = Image.new('RGBA', (300.300), (255.255.255.0))
Copy the code
The above code creates a fully transparent 300 by 300 image on which we draw the largest circle:
# Get Carver
drawer = ImageDraw.Draw(im)
The ellipse method takes three parameters: the first is the area containing the smallest square of the circle, the second is the color, and the third is the edge width
drawer.ellipse((0.0.300.300), fill=(255.255.0), width=0)
Copy the code
The generated images are as follows:
We prepare A 300 by 300 square image and walk through every pixel of the image. If the pixel value is A==0 (i.e. the pixel is opaque) then we set the pixel value in that area of the image to transparent.
The code is as follows:
To convert the image into a circle, we crop the image beforehand
pic = Image.open(img_path).convert('RGBA')
Walk through every pixel of the image
for i in range(300) :for j in range(300) :Get the pixel of this pixel
r, g, b, a = im.getpixel((i, j))
# When RGB value is not yellow, i.e., when pixel value is transparent
if(r, g, b) ! = (255.255.0) :# Set the pixel value of the original image to transparent
pic.putpixel((i, j), (255.255.255.0))
Copy the code
Our PIC is a circular picture, the complete code is as follows:
# The diameter of the circle in the background
radius = 533
# Size of picture
circle_size = (radius, radius)
def generate_circle_image(img_path) :
Create a transparent square
im = Image.new('RGBA', circle_size, (255.255.255.0))
# Get the painter
drawer = ImageDraw.Draw(im)
# Draw a yellow circle on the transparent square
drawer.ellipse((0.0, circle_size[0], circle_size[1]), fill=(255.255.0), width=0)
To convert the image into a circle, we crop the image beforehand
pic = Image.open(img_path).convert('RGBA')
# Resize the image so that it matches the size of the circle
re_pic = pic.resize(circle_size, Image.ANTIALIAS)
Walk through every pixel of the image
for i in range(circle_size[0) :for j in range(circle_size[1]):
r, g, b, a = im.getpixel((i, j))
if(r, g, b) ! = (255.255.0):
re_pic.putpixel((i, j), (255.255.255.0))
return re_pic
Copy the code
In the above method, we have improved the code so that we need to use images of the specified size as materials, but now we only need to use square images.
Generate a poster
Originally I thought I could paste the round image directly onto the background image, but after trying it, I found that the effect is not quite what I expected. Anyway, it didn’t work, and the effect is as follows:
Yes, it is pasted in, and the image is also transparent, but from this effect, paste is only pixel replacement, not image overlay. So I came up with the idea of traversing pixels.
I used a special method to get the pixels from the top square to the left, and the pixels from the top. I tried image detection and pixel determination to automatically identify the position of the middle circle, but it didn’t work very well (it just failed anyway), so I shamelessly used Photoshop to look at the pixels.
To get back to the point, instead of traversing the entire image, we just need to start from the (left, top) pixel and traverse to the (left+ RADIUS, top+ RADIUS) region, i.e. traverse the square region (left, top and RADIUS are all obtained by photoshop).
We first copy the background picture and paste it on the copy. Then iterate over the pasted image. If the pixel value is transparent, we will replace the pixel at the position of the original image to the copy. The implementation principle is the same as above, the code is as follows:
def generate_music_post(circle_im, bg_im) :
Circle_im: circle picture bg_im: background picture return: generated picture """
# copy copy
bg_copy = bg_im.copy()
# Paste the round picture onto the copy
bg_copy.paste(circle_im, (left, top))
# Walk through the pixel square area
for i in range(left, left+radius):
for j in range(top, top+radius):
Get the pixel value
color = bg_copy.getpixel((i, j))
# If the pixel is transparent. The value of color is (r,g,b,a), and color[3] is the value of A, that is, the transparent value
if color[3] = =0:
# Replace the original pixel with the transparent part of the copy
bg_copy.putpixel((i, j), bg_im.getpixel((i, j)))
# Return the composited image
return bg_copy
Copy the code
And you’re done. The complete code is as follows:
from PIL import Image, ImageDraw
left = 273 # Distance of the circle from the left
top = 573 # Distance of the circle from the top
radius = 533 # Diameter of the circle
circle_size = (radius, radius) # The size of the square enclosing the circle
def generate_circle_image(img_path) :
Create a transparent square
im = Image.new('RGBA', circle_size, (255.255.255.0))
# Get the painter
drawer = ImageDraw.Draw(im)
# Draw a yellow circle on the transparent square
drawer.ellipse((0.0, circle_size[0], circle_size[1]), fill=(255.255.0), width=0)
To convert the image into a circle, we crop the image beforehand
pic = Image.open(img_path).convert('RGBA')
re_pic = pic.resize(circle_size, Image.ANTIALIAS)
Walk through every pixel of the image
for i in range(circle_size[0) :for j in range(circle_size[1]):
r, g, b, a = im.getpixel((i, j))
if(r, g, b) ! = (255.255.0):
re_pic.putpixel((i, j), (255.255.255.0))
return re_pic
def generate_music_post(circle_im, bg_im) :
Circle_im: circle picture bg_im: background picture return: generated picture """
# copy copy
bg_copy = bg_im.copy()
# Paste the round picture onto the copy
bg_copy.paste(circle_im, (left, top))
# Walk through the pixel square area
for i in range(left, left+radius):
for j in range(top, top+radius):
Get the pixel value
color = bg_copy.getpixel((i, j))
# If the pixel is transparent. The value of color is (r,g,b,a), and color[3] is the value of A, that is, the transparent value
if color[3] = =0:
# Replace the original pixel with the transparent part of the copy
bg_copy.putpixel((i, j), bg_im.getpixel((i, j)))
# Return the composited image
return bg_copy
# Generate a circular image
pic = generate_circle_image('girl.jpeg')
# Read background images in RGBA mode
bg_im = Image.open('music.jpg').convert('RGBA')
# Generate music posters
music_post = generate_music_post(pic, bg_im)
music_post.show()
Copy the code
Plus, this example could be even smarter. We can use OpenCV to recognize the face of the subject image, and then calculate a more suitable square area based on the face area, so we don’t have to pass in the square (but there are still issues such as accuracy of face recognition).
Code uploaded making address is as follows: https://github.com/IronSpiderMan/MusicPost
The source pictures are also in there.