Skip to content

Use Python PIL module to merge two images

Last Updated on 2020-11-30 by Clay


Introduction

Recently, because I have been studying the interface of the program, I got many strange problems.

I want to record today is how to merge two pictures. I found that if I simply use the composite() function in PIL, the second picture will be overwritten by the first picture. So, I started to try convert the background of the second picture to transparent.

After converting the image to a transparent background, the result of the merging is quite natural to me.

I will start to introduce how to merge two pictures in below.


Preparation

If you use pillow in the first time, you need to use the following command:

pip3 install pillow

Merge pictures

I have a dog picture to be example.

And then I have a canvas program. (You can use any QLabel to replace it.)

I saved the code as PaintLabel.py to rewrite the QLabel program in PyQt5.

# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *


class PLabel(QLabel):
    def __init__(self, centralwidget):
        super(PLabel, self).__init__(centralwidget)
        self.tracing_xy = []
        self.lineHistory = []
        self.pen = QPen(Qt.black, 10, Qt.SolidLine)


    def paintEvent(self, QPaintEvent):
        self.painter = QPainter()
        self.painter.begin(self)
        self.painter.setPen(self.pen)

        start_x_temp = 0
        start_y_temp = 0

        if self.lineHistory:
            for line_n in range(len(self.lineHistory)):
                for point_n in range(1, len(self.lineHistory[line_n])):
                    start_x, start_y = self.lineHistory[line_n][point_n-1][0], self.lineHistory[line_n][point_n-1][1]
                    end_x, end_y = self.lineHistory[line_n][point_n][0], self.lineHistory[line_n][point_n][1]
                    self.painter.drawLine(start_x, start_y, end_x, end_y)

        for x, y in self.tracing_xy:
            if start_x_temp == 0 and start_y_temp == 0:
                self.painter.drawLine(self.start_xy[0][0], self.start_xy[0][1], x, y)
            else:
                self.painter.drawLine(start_x_temp, start_y_temp, x, y)

            start_x_temp = x
            start_y_temp = y

        self.painter.end()

    def mousePressEvent(self, QMouseEvent):
        self.start_xy = [(QMouseEvent.pos().x(), QMouseEvent.pos().y())]

    def mouseMoveEvent(self, QMouseEvent):
        self.tracing_xy.append((QMouseEvent.pos().x(), QMouseEvent.pos().y()))
        self.update()

    def mouseReleaseEvent(self, QMouseEvent):
        self.lineHistory.append(self.start_xy+self.tracing_xy)
        self.tracing_xy = []


Then I stacked the two pictures together (the drawing board above):

I can paint whatever I want.

Then, we write a program to store the two pictures, the code is not long, plus the program that rewrites QLabel just now is only about 100 lines.

# -*- coding: utf-8 -*-
import sys

from PyQt5 import QtWidgets
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from label_test import Ui_MainWindow
from PIL import ImageQt, Image
from PaintLabel import PLabel


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.statusbar.setVisible(False)

        self.paintBoard = PLabel(self.ui.centralwidget)
        self.paintBoard.setGeometry(QRect(self.ui.label.pos(), self.ui.label.size()))

        self.add = QShortcut(QKeySequence("Ctrl+S"), self)
        self.add.activated.connect(self.compositeEvent)

    def compositeEvent(self):
        image1 = ImageQt.fromqpixmap(self.ui.label.pixmap())
        image2 = ImageQt.fromqimage(self.paintBoard.grab())
        image1 = image1.convert('RGBA')
        image2 = image2.resize(image1.size)

        # Transparency
        newImage2 = []
        for item in image2.getdata():
            if item[:3] == (240, 240, 240):
                newImage2.append((240, 240, 240, 0))
            else:
                newImage2.append(item)

        image2.putdata(newImage2)

        print(image1.mode, image1.size)
        print(image2.mode, image2.size)

        newImage = Image.alpha_composite(image1, image2)
        newImage.save('test.png')


if __name__ == '__main__':
    app = QtWidgets.QApplication([])
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())


The most important thing is actually this line:

newImage = Image.alpha_composite(image1, image2)


Use the alpha_composite() function to merge my two pictures together. The saved file is the picture of the dog pirate at the top of me.


References


Read More

Leave a Reply