Different positions make differences

Hi,
I am doing Exercise: load_image2.py of OPenCV of Robotics. I think this is a problem about python itself:
when I do image-read in call_back() of topic '/camera/rgb/image_raw', and directly input msg into self.cv_bridge.imgmsg_to_cv2(), everything is alright. The code is:

#! /usr/bin/env python
import rospy
import cv2
import os
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError

class ROS_CV2_Image_Class():

    def __init__(self):

        # define subscriber of topic '/camera/rgb/image_raw'
        self.camera_sub = rospy.Subscriber(
            '/camera/rgb/image_raw', Image, self.camera_callback)
        self.img = Image()

        # define cv_bridge instance
        self.cv_bridge = CvBridge()

        # other things
        self.rate = rospy.Rate(1)
        self.count = 1

    def camera_callback(self, msg):

        self.img = msg
        # get image from drone and save it
        rospy.loginfo('showing ' + str(self.count) +
                      'th image from the drone......')
        # convert camera data into array
        try:
            image_from_drone = self.cv_bridge.imgmsg_to_cv2(
                self.img, desired_encoding="bgr8")
        except CvBridgeError as e:
            print(e)

        cv2.imshow('the image from the drone', image_from_drone)
        self.rate.sleep()
        self.count += 1

        # cv2.waitKey(i) functions as:
        # similar with time.sleep(i)
        cv2.waitKey(1)

    def main(self):

        try:
            rospy.spin()
        except KeyboardInterrupt:
            print("Shutting down")

        cv2.destroyAllWindows()


if __name__ == '__main__':

    rospy.init_node("load_image_2_node")
    ROS_cv2_image = ROS_CV2_Image_Class()
    ROS_cv2_image.main()

But when I only do self.img = msg in call_back() of topic '/camera/rgb/image_raw', and do self.cv_bridge.imgmsg_to_cv2() in main(), it shows error all the time. The code is:

#! /usr/bin/env python
import rospy
import cv2
import os
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError

class ROS_CV2_Image_Class():

    def __init__(self):

        # define subscriber of topic '/camera/rgb/image_raw'
        self.camera_sub = rospy.Subscriber(
            '/camera/rgb/image_raw', Image, self.camera_callback)
        self.img = Image()

        # define cv_bridge instance
        self.cv_bridge = CvBridge()

        # other things
        self.rate = rospy.Rate(1)
        self.count = 1

    def camera_callback(self, msg):

        self.img = msg

    def main(self):

        # get image from drone and save it
        rospy.loginfo('showing ' + str(self.count) +
                      'th image from the drone......')
        # convert camera data into array
        try:
            image_from_drone = self.cv_bridge.imgmsg_to_cv2(
                self.img, desired_encoding="bgr8")
        except CvBridgeError as e:
            print(e)

        cv2.imshow('the image from the drone', image_from_drone)
        self.rate.sleep()
        self.count += 1

        # cv2.waitKey(i) functions as:
        # similar with time.sleep(i)
        cv2.waitKey(1)

        try:
            rospy.spin()
        except KeyboardInterrupt:
            print("Shutting down")

        cv2.destroyAllWindows()


if __name__ == '__main__':

    rospy.init_node("load_image_2_node")
    ROS_cv2_image = ROS_CV2_Image_Class()
    ROS_cv2_image.main()

the error shows:

Unrecognized image encoding []
Traceback (most recent call last):
  File "/home/user/catkin_ws/src/unit2/src/load_image_2.py", line 81, in <module>
    ROS_cv2_image.main()
  File "/home/user/catkin_ws/src/unit2/src/load_image_2.py", line 61, in main
    cv2.imshow('the image from the drone', image_from_drone)
UnboundLocalError: local variable 'image_from_drone' referenced before assignment
[load_image_2_node-1] process has died [pid 4859, exit code 1, cmd /home/user/catkin_ws/src/unit2/src/load_image_2.py __name:=load_image_2_node __log:=/home/user/.ros/log/a302951c-6a6d-11ed-bfca-0242ac120007/load_image_2_node-1.log].
log file: /home/user/.ros/log/a302951c-6a6d-11ed-bfca-0242ac120007/load_image_2_node-1*.log

Do these 2 ways really have differences?

btw, can anyone explain: what does these 2 actually do?

cv2.waitKey(0)
cv2.destroyAllWindows()

when it is cv2.waitKey(0), it shows only one image all the time;
when it is cv2.waitKey(1), it changes images approximately every 1 second;
But it seems not like cv2.waitKey() functions as time.sleep(), because when I set it as cv2.waitKey(10), it changes images still approximately every 1 second.

Hi @MeineLiebeAxt ,

You must refer OpenCV documentation to know about the functions.

Refer these links:
waitKey:
https://docs.opencv.org/4.x/d7/dfc/group__highgui.html#ga5628525ad33f52eab17feebcfba38bd7

destroyAllWindows:
https://docs.opencv.org/3.4/d7/dfc/group__highgui.html#ga6b7fc1c1a8960438156912027b38f481

Regards,
Girish

PS: A tip for you: Google function definitions always. If you can’t find an answer / explanation, then ask in a forum.

Thanks! @girishkumar.kannan