Counting the number of iterations through a ROS subscriber node - python

I am trying to write a subscriber that will take images from a camera in a gazebo simulation and save them. I am able to take pictures and save them, however I am trying to increment the image name each time, yet I am finding it difficult to do so. I tried to create a class and then increment a number (image_number) inside the class each time I run the image_callback funcion, however I get an error. I also tried defining a global variable and incrementing that, yet it did not recognize the variable inside the functions. I have attached the code and error below, any help is greatly appreciated!
# rospy for the subscriber
import rospy, time
# ROS Image message
from sensor_msgs.msg import Image
# ROS Image message -> OpenCV2 image converter
from cv_bridge import CvBridge, CvBridgeError
# OpenCV2 for saving an image
import cv2
# Instantiate CvBridge
bridge = CvBridge()
class Image(object):
def __init__(self):
self.image_number = 0
#rospy.init_node('image_listener')
# Define your image topic
image_topic = "/wamv/sensors/cameras/front_left_camera/image_raw"
# Set up your subscriber and define its callback
rospy.Subscriber(image_topic, Image, self.image_callback)
#rospy.spin()
def image_callback(self, msg):
print("Received an image!")
try:
# Convert your ROS Image message to OpenCV2
cv2_img = bridge.imgmsg_to_cv2(msg, "bgr8")
except CvBridgeError as e:
print(e)
else:
# Save your OpenCV2 image as a jpeg
cv2.imwrite('croc_{}'.format(self.image_number)+'.png', cv2_img)
print("Saved Image!")
self.image_number += 1
time.sleep(3.0)
if __name__ == '__main__':
rospy.init_node('image_listener')
image_node = Image()
and the error:
Traceback (most recent call last):
File "/home/jehan/PycharmProjects/spawner/take_photo.py", line 73, in <module>
image_node = Image()
File "/home/jehan/PycharmProjects/spawner/take_photo.py", line 54, in __init__
rospy.Subscriber(image_topic, Image, self.image_callback)
File "/opt/ros/noetic/lib/python3/dist-packages/rospy/topics.py", line 563, in __init__
super(Subscriber, self).__init__(name, data_class, Registration.SUB)
File "/opt/ros/noetic/lib/python3/dist-packages/rospy/topics.py", line 144, in __init__
raise ValueError("data_class [%s] is not a message data class"%data_class.__class__.__name__)
ValueError: data_class [type] is not a message data class

Your problem isn't the counter. It's the fact your class is called Image, just like the message type. This means you will be re-defining over the imported message type. And then when you go to create a subscriber the Image type is actually the class; not a ROS message type. I'd suggest using a different class name as such:
class ImageNode(object):
image_node = ImageNode()

Related

How to fix AttributeError: 'ConfigDict' object has no attribute 'data' on mmdetection?

I am trying to set up mm-detection for custom datasets at the moment and have consistently hit these errors. I have tried getting rid of the def functions in the code, have change file locations and all of the above. I have no idea what is wrong with the code and why it is not working.
from argparse import ArgumentParser
from mmdet.apis import init_detector, inference_detector
import mmcv
from mmdet.apis import (async_inference_detector, inference_detector,
init_detector, show_result_pyplot)
import asyncio
import torch
from mmdet.apis import init_detector, async_inference_detector
from mmdet.utils.contextmanagers import concurrent
def data():
# The new config inherits a base config to highlight the necessary modification
base_ = 'configs/mask_rcnn/mask_rcnn_r50_caffe_fpn_1x_coco.py'
# We also need to change the num_classes in head to match the dataset's annotation
# dict is a python dictionary object which is used to save or load models from PyTorch
model = dict(
roi_head=dict(
# defining the number of classes a bounding box can go around
bbox_head=dict(num_classes=1),
#
mask_head=dict(num_classes=1)))
def dataset():
# Modify dataset related settings
dataset_type = 'COCODataset'
#Defining the classes
classes = ('Pantograph')
data = dict(
train=dict(
img_prefix='testing/',
classes=classes,
ann_file='train/Pan2_COCO.json'),
val=dict(
img_prefix='testing/',
classes=classes,
ann_file='val/Pan2_COCO.json'),
test=dict(
img_prefix='testing/',
classes=classes,
ann_file='val/Pan2_COCO.json'))
def load():
# We can use the pre-trained Mask RCNN model to obtain higher performance
load_from = 'testing/checkpoints/mask_rcnn_r50_caffe_fpn_mstrain-poly_3x_coco_bbox_mAP-0.408__segm_mAP-0.37_20200504_163245-42aa3d00.pth'
data()
dataset()
load()
Error message:
Traceback (most recent call last):
File "tools/train.py", line 244, in <module>
main()
File "tools/train.py", line 135, in main
setup_multi_processes(cfg)
File "/home/dtl-admin/dev/mmdetection/mmdet/utils/setup_env.py", line 30, in setup_multi_processes
workers_per_gpu = cfg.data.get('workers_per_gpu', 1)
File "/home/dtl-admin/miniconda3/envs/mmtest/lib/python3.8/site-packages/mmcv/utils/config.py", line 519, in __getattr__
return getattr(self._cfg_dict, name)
File "/home/dtl-admin/miniconda3/envs/mmtest/lib/python3.8/site-packages/mmcv/utils/config.py", line 50, in __getattr__
raise ex
AttributeError: 'ConfigDict' object has no attribute 'data'
I was expecting an output where the image detects the class pantograph. However, I cannot get any output no matter what I try and I have tried changing as many variables as possible.
If this is your config file it definitely shouldn't include definitions, mmDetection has a great example of a mask rcnn config file here: https://mmdetection.readthedocs.io/en/v2.28.1/tutorials/config.html
You can pretty much copy it and change the ann_file attributes to point to your data.
You can then load this config file into your test file and train your model. This notebook I've been using:
https://notebook.community/open-mmlab/mmdetection/demo/MMDet_Tutorial
has a good step by step tutorial (though its a little out of date) for how to go about it. You can cross reference with the first link to make sure you have the right updates.

Azure Detect With Stream Invalid Request

it's my first time with Azure Face Detection API and I'm using this code right here:
import os
import io
import cv2
from azure.cognitiveservices.vision.face import FaceClient
from msrest.authentication import CognitiveServicesCredentials
from PIL import Image, ImageDraw, ImageFont
API_KEY = '...'
ENDPOINT = '...'
image = open('realmadrid.jpg', 'rb')
face_client = FaceClient(ENDPOINT, CognitiveServicesCredentials(API_KEY))
response_detected_faces = face_client.face.detect_with_stream(
image=image,
detection_model='detection_03',
recognition_model='recognition_04',
return_face_landmarks=True,
)
if not response_detected_faces:
raise Exception("No face detected!")
print(f"Number of face detected {len(response_detected_faces)}")
The problem is that everytime I run this code it gives me an exception:
/home/thecowmilk/dev/azure_faceapi/venv/bin/python /home/thecowmilk/dev/azure_faceapi/faceapi/starting.py
Traceback (most recent call last):
File "/home/thecowmilk/dev/azure_faceapi/faceapi/starting.py", line 20, in <module>
detected_faces = face_client.face.detect_with_stream(
File "/home/thecowmilk/dev/azure_faceapi/venv/lib/python3.8/site-packages/azure/cognitiveservices/vision/face/operations/_face_operations.py", line 782, in detect_with_stream
raise models.APIErrorException(self._deserialize, response)
azure.cognitiveservices.vision.face.models._models_py3.APIErrorException: (InvalidRequest) Invalid request has been sent.
Process finished with exit code 1
I don't know how to solve this. It looks there's not much info about Azure Face Detection API. I'd appreciate your thoughts <3!
According to Get face landmarks, to get face landmark data, set the detectionModel parameter to DetectionModel.Detection01 and the returnFaceLandmarks parameter to true.
IList<DetectedFace> faces2 = await faceClient.Face.DetectWithUrlAsync(url: imageUrl, returnFaceId: true, returnFaceLandmarks: true, detectionModel: DetectionModel.Detection01);
Instead of detection_03 use detection_01:
response_detected_faces = face_client.face.detect_with_stream(
image=image,
detection_model='detection_01',
recognition_model='recognition_04',
return_face_landmarks=True,
)
You can refer to recent changes/limitations about some features of Face API: Responsible AI investments and safeguards for facial recognition

Approach to get currently playing media's thumbnail on Windows only works once per Python instance

I'm trying to get the thumbnail of the currently playing media on windows, and thanks to this answer (https://stackoverflow.com/a/66037406/15491505) i got quite far, however I'm facing a strange issue where in get_thumbnail() the variable byte_buffer always ends up being 0 in length after the first run... as in the first time I call it I get back the thumbnail perfectly, but all further calls end up failing...
This is what I have so far:
from winrt.windows.media.control import GlobalSystemMediaTransportControlsSessionManager as MediaManager
from winrt.windows.storage.streams import DataReader, Buffer, InputStreamOptions
from io import BytesIO
from PIL import Image
import asyncio
async def get_thumbnail():
sessions = await MediaManager.request_async()
current_session = sessions.get_current_session()
if current_session:
properties = await current_session.try_get_media_properties_async()
media_info = {song_attr: properties.__getattribute__(song_attr) for song_attr in dir(properties) if song_attr[0] != '_'}
if media_info.get('thumbnail'):
thumb_stream_ref = media_info['thumbnail']
thumb_read_buffer = Buffer(5000000)
readable_stream = await thumb_stream_ref.open_read_async()
readable_stream.read_async(thumb_read_buffer, thumb_read_buffer.capacity, InputStreamOptions.READ_AHEAD)
buffer_reader = DataReader.from_buffer(thumb_read_buffer)
byte_buffer = buffer_reader.read_bytes(thumb_read_buffer.length)
binary = BytesIO()
binary.write(bytearray(byte_buffer))
binary.seek(0)
print(len(bytearray(byte_buffer)))
img = Image.open(binary)
return img
thumbnail = asyncio.run(get_thumbnail())
thumbnail.show()
# This will work
thumbnail2 = asyncio.run(get_thumbnail())
thumbnail2.show()
# This will not
Example output:
C:\Users\willy\Desktop>test.py
117672
0
Traceback (most recent call last):
File "C:\Users\willy\Desktop\test.py", line 39, in <module>
thumbnail2 = asyncio.run(get_thumbnail())
File "C:\Python38\lib\asyncio\runners.py", line 44, in run
return loop.run_until_complete(main)
File "C:\Python38\lib\asyncio\base_events.py", line 616, in run_until_complete
return future.result()
File "C:\Users\willy\Desktop\test.py", line 31, in get_thumbnail
img = Image.open(binary)
File "C:\Python38\lib\site-packages\PIL\Image.py", line 2930, in open
raise UnidentifiedImageError(
PIL.UnidentifiedImageError: cannot identify image file <_io.BytesIO object at 0x00000278D2FB3B30>
Solution
Simply await the result of the readable_stream.read_async(...) call:
...
readable_stream = await thumb_stream_ref.open_read_async()
await readable_stream.read_async(thumb_read_buffer, thumb_read_buffer.capacity, InputStreamOptions.READ_AHEAD)
buffer_reader = DataReader.from_buffer(thumb_read_buffer)
...
The thumbnail should now be successfully displayed each time.
Debugging process
(for anyone interested and for similar bugs in the future)
After break-pointing your code, it appeared that, on the second call of get_thumbnail(), byte_buffer was left empty. This indicated that the thumb_read_buffer was not being populated correctly from the stream.
Interestingly, when single-stepping the code instead, the image displayed both times. This suggested to me that maybe an asynchronous function call wasn't being awaited.
Turns out .read_async() (as the function name suggests) is an asynchronous operation in winrt (see IInputStream.ReadAsync on learn.microsoft.com). Hence, awaiting its execution fixed the problem of the empty thumb_read_buffer.

Getting NameError: name 'video' is not defined in Vapoursynth/Python

Trying to make a gif in vapoursynth, followed tutorials yet keep getting name error. If anyone could help explain what's wrong with it and how to fix it, I would appreciate it.
Failed to initialize script.
Failed to evaluate the script:
Python exception: name 'video' is not defined
Traceback (most recent call last):
File "src\cython\vapoursynth.pyx", line 1927, in
vapoursynth.vpy_evaluateScript
File "src\cython\vapoursynth.pyx", line 1928, in
vapoursynth.vpy_evaluateScript
File "C:/Users/caitl/Pictures/bbh.vpy", line 12, in
core.max_cache_size = 1000 #Use this command to limit the RAM usage. 1000 or 2000 is fine.
NameError: name 'video' is not defined
Code
import os
import vapoursynth as vs
import havsfunc as haf
import mvsfunc as mvs
import descale as descale
import muvsfunc as muvs
import resamplehq as rhq
import CSMOD as cs
import Dither as dither
core = vs.get_core()
video = core.std.Trim(video, a, b)
video = haf.QTGMC(video, Preset="Slower", TFF=True)
video = core.fmtc.resample(video, css="444")
video = descale.Debilinear(video, 629,354)
video = mvs.BM3D(video, sigma=8.84, radius1=1, profile1="fast", matrix="709")
video = hnw.FineSharp(video, sstr=1.13)
video = core.std.CropRel(video, left=72, top=52, right=107, bottom=52)
video = core.fmtc.bitdepth(video, bits=8)
video.set_output()
You didn't define video before the call to Trim which takes it as a parameter.
The example script in the documentation says you need to create a video object, for example, by loading a file:
from vapoursynth import core
video = core.ffms2.Source(source='Rule6.mkv')
This loads a video file Rule6.mkv using the ffms2 plugin, which it assumes is installed correctly.

how to display HSV image - tkinter, python 2.7

I'm converting an RGB image to HSV, and trying to display the same in a Label. But I'm getting error.
My code snippet is:
def hsv_img():
img1=cv2.medianBlur(img,3)
imghsv = cv2.cvtColor(img1,cv2.COLOR_BGR2HSV)
lw_range=np.array([160,170,50])
up_range=np.array([179,250,220])
imgthresh1=cv2.inRange(imghsv,lw_range,up_range)
imgthresh=Image.open(imgthresh)
re_hsv=imhsv.resize((360,360),Image.ANTIALIAS)
imhsv1=ImageTk.PhotoImage(re_hsv)
lb_hsv = Label(windo, image = imhsv1,relief=SOLID)
lb_hsv.image=imhsv1
lb_hsv.pack()
lb_hsv.place(x=230,y=180)
And my error is:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Balu\AppData\Local\Enthought\Canopy32\App\appdata\canopy-1.0.3.1262.win-x86\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
File "E:\python\track\guinew.py", line 215, in hsv_img
imhsv=Image.open(imgthresh)
File "C:\Users\Balu\AppData\Local\Enthought\Canopy32\System\lib\site-packages\PIL\Image.py", line 1956, in open
prefix = fp.read(16)
AttributeError: 'numpy.ndarray' object has no attribute 'read'
So how to display the HSV image, is there any other way then what i have tried? Any suggestions are welcome!
Thanks in advance!
The error is thrown when you call Image.open(imgthresh), because Image.open expects a file-like object, but imgthresh is a Numpy array.
Try removing that line altogether.
EDIT: Here's a complete version that works (on my machine):
from PIL import Image, ImageTk
from Tkinter import Tk, Label, SOLID
import cv2
import numpy as np
img = np.array(Image.open('some-file.png'))
window = Tk()
def hsv_img():
img1=cv2.medianBlur(img,3)
imghsv = cv2.cvtColor(img1,cv2.COLOR_BGR2HSV)
lw_range=np.array([160,170,50])
up_range=np.array([179,250,220])
imgthresh1=cv2.inRange(imghsv,lw_range,up_range)
re_hsv=Image.fromarray(imghsv).resize((360,360),Image.ANTIALIAS)
imhsv1=ImageTk.PhotoImage(re_hsv)
lb_hsv = Label(window, image = imhsv1,relief=SOLID)
lb_hsv.image=imhsv1
lb_hsv.pack()
lb_hsv.place(x=230,y=180)
hsv_img()
window.mainloop()
I had to rename some things, as well as add a call to Image.fromarray when you resize to 360x360.
It seems like most of the confusion stems from different numpy/PIL/OpenCV/Tkinter image formats. You might find this conversion guide useful, though it's slightly out of date.

Categories