Python 订阅服务器无法从发布服务器读取图像

Python 订阅服务器无法从发布服务器读取图像,python,pyqt5,ros,Python,Pyqt5,Ros,我一直试图通过集成opencv和pyqt5,让订阅者用GUI显示一个图像,但在我单击按钮后,图像没有显示出来。在我将pyqt5集成到订阅服务器之前,它能够显示一个只有opencv本身的图像 -我正在使用Ubuntu 18.04 我的发布者代码: def main(): image_pub = rospy.Publisher("/image", Image, queue_size=1) rate = rospy.Rate(50) bridge = CvBridge() whi

我一直试图通过集成opencv和pyqt5,让订阅者用GUI显示一个图像,但在我单击按钮后,图像没有显示出来。在我将pyqt5集成到订阅服务器之前,它能够显示一个只有opencv本身的图像

-我正在使用Ubuntu 18.04

我的发布者代码:

def main():
image_pub = rospy.Publisher("/image", Image, queue_size=1)
rate = rospy.Rate(50)
bridge = CvBridge()

while not rospy.is_shutdown():
      print("------------Mask detection processing one time!------------")

      image_path='/home/sk/catkin_ws/src/test/scripts/p_e.png'
      cv_image = cv2.imread(image_path)

      # read a image using opencv
      # change to your real image path    

      print(cv_image.shape)
      #cv2.imshow("Pikachu", cv_image)
      msg_image = bridge.cv2_to_imgmsg(cv_image, encoding = "bgr8") 

      stamp = rospy.Time.now()
      msg_image.header.frame_id = "camera_link"
      msg_image.header.stamp = stamp

      image_pub.publish(msg_image)
      rate.sleep()
if __name__ == '__main__':
try:
  rospy.init_node('image_pub_node', anonymous=True)
  main()
  rospy.spin()
except KeyboardInterrupt:
  print("Shutting down")
  sys.exit(0)
  pass
我的订户代码:

class ImageWidget(QtWidgets.QWidget):
#def callback(self,data):
def callback(self,rosdata):
  global cv_image      
  #self.bridge = CvBridge()
  self.bridge = CvBridge()
  #print("in callback")
  rate = rospy.Rate(10)
  rate.sleep() 
  try:
    cv_image = self.bridge.imgmsg_to_cv2(rosdata, "bgr8")
    #cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")    

  except CvBridgeError as e:                            
      print(e)


def __init__(self, parent=None):

    super(ImageWidget, self).__init__(parent)

    self.button = QtWidgets.QPushButton('Show picture')
    self.button.clicked.connect(self.main)
    self.image_frame = QtWidgets.QLabel()

    self.layout = QtWidgets.QVBoxLayout()
    self.layout.addWidget(self.button)
    self.layout.addWidget(self.image_frame)
    self.setLayout(self.layout)

def main(self):

    rospy.init_node('image_sub_node', anonymous=True)
    self.image_sub = rospy.Subscriber("/image", Image, self.callback, queue_size=1, buff_size=52428800)
    
    rate = rospy.Rate(50) #50Hz
    bridge = CvBridge()
  
    while not rospy.is_shutdown():
      print("------------Mask detection processing one time!------------")

      try:
        self.cv_image = cv2.imread('Image')
        self.cv_image = QtGui.QImage(self.cv_image.data, self.cv_image.shape[1], self.cv_image.shape[0], QtGui.QImage.Format_RGB888).rgbSwapped()
        self.image_frame.setPixmap(QtGui.QPixmap.fromImage(self.cv_image))
      except Exception:
        continue

        rate.sleep()
if __name__ == '__main__':
try:
  app = QtWidgets.QApplication(sys.argv)
  image_widget = ImageWidget()
  image_widget.show()
  sys.exit(app.exec_())
  rospy.init_node('image_sub_node', anonymous=True)
  main()
  rospy.spin()
except KeyboardInterrupt:
  pass
exec_389;()方法执行eventloop,因此它只会在Qt完成执行后完成执行,如果将其与sys.exit关联,则后续代码将永远不会执行

另一方面,您不应该使用while循环,而只需要使用eventloop,并使用信号将回调(在辅助线程中执行)中的信息发送到窗口

import sys

from PyQt5 import QtCore, QtGui, QtWidgets
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError
import rospy
import cv2


class SubscriberManager(QtCore.QObject):
    imageChanged = QtCore.pyqtSignal(QtGui.QImage)

    def __init__(self, parent=None):
        super(SubscriberManager, self).__init__(parent)
        self.bridge = CvBridge()
        self.subscriber = None

    def start(self, name):
        self.stop()
        self.subscriber = rospy.Subscriber(
            name, Image, self._callback, queue_size=1, buff_size=52428800
        )

    def stop(self):
        if self.subscriber is not None:
            self.subscriber.unregister()
            self.subscriber = None

    def _callback(self, rosdata):
        try:
            cv_image = self.bridge.imgmsg_to_cv2(rosdata, "bgr8")
        except CvBridgeError as e:
            print(e)
        else:
            src = cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB)
            h, w, ch = src.shape
            bytesPerLine = ch * w
            qImg = QtGui.QImage(
                src.data, w, h, bytesPerLine, QtGui.QImage.Format_RGB888
            )
            self.imageChanged.emit(qImg)


class ImageWidget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(ImageWidget, self).__init__(parent)

        self.button = QtWidgets.QPushButton("Show picture")
        self.image_frame = QtWidgets.QLabel()

        lay = QtWidgets.QVBoxLayout(self)
        lay.addWidget(self.button)
        lay.addWidget(self.image_frame)

        self.subscribe_manager = SubscriberManager()

        self.subscribe_manager.imageChanged.connect(self.on_image_changed)
        self.button.clicked.connect(self.start)

    def start(self):
        self.subscribe_manager.start("/image")

    @QtCore.pyqtSlot(QtGui.QImage)
    def on_image_changed(self, image):
        self.image_frame.setPixmap(QtGui.QPixmap.fromImage(image))


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)

    rospy.init_node("image_sub_node", anonymous=True)

    image_widget = ImageWidget()
    image_widget.show()
    sys.exit(app.exec_())