Program Crashes ERROR when converting a numpy array to Pixmap
-
wrote on 16 Jan 2021, 16:56 last edited by
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.
-
wrote on 17 Jan 2021, 20:10 last edited by
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.
-
I just realized, at least in C++ there's no constructor taking a QImage. The method is QPixmap::fromImage
-
wrote on 16 Jan 2021, 20:05 last edited by duddal_
@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 ?
-
wrote on 17 Jan 2021, 08:01 last edited by duddal_
@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.
-
wrote on 17 Jan 2021, 19:52 last edited by
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_())
-
wrote on 17 Jan 2021, 20:10 last edited by
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!
1/10