Reproduce Python 2 PyQt4 QImage constructor behavior in Python 3 -
i have written small gui using pyqt4 displays image , gets point coordinates user clicks on. need display 2d numpy array grayscale, creating qimage array, creating qpixmap. in python 2 works fine.
when moved python 3, however, can't decide on constructor qimage - gives me following error:
typeerror: arguments did not match overloaded call: qimage(): many arguments qimage(qsize, qimage.format): argument 1 has unexpected type 'numpy.ndarray' qimage(int, int, qimage.format): argument 1 has unexpected type 'numpy.ndarray' qimage(str, int, int, qimage.format): argument 1 has unexpected type 'numpy.ndarray' qimage(sip.voidptr, int, int, qimage.format): argument 1 has unexpected type 'numpy.ndarray' qimage(str, int, int, int, qimage.format): argument 1 has unexpected type 'numpy.ndarray' qimage(sip.voidptr, int, int, int, qimage.format): argument 1 has unexpected type 'numpy.ndarray' qimage(list-of-str): argument 1 has unexpected type 'numpy.ndarray' qimage(str, str format=none): argument 1 has unexpected type 'numpy.ndarray' qimage(qimage): argument 1 has unexpected type 'numpy.ndarray' qimage(object): many arguments
as far can tell, qimage constructor calling 1 of these:
qimage(str, int, int, qimage.format)
qimage(sip.voidptr, int, int, qimage.format)
i'm assuming numpy array fits 1 of protocols necessary 1 of these. i'm thinking might have array versus view, variations i've tried either produce above error or make gui exit without doing anything. how can reproduce python 2 behavior in python 3?
the following small example, in same exact code works fine under python 2 not python 3:
from __future__ import (print_function, division) pyqt4 import qtgui, qtcore import numpy np class mouseview(qtgui.qgraphicsview): mouseclick = qtcore.pyqtsignal(tuple) def __init__(self, scene, parent=none): super(mouseview, self).__init__(scene, parent=parent) def mousepressevent(self, event): self.mouseclick.emit((event.x(), self.scene().scenerect().height() - event.y())) class simplepicker(qtgui.qdialog): def __init__(self, data, parent=none): super(simplepicker, self).__init__(parent) mind = data.min() maxd = data.max() bdata = ((data - mind) / (maxd - mind) * 255.).astype(np.uint8) wdims = data.shape wid = wdims[0] hgt = wdims[1] # line of interest - works fine under python 2, not python 3 img = qtgui.qimage(bdata.t, wid, hgt, qtgui.qimage.format_indexed8) self.scene = qtgui.qgraphicsscene(0, 0, wid, hgt) self.px = self.scene.addpixmap(qtgui.qpixmap.fromimage(img)) view = mouseview(self.scene) view.sethorizontalscrollbarpolicy(qtcore.qt.scrollbaralwaysoff) view.setverticalscrollbarpolicy(qtcore.qt.scrollbaralwaysoff) view.setsizepolicy(qtgui.qsizepolicy.fixed, qtgui.qsizepolicy.fixed) view.setminimumsize(wid, hgt) view.mouseclick.connect(self.click_point) quitb = qtgui.qpushbutton("done") quitb.clicked.connect(self.quit) lay = qtgui.qvboxlayout() lay.addwidget(view) lay.addwidget(quitb) self.setlayout(lay) self.points = [] def click_point(self, xy): self.points.append(xy) def quit(self): self.accept() def test_picker(): x, y = np.mgrid[0:100, 0:100] img = x * y app = qtgui.qapplication.instance() if app none: app = qtgui.qapplication(['python']) picker = simplepicker(img) picker.show() app.exec_() print(picker.points) if __name__ == "__main__": test_picker()
i using anaconda installation on windows 7 64-bit, qt 4.8.7, pyqt 4.10.4, numpy 1.9.2.
in pyqt constructor above, following behavior observed numpy array called bdata
:
bdata
works correctly both python 2 , python 3bdata.t
works 2, not 3 (constructor error)bdata.t.copy()
works bothbdata[::-1,:]
not work either 2 or 3 (the same error)bdata[::-1,:].copy()
works bothbdata[::-1,:].base
works both, loses result of reverse operation
as mentioned @ekhumoro in comments, need supports python buffer protocol. actual qt constructor of interest here this qimage constructor, or const version of it:
qimage(uchar * data, int width, int height, format format)
from pyqt 4.10.4 documentation kept here, pyqt expects unsigned char *
different in python 2 , 3:
python 2:
if qt expects
char *
,signed char *
orunsigned char *
(or const version) pyqt4 accept unicode or qstring contains ascii characters, str, qbytearray, or python object implements buffer protocol.
python 3:
if qt expects
signed char *
orunsigned char *
(or const version) pyqt4 accept bytes.
a numpy array satisfies both of these, apparently numpy view doesn't satisfy either. it's baffling bdata.t
works @ in python 2, purportedly returns view:
>>> = np.ones((2,3)) >>> b = a.t >>> b.base true
the final answer: if need transformations result in view, can avoid errors doing copy()
of result new array passing constructor. may not best answer, work.
Comments
Post a Comment