making a laser detector have an error in my code

2019-08-26 08:10发布

问题:

I am making a program that detects lasers and circles and numbers then with the opencv library. This is my first time using ros indigo and I don't really know what I am doing but I am getting an error that is repeating at a rapid rate when I run my program. this is the error I am getting:

[ERROR] [WallTime: 1565273888.861720] bad callback: Traceback (most recent call last): File "/opt/ros/indigo/lib/python2.7/dist-packages/rospy/topics.py", line 720, in _invoke_callback cb(msg) File "lazer3.py", line 89, in callback cv_image2 = self.convert_image(cv_image) NameError: global name 'self' is not defined

the error is in the line that says cv_image2 = self.convert_image(cv_image) and it is because I use the self if I delete self I get a different error:

[ERROR] [WallTime: 1565274017.459066] bad callback: Traceback (most recent call last): File "/opt/ros/indigo/lib/python2.7/dist-packages/rospy/topics.py", line 720, in _invoke_callback cb(msg) File "lazer3.py", line 89, in callback cv_image2 = convert_image(cv_image) File "lazer3.py", line 29, in convert_image labels = measure.label(thresh, neighbors=8, background=0) AttributeError: 'module' object has no attribute 'label'

here is my code:

from __future__ import print_function
import cv2
import numpy as np
import imutils
from imutils import contours
from skimage import measure

'''
def getPoint(cameraTip,dotXY,normalPoint):
    slope= (cameraTip[2]-dotXY[2])/(cameraTip[1]-dotXY[1])
    b=cameraTip[2]-(slope*cameraTip[1])
    z=slope*normalPoint[1]+b
    return [normalPoint[0],normalPoint[1],z]
'''
# Image Processing functions
def convert_image(image): # Image of kind bgr8
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (11, 11), 0)
        #threshold the image to reveal light regions in the
        # blurred image
    thresh = cv2.threshold(blurred, 30, 255, cv2.THRESH_BINARY)[1]
        # perform a series of erosions and dilations to remove
        # any small blobs of noise from the thresholded image
    thresh = cv2.erode(thresh, None, iterations=2)
    thresh = cv2.dilate(thresh, None, iterations=4)
        # perform a connected component analysis on the thresholded
        # image, then initialize a mask to store only the "large"
        # components
    labels = measure.label(thresh, neighbors=8, background=0)
    mask = np.zeros(thresh.shape, dtype="uint8")

        # loop over the unique components
    for label in np.unique(labels):
            # if this is the background label, ignore it
        if label == 0:
            continue

            # otherwise, construct the label mask and count the
                # number of pixels
        labelMask = np.zeros(thresh.shape, dtype="uint8")
        labelMask[labels == label] = 255
        numPixels = cv2.countNonZero(labelMask)

                # if the number of pixels in the component is sufficiently
                # large, then add it to our mask of "large blobs"
        if numPixels > 300:
            mask = cv2.add(mask, labelMask)
    # find the contours in the mask, then sort them from left to
    # right
    cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE)
    cnts = imutils.grab_contours(cnts)
    cnts = contours.sort_contours(cnts)[0]

        # loop over the contours
    for (i, c) in enumerate(cnts):
            # draw the bright spot on the image
        (x, y, w, h) = cv2.boundingRect(c)
        ((cX, cY), radius) = cv2.minEnclosingCircle(c)
        #x and y center are cX and cY
        cv2.circle(image, (int(cX), int(cY)), int(radius),
            (0, 0, 255), 3)
        cv2.putText(image, "#{}".format(i + 1), (x, y - 15),
            cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)

        # show the output image
    cv2.imshow("Image", image)
    cv2.waitKey(1)
        #camera.release()
    return image

# ROS Interface
if __name__ == "__main__":
    import rospy
    from cv_bridge import CvBridge, CvBridgeError
    from sensor_msgs.msg import Image
    bridge = CvBridge()
    def show_img(cv_image):
        (rows,cols,channels) = cv_image.shape
        if cols > 60 and rows > 60 :
            cv2.circle(cv_image, (50,50), 10, 255)
        cv2.imshow("Image window", cv_image)
        cv2.waitKey(3)
    image_pub = rospy.Publisher("image_topic_2", Image)
    def callback(data):
        try:
            cv_image = bridge.imgmsg_to_cv2(data, "bgr8")
            show_img(cv_image)
            cv_image2 = self.convert_image(cv_image)
            image_pub.publish(bridge.cv2_to_imgmsg(cv_image2, "bgr8"))
        except CvBridgeError as e:
            print(e)
    image_sub = rospy.Subscriber("CM_040GE/image_raw", Image, callback)
    rospy.init_node('image_converter', anonymous=True)
    rospy.spin()
    print("image_converter: Shutting down")
    cv2.destroyAllWindows()

also I want to make it clear that just because the code is the similar this is not a repeat of my last question because I was getting a different error and I was asking about a completely separate issue

回答1:

It is correct to not have the self in there, as convert_image() is a regular function. The real error is that measure has no label attribute/function. Except, (depending on the version), skimage.measure.label exists as you say.

Based on other SO solutions to this (no attribute in module) problem, try checking that the version of skimage you're using has measure.label, try deleting any .pyc files, and make sure you have no naming conflicts or modules with the same name as what you're trying to import.

Edit: skimage v0.9.x has the label function under the morphology module: skimage.morphology.label. It was moved to measure at a later date.



回答2:

If the function convert_image is a method of a class, then you would normally do

# instantiate the class
my_obj = my_class()

# call the class' method
my_obj.convert_image(paramaters)

so cv_image2 = self.convert_image(cv_image) should be cv_image2 = my_obj.convert_image(cv_image)

If you aren't instantiating a class, and just calling a function, then you can just get rid of the self - cv_image2 = convert_image(cv_image)