QImage(img.data,...) out of scope - img.data gets deleted when QImage is destroyed
-
Hi, im a newbie,
i have a livestream with overlays which are changing when hitting a keybutton. After some minutes the livestream is freezing and then second later crashing without any action or error. ive read some where that the QImage(img.data...) is going out of scope and i must delete when QImage gets destroyed or explicite copy the data. Here is my snapshot of my code.# Display Geometrie MyApp = QtWidgets.QApplication(sys.argv) V = MyApp.desktop().screenGeometry() h = V.height() w = V.width() HEIGHT= 1080 WIDTH = 1920 class MainWindow(QWidget): # Start Button Action def pushbutton_left_Callback(self): if not self.timer.isActive(): self.loading_screen = LoadingScreen() self.cap = cv2.VideoCapture(1) if not (self.cap.isOpened()): self.noWebCam() # for using two external webcam if self.spsn == True: self.timer.start(5) else: self.timer.start(35) # +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++# # ----------------------- Live Stream functions --------------------------# def cap_img(self, cap): ret, img = cap.read() img = cv2.flip(img,1)#flip cam img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) height, width, channel = img.shape step = channel * width img = QImage(img.data, width, height, step, QImage.Format_RGB888) if height != HEIGHT and width != WIDTH: img = img.scaled(WIDTH, HEIGHT) return img def snap_img(self, cap): ret, img = cap.read() img = cv2.flip(img,1)#flip cam self.snap_cv = img.copy() img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) height, width, channel = img.shape step = channel * width self.snap = QImage(img.data, width, height, step, QImage.Format_RGB888) if height != HEIGHT and width != WIDTH: self.snap = self.snap.scaled(WIDTH, HEIGHT) # Show Livestream def livestream_overlays(self): super().__init__() self.overlay_base() # red lines as overlays if self.state == 1 or self.state == 2: self.overlay_red() elif self.state == 3: self.overlay_blue() # green lines as overlays (L-Button) if self.lvalue: self.overlay_green() # Show Livestream with overlays if self.spsn == True: img = self.img.scaled(int(w/2), int(h)) self.img2 = self.img2.scaled(int(w/2), int(h)) if self.state_cams == True: self.show_cam(self.img2,2) self.show_cam(img,3) else: self.show_cam(self.img2,3) self.show_cam(img,2) else: img = self.img.scaled(w, h) self.show_cam(img,1) def insertShape(self, img1, lines, linewidth, color): img = img1.copy() painter = QPainter() pixmap = QPixmap(img) painter.begin(img) painter.setRenderHint(QPainter.Antialiasing) painter.drawPixmap(img.rect(), pixmap) painter.setPen(QPen(colors[color], linewidth)) for line in lines: painter.drawLine(line[0],line[1],line[2],line[3]) return img def overlay_base(self): if self.pop != None: if self.pop.chns != None: self.ns = self.pop.chns self.pop = None img = self.cap_img(self.cap) img = self.insertShape(img, self.yellowline, 2, 'yellow') if self.spsn == True: img2 = self.cap_img(self.cap2) self.img2 = self.insertShape(img2, self.yellowline, 2, 'yellow') if self.spsn == True: if self.state_cams == True: self.set_nsheet(img,self.ns) else: self.set_nsheet(self.img2,self.ns) else: self.set_nsheet(img,self.ns) # set paramenter overlays if visible_parameter_overlays ==1: if self.spsn == True: if self.state_cams == True: img = self.set_parameter_overlays(img) else: self.img2 = self.set_parameter_overlays(self.img2) else: img = self.set_parameter_overlays(img) self.img = img def overlay_red(self): redlines = self.outputs['redlines'] self.img = self.insertShape(self.img, redlines, 2, 'red') if self.spsn == True: self.img2 = self.insertShape(self.img2, redlines, 2, 'red') def overlay_blue(self): bluelines = self.outputs['bluelines'] self.img = self.insertShape(self.img, bluelines, 2, 'blue') if self.spsn == True: self.img2 = self.insertShape(self.img2, bluelines ,2, 'blue') def overlay_green(self): greenlines = self.outputs['lines'] self.img = self.insertShape(self.img, greenlines, 2, 'green') if self.spsn == True: self.img2 = self.insertShape(self.img2, greenlines ,2, 'green') if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) mainWindow = MainWindow() mainWindow.showFullScreen() sys.exit(app.exec_())
I dont know how i must do it. Does somebody has a idea or a example what i need to do?
Thank You all -
@gerrard87
I'm just not sure with Python's reference counting and garbage collection whether yourimg.data
stays in existence, as required by thatQImage
constructor. Why don't you try something like:img = QImage(width, height, QImage.Format_RGB888) img.loadFromData(img.data, len(img.data))
which I believe manages the data for you to see whether it makes any differenece?
If your app crashes after a while check computer's free memory available to see if it's endlessly allocating.
-
I already told them on so that he simply should use QImage::copy() to make sure the image data is copied. But ...
-
@JonB said in QImage(img.data,...) out of scope - img.data gets deleted when QImage is destroyed:
img.loadFromData(img.data, len(img.data))
i get a Error when i using:
img = QImage(img.data, width, height, step, QImage.Format_RGB888) img.loadFromData(img.data, len(img.data))
AttributeError: 'QImage' object has no attribute 'data' ? Whats wrong?
-
@gerrard87 said in QImage(img.data,...) out of scope - img.data gets deleted when QImage is destroyed:
Whats wrong?
The error message already told you what is wrong.
Also easy to find out that there is no data property in QImage (read its docu).
What you need is rather https://doc.qt.io/qt-5/qimage.html#bits-1But i don't understand what you are doing.
You create a QImage from another one (first line), then you call loadFromData from exact same image (second line) - what is the point? -
@gerrard87 said in QImage(img.data,...) out of scope - img.data gets deleted when QImage is destroyed:
AttributeError: 'QImage' object has no attribute 'data' ? Whats wrong?
But I copied my
img.data
from yourimg = QImage(img.data, width, height, step, QImage.Format_RGB888)
. I did say "something like", you are supposed to figure it yourself....Oh, I see, you are using the same-named local
img
variable for two different types of image object! Just why Python is so meh....You are using
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
. So use a different variable name for theQImage
now. -
@JonB said in QImage(img.data,...) out of scope - img.data gets deleted when QImage is destroyed:
@gerrard87 said in QImage(img.data,...) out of scope - img.data gets deleted when QImage is destroyed:
AttributeError: 'QImage' object has no attribute 'data' ? Whats wrong?
But I copied my
img.data
from yourimg = QImage(img.data, width, height, step, QImage.Format_RGB888)
. I did say "something like", you are supposed to figure it yourself....Oh, I see, you are using the same-named local
img
variable for two different types of image object! Just why Python is so meh....You are using
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
. So use a different variable name for theQImage
now.mmh so just change this?
def cap_img(self, cap): ret, img = cap.read() img = cv2.flip(img,1)#flip cam img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) height, width, channel = img.shape step = channel * width img_new= QImage(img.data, width, height, step, QImage.Format_RGB888) if height != HEIGHT and width != WIDTH: img = img.scaled(WIDTH, HEIGHT) return img
would that be enough? its not working because scaled is not found (object has no attribute 'scaled')
-
@gerrard87 said in QImage(img.data,...) out of scope - img.data gets deleted when QImage is destroyed:
img_new= QImage(img.data, width, height, step, QImage.Format_RGB888) if height != HEIGHT and width != WIDTH: img = img.scaled(WIDTH, HEIGHT)
Don't you think there's something wrong here?
And you forgot the copy - just saying it for the third time...
-
@gerrard87 said in QImage(img.data,...) out of scope - img.data gets deleted when QImage is destroyed:
its not working because scaled is not found (object has no attribute 'scaled')
Why do you think that is? You should understand what you are doing/changing, not just copy & paste.
-
@Christian-Ehrlicher said in QImage(img.data,...) out of scope - img.data gets deleted when QImage is destroyed:
I already told them on so that he simply should use QImage::copy() to make sure the image data is copied. But ...
sorry i just started with python and im still learning. I got this code from a friend and now i must work with it.
Can you help me how the line with Qimage::copy() must look like? Still dont know how to make it work. -
Hi,
I would recommend that you do all image manipulation with OpenCV since you have the original data in it.
Then
return QImage(img.data, width, height, step, QImage.Format_RGB888).copy()
-
@SGaist said in QImage(img.data,...) out of scope - img.data gets deleted when QImage is destroyed:
return QImage(img.data, width, height, step, QImage.Format_RGB888).copy()
ok thank you, but what you mean with doing all the stuff with OpenCV? What kind of function in particular? I thought i was already doing everything with OpenCV?!
THank You all. -
You are not doing the resizing with OpenCV.