0

i'm trying to write a program that mashes 2 images together with a function (using cv2) and then display it on screen with a GUI written in PyQT, so my first attempt was to do the following

imgComb = self.mergeimages(img1,img2)
self.label.setPixmap(QtGui.QPixmap(imgComb))

however the following code doesn't work, as setPixMap does not take Numpy Arrays object, as such i was suggested to use setpixmap.fromimage instead and convert the Numpy Array into an Image, and the Image into a QTImage with the following code

imgComb = self.mergeimages(img1,img2)
img3 = Image.fromarray(imgComb)
img4 = ImageQt(img3)
self.label.setPixmap(QtGui.QPixmap.fromImage(img4))

however, the following code makes python flat out crashes without giving any error code and giving exit code: 3221225477 the code works if i save the image into my HDD and then load it however i would like to avoid doing that, when i tried to figure out why there would be such a difference, i noticed that my created image was an object of type PIL.Image.Image but when loaded from my HDD it became of type PIL.PngImagePlugin.PngImageFile while searching for a solution i found a person who seemed to have a similar problem, though there was no satisfactory answer to his issue Why can't I make a GIF from PIL.Image.Image files but can with PIL.PngImagePlugin.PngImageFile? what can i do to solve this issue?

EDIT: Full code

from PyQt5 import QtCore, QtGui, QtWidgets
import random
import cv2
from PIL import Image
from PIL.ImageQt import ImageQt



class Ui_MainWindow(object):
    
    def mergeimages(self,img1,img2):

        img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
        ret, mask = cv2.threshold(img2_gray, 245, 255, cv2.THRESH_BINARY)
        mask_inv = cv2.bitwise_not(mask)
        Attack = cv2.bitwise_and(img1, img1, mask=mask)
        Defense = cv2.bitwise_and(img2, img2, mask=mask_inv)
        result = cv2.add(Defense,Attack)
        return result
    
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1000, 900)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(190, 20, 674, 478))
        self.label.setStyleSheet("ImageCombined.png")
        self.label.setText("")
        img1 = cv2.imread("Image1.png")
        img2 = cv2.imread("Image2.png")
        img2 = cv2.flip(img2,1)
        imgComb = self.mergeimages(img1,img2)
        img3 = Image.fromarray(imgComb)
        img4 = ImageQt(img3)
        self.label.setPixmap(QtGui.QPixmap.fromImage(img4))
        self.label.setScaledContents(True)
        self.label.setObjectName("label")
        MainWindow.setCentralWidget(self.centralwidget)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

All i want to do is display the resulting imgComb at the center of my GUI

Gran
  • 5
  • 4
  • Please provide a [mre]. You're not trying to use threading, are you? – musicamante Feb 16 '22 at 12:50
  • added the full code – Gran Feb 16 '22 at 13:36
  • I get an error from opencv already in the `mergeimages` function, and specifically the first `bitwise_and` line. In any case, run your code from a terminal or prompt to see the full traceback. – musicamante Feb 16 '22 at 20:15
  • i was able to find a solution by using the code described here to convert a numpy array into a QPixmap https://stackoverflow.com/questions/34232632/convert-python-opencv-image-numpy-array-to-pyqt-qpixmap-image – Gran Feb 17 '22 at 09:33

1 Answers1

1

Here's how you can convert cv2 image to pixmap

h, w, ch = cv2_image.shape

bytes_per_line = ch * w
converted = QtGui.QImage(imgComb.data, w, h, bytes_per_line, QtGui.QImage.Format_RGB888)

converted = converted.scaled(target_width, target_height, Qt.KeepAspectRatio) # Only if you want to scale image

pic = QtGui.QPixmap.fromImage(converted)
#pic is pixmap which can directly be set to QLabel

Here is your updated code

from PyQt5 import QtCore, QtGui, QtWidgets
import random
import cv2



class Ui_MainWindow(object):

    def mergeimages(self, img1, img2):
        img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
        ret, mask = cv2.threshold(img2_gray, 245, 255, cv2.THRESH_BINARY)
        mask_inv = cv2.bitwise_not(mask)
        Attack = cv2.bitwise_and(img1, img1, mask=mask)
        Defense = cv2.bitwise_and(img2, img2, mask=mask_inv)
        result = cv2.add(Defense, Attack)
        return result

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1000, 900)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(190, 20, 674, 478))
        self.label.setStyleSheet("ImageCombined.png")
        self.label.setText("")
        img1 = cv2.imread("Image1.png")
        img2 = cv2.imread("Image2.png")
        img2 = cv2.flip(img2, 1)
        imgComb = self.mergeimages(img1, img2)
# Change Start
        h, w, ch = imgComb.shape

        bytes_per_line = ch * w
        converted = QtGui.QImage(imgComb.data, w, h, bytes_per_line, QtGui.QImage.Format_RGB888)

        pic = QtGui.QPixmap.fromImage(converted)


        self.label.setPixmap(pic)
# Change End
        self.label.setScaledContents(True)
        self.label.setObjectName("label")
        MainWindow.setCentralWidget(self.centralwidget)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())
Ayush Shah
  • 468
  • 4
  • 9