Reputation: 309
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
Upvotes: 0
Views: 210
Reputation: 1211
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.
Upvotes: 1
Reputation: 1673
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)
Upvotes: 1