2

Suppose I am taking an image from the webcam using opencv.

_, img = self.cap.read()  # numpy.ndarray (480, 640, 3)

Then I create a QImage qimg using img:

qimg = QImage(
    data=img,
    width=img.shape[1],
    height=img.shape[0],
    bytesPerLine=img.strides[0],
    format=QImage.Format_Indexed8)

But it gives an error saying that:

TypeError: 'data' is an unknown keyword argument

But said in this documentation, the constructor should have an argument named data.

I am using anaconda environment to run this project.

opencv version = 3.1.4

pyqt version = 5.9.2

numpy version = 1.15.0

Community
  • 1
  • 1
Rahat Zaman
  • 1,322
  • 14
  • 32

2 Answers2

3

What they are indicating is that the data is required as a parameter, not that the keyword is called data, the following method makes the conversion of a numpy/opencv image to QImage:

from PyQt5.QtGui import QImage, qRgb
import numpy as np
import cv2

gray_color_table = [qRgb(i, i, i) for i in range(256)]

def NumpyToQImage(im):
    qim = QImage()
    if im is None:
        return qim
    if im.dtype == np.uint8:
        if len(im.shape) == 2:
            qim = QImage(im.data, im.shape[1], im.shape[0], im.strides[0], QImage.Format_Indexed8)
            qim.setColorTable(gray_color_table)
        elif len(im.shape) == 3:
            if im.shape[2] == 3:
                qim = QImage(im.data, im.shape[1], im.shape[0], im.strides[0], QImage.Format_RGB888)
            elif im.shape[2] == 4:
                qim = QImage(im.data, im.shape[1], im.shape[0], im.strides[0], QImage.Format_ARGB32)
    return qim

img = cv2.imread('/path/of/image')
qimg = NumpyToQImage(img)
assert(not qimg.isNull())

or you can use the qimage2ndarray library

When using the indexes to crop the image is only modifying the shape but not the data, the solution is to make a copy

img = cv2.imread('/path/of/image')
img = np.copy(img[200:500, 300:500, :]) # copy image
qimg = NumpyToQImage(img)
assert(not qimg.isNull())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
  • I have another problem in this same context. If I crop the image by `img = img[200:500, 300:500, :]`, then create the qimg with `qimg = QImage(img.data, img.shape[1], img.shape[0], img.strides[0], qformat)`, then it says the error `TypeError: arguments did not match any overloaded call`. Why is this happening? – Rahat Zaman Jul 31 '18 at 08:05
  • @eyllanesc: spotted typo `qimg` in your answer at duplicate page. Should be `qim`. Now its an infinity loopback, right? Or is the assert dealing with this? Came here via https://stackoverflow.com/questions/54744449/whats-wrong-with-my-code-when-i-pressed-button-the-window-not-reponding – ZF007 Feb 18 '19 at 10:53
  • its about your answer here at: ~def NumpyToQImage(im): qim = QImage() if im is None: return qimg` But changing just one letter is not aloud by comm bot. That's why my remark. – ZF007 Feb 18 '19 at 11:03
  • @eyllanesc: created is the empty `qim = QImage()` array and `return qimg` when `im` is zero won't work. So it should be `return qim` and not `qimg`. In all other cases it keeps loading `qimg = NumpyToQImage(img)` and won't stop. – ZF007 Feb 18 '19 at 11:10
  • 1
    @ZF007 okay, I just understand, I recommend trying to highlight the error, as for example you could have told me change `return qim**g**` to `return qim`, thanks – eyllanesc Feb 18 '19 at 11:12
1

I suspect it is erroring out with TypeError: 'data' is an unknown keyword argument because that is the first argument that it encounters.

The linked class reference is for PyQt4, for PyQt5 it links to C++ documentation at https://doc.qt.io/qt-5/qimage.html, but the similarities are clear.

PyQt4:

QImage.__init__ (self, bytes data, int width, int height, int bytesPerLine, Format format)

Constructs an image with the given width, height and format, that uses an existing memory buffer, data. The width and height must be specified in pixels. bytesPerLine specifies the number of bytes per line (stride).

PyQt5 (C++):

QImage(const uchar *data, int width, int height, int bytesPerLine, QImage::Format format, QImageCleanupFunction cleanupFunction = nullptr, void *cleanupInfo = nullptr)

Constructs an image with the given width, height and format, that uses an existing memory buffer, data. The width and height must be specified in pixels. bytesPerLine specifies the number of bytes per line (stride).

Per the examples at https://www.programcreek.com/python/example/106694/PyQt5.QtGui.QImage, you might try

qimg = QImage(img, img.shape[1], img.shape[0], img.strides[0], QImage.Format_Indexed8)

(without the data=, width=, etc)

Community
  • 1
  • 1
Mick
  • 811
  • 14
  • 31