Solved Program Crashes ERROR when converting a numpy array to Pixmap
-
Hello guys,
I am working on an application wherein I load a binary (.bin) file and convert it to a 2D numpy array. I can read the binary file and I have also managed to convert it to a numpy array.
The name of the variable is out and its shape is (512, 1536). As the shape of the array is 2D, it is a grayscale image. The variable contains:out = array([[ 0, 107, 68, ..., 0, 2, 3], [ 47, 65, 66, ..., 0, 1, 0], [ 27, 24, 34, ..., 2, 0, 1], ..., [124, 127, 124, ..., 136, 140, 147], [125, 129, 125, ..., 130, 134, 132], [130, 126, 126, ..., 139, 134, 130]], dtype=uint8)
I used opencv to show the image:
import cv2 cv2.imshow('out', out)
This works and I can see the grayscale image in a new window.
However, when I try to convert the numpy array to Pixmap using the following code the program crashes without outputting any error:
qImg = QPixmap(QImage(out.data, out.shape[1], out.shape[0], QImage.Format_Grayscale8)) print(qImg)
The
print(qImg)
line should output a pixmap object but it doesn't and just crashes.What could the reason for this be?
Appreciate your help.
Thank You.
-
Okay, so it worked:
I used the following function to create a QImage:def numpyQImage(image): qImg = QImage() if image.dtype == np.uint8: if len(image.shape) == 2: channels = 1 height, width = image.shape bytesPerLine = channels * width qImg = QImage( image.data, width, height, bytesPerLine, QImage.Format_Indexed8 ) qImg.setColorTable([qRgb(i, i, i) for i in range(256)]) elif len(image.shape) == 3: if image.shape[2] == 3: height, width, channels = image.shape bytesPerLine = channels * width qImg = QImage( image.data, width, height, bytesPerLine, QImage.Format_RGB888 ) elif image.shape[2] == 4: height, width, channels = image.shape bytesPerLine = channels * width fmt = QImage.Format_ARGB32 qImg = QImage( image.data, width, height, bytesPerLine, QImage.Format_ARGB32 ) return qImg
After this,
new = out.copy() image = numpyQImage(new) pixmap = QPixmap.fromImage(image) label.setPixmap(pixmap) vbox = QVBoxLayout() vbox.addWidget(label) win.setLayout(vbox) win.show() sys.exit(app.exec_())
@SGaist Thank you for your help!
-
Hi,
You should take a look at this stack overflow thread.
It also links to a Python helper module that allows for numpy<->QImage conversion.
-
@SGaist
I have tried this and it still doesnot work. The program still crashes.q = qimage2ndarray.array2qimage(out) pix = QPixmap(q) # After this line the program crashes
-
I just realized, at least in C++ there's no constructor taking a QImage. The method is QPixmap::fromImage
-
@SGaist
I used:q = qimage2ndarray.array2qimage(out) pix = QPixmap.fromImage(q)
But the error still persists as in the program crashes.
Would it help if you have the complete numpy array(out) because what I have posted is a truncated version. -
A minimal test with a minimal numpy array would be nice indeed.
By the way, which version of Python, Numpy and PySide/PyQt are you using ?
-
@SGaist
Thanks for your reply. Morning.
Using PyQt5, Python 3.7.9 (Conda environment), Numpy (1.19.4)Please use this link to download the text file which contains the numpy array.
https://drive.google.com/file/d/1utNAS7srr4toCTBHIcRvm-mIGL3IPPB-/view?usp=sharingHow i run the script:
import numpy as np import sys from PyQt5.QtGui import QImage, QPixmap from PyQt5.QtWidgets import QApplication, QLabel import matplotlib.pyplot as plt import qimage2ndarray var = np.array(np.loadtxt('out.txt')).astype(np.uint8) new_var = var.copy() q = qimage2ndarray.array2qimage(new_var) pix = QPixmap.fromImage(q) # Program crashes here app = QApplication(sys.argv) w = QLabel() w.setPixmap(pixmap) w.show() sys.exit(app.exec_())
I have also tried following but still no luck.
qImg = QPixmap.fromImage(QImage(new_var.data, new_var.shape[1], new_var.shape[0], new_var.strides[0], QImage.Format_Grayscale8))
Please let me know if you cannot open the link.
Edit 1:
According to this link(https://stackoverflow.com/questions/58366734/converting-numpy-image-to-qpixmap) I also tried the following (extension of the script):from PyQt5.QtGui import qRgb GRAY_COLORTABLE = [qRgb(i, i, i) for i in range(256)] img_array = out.copy() # img_array.strides = (1536, 1) bytesPerLine = img_array.strides[1] # Hence here indexed 1 for Grayscale image print(f'strides:{img_array.strides[1]}') # Channel = 1 For grayscale image height, width = img_array.shape image = QImage(img_array.data, width, height, bytesPerLine, QImage.Format_Indexed8) image.setColorTable(GRAY_COLORTABLE) print('image: ', image) print('test') new = image.copy() pixmap = QPixmap.fromImage(new) # Program crashes here print(pixmap) # Cannot print this
And still it doesn't work. I cannot print the Pixmap object let alone set it on a Label.
I cannot get my head around this. Appreciate any help I can get.
-
I have not run your script yet but one big issue you have is that you try to create your QPixmap before your QApplication object. Contrary to QImage, QPixmap requires a connection to the windowing system which is setup by QApplication.
-
So you were right. Even though I can print the pixmap object, the window (label) doesn't show the image.
import numpy as np import sys from PyQt5.QtGui import QImage, QPixmap, QColor, qRgb from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout win = QWidget() label = QLabel() GRAY_COLORTABLE = [qRgb(i, i, i) for i in range(256)] out = np.array(np.loadtxt('out.txt')).astype(np.uint8) img_array = out.copy() bytesPerLine = img_array.strides[1] height, width = img_array.shape image = QImage(img_array.data, width, height, bytesPerLine, QImage.Format_Indexed8) image.setColorTable(GRAY_COLORTABLE) print('image: ', image) # new = image.copy() pixmap = QPixmap.fromImage(image) print(pixmap) # I can see the pixmap object now label.setPixmap(pixmap) vbox = QVBoxLayout() vbox.addWidget(label) win.setLayout(vbox) win.show() sys.exit(app.exec_())
-
Okay, so it worked:
I used the following function to create a QImage:def numpyQImage(image): qImg = QImage() if image.dtype == np.uint8: if len(image.shape) == 2: channels = 1 height, width = image.shape bytesPerLine = channels * width qImg = QImage( image.data, width, height, bytesPerLine, QImage.Format_Indexed8 ) qImg.setColorTable([qRgb(i, i, i) for i in range(256)]) elif len(image.shape) == 3: if image.shape[2] == 3: height, width, channels = image.shape bytesPerLine = channels * width qImg = QImage( image.data, width, height, bytesPerLine, QImage.Format_RGB888 ) elif image.shape[2] == 4: height, width, channels = image.shape bytesPerLine = channels * width fmt = QImage.Format_ARGB32 qImg = QImage( image.data, width, height, bytesPerLine, QImage.Format_ARGB32 ) return qImg
After this,
new = out.copy() image = numpyQImage(new) pixmap = QPixmap.fromImage(image) label.setPixmap(pixmap) vbox = QVBoxLayout() vbox.addWidget(label) win.setLayout(vbox) win.show() sys.exit(app.exec_())
@SGaist Thank you for your help!