Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Road signs classifier #436

Merged
merged 32 commits into from
Nov 13, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
a52db40
Add new message files
pranavboyapati Nov 5, 2024
65ba763
Updated API url
pranavboyapati Nov 6, 2024
34a62df
Debug camera info
pranavboyapati Nov 7, 2024
195edff
camera change
pranavboyapati Nov 7, 2024
7e616a6
debug issues in main()
pranavboyapati Nov 7, 2024
13c4f34
Create Message Files
pranavboyapati Nov 8, 2024
6b41055
Updated messages
pranavboyapati Nov 8, 2024
a1df417
Updated message files
pranavboyapati Nov 8, 2024
35ee33c
Modified RoadSignsDetection.msg
pranavboyapati Nov 8, 2024
e369535
Fixed image subscription
pranavboyapati Nov 8, 2024
a36ec6f
Update image path
pranavboyapati Nov 8, 2024
beb8953
Debugging part 1
pranavboyapati Nov 8, 2024
dda66cc
Debugged errors with classification API call
pranavboyapati Nov 8, 2024
9bd1540
Debugged message publishing
pranavboyapati Nov 8, 2024
f0174c4
updated launch files
pranavboyapati Nov 12, 2024
d98e943
updated dockerfile with a pip install
pranavboyapati Nov 12, 2024
91d4a99
updated dockerfile for pip install
pranavboyapati Nov 12, 2024
e74f032
debug dockerfile
pranavboyapati Nov 12, 2024
c882a48
updated dockerfile
pranavboyapati Nov 12, 2024
dab37b1
debugged dockerfile
pranavboyapati Nov 12, 2024
2147984
Update Dockerfile to keep all pip installs together
pranavboyapati Nov 12, 2024
4b1f00c
debug dockerfile
pranavboyapati Nov 12, 2024
f18ab36
Merge branch 'dev' into perception/road_signs_classifier
pranavboyapati Nov 12, 2024
46b990e
debugged launch
pranavboyapati Nov 12, 2024
8350720
specified version for inference sdk
pranavboyapati Nov 12, 2024
9eb7432
removed unused tests
pranavboyapati Nov 12, 2024
7f41ab3
remove debug print
pranavboyapati Nov 12, 2024
4b13473
specify use of inference sdk
pranavboyapati Nov 12, 2024
7127922
removed unnecessary image file
pranavboyapati Nov 12, 2024
5da637d
update class name to PascalCase
pranavboyapati Nov 12, 2024
1aa9c48
added documentation
pranavboyapati Nov 12, 2024
cd56aba
updated to no longer use disk IO for input images
pranavboyapati Nov 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ RUN pip3 install \
#
autopep8 \
#
inference-sdk \
pranavboyapati marked this conversation as resolved.
Show resolved Hide resolved
#
cmake_format==0.6.11 \
#
dictor \
Expand Down Expand Up @@ -239,8 +241,11 @@ RUN mkdir /lib/x86_64-linux-gnu/cmake/pcl/include && ln -s /usr/include/pcl-1.10

# Lemon
# Library for Efficient Modeling and Optimization in Networks. It is a C++ template library providing efficient implementations of common data structures and algorithms with focus on combinatorial optimization tasks connected mainly with graphs and networks.
RUN wget http://lemon.cs.elte.hu/pub/sources/lemon-1.3.1.tar.gz && tar xvzf lemon-1.3.1.tar.gz && cd lemon-1.3.1 && mkdir build && cd build && cmake .. && make && make install

RUN git clone https://github.com/The-OpenROAD-Project/lemon-graph.git && cd lemon-graph \
# This specific commit is for Lemon-1.3.1. See https://github.com/The-OpenROAD-Project/lemon-graph/commits/master.
&& git checkout 62ac753 \
&& mkdir build && cd build && cmake .. && make && make install

# RUN useradd -ms /bin/bash docker
RUN usermod -a -G dialout root
RUN usermod -a -G tty root
Expand All @@ -251,4 +256,4 @@ ENV ROS_VERSION 2
WORKDIR /navigator
COPY ./docker/entrypoint.sh /opt/entrypoint.sh

ENTRYPOINT [ "/opt/entrypoint.sh" ]
ENTRYPOINT [ "/opt/entrypoint.sh" ]
Binary file added image.jpeg
pranavboyapati marked this conversation as resolved.
Show resolved Hide resolved
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions launches/launch.perception.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,11 @@ def generate_launch_description():
return LaunchDescription([
# image_segmentation,
# semantic_projection,
ground_seg,
static_grid,
# ground_seg,
# static_grid,
# *object3d_launch_entities,
# traffic_light_detector,
# prednet_inference,
# driveable_area,
road_signs_classifier,
])
7 changes: 7 additions & 0 deletions launches/launch_node_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,3 +190,10 @@
package='traffic_light_detector',
executable='traffic_light_node'
)

road_signs_classifier = Node(
package='road_signs_classifier',
executable='road_signs_classifier',
name='road_signs_classifier',
parameters=[],
)
7 changes: 7 additions & 0 deletions src/msg/navigator_msgs/msg/RoadSigns.msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# MSG for one specific road sign
float32 x # X-coordinate of the road sign bounding box
float32 y # Y-coordinate of the road sign bounding box
float32 width # Width of the road sign bounding box
float32 height # Height of the road sign bounding box
string label # Label indicating the type of road sign
float32 confidence # Confidence score of the road sign detection
2 changes: 2 additions & 0 deletions src/msg/navigator_msgs/msg/RoadSignsDetection.msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
std_msgs/Header header
RoadSigns[] road_signs # Array of road sign detections
26 changes: 26 additions & 0 deletions src/perception/road_signs_classifier/package.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>road_signs_classifier</name>
<version>1.0.0</version>
<description>Tools to perform road sign classifications</description>
<maintainer email="[email protected]">root</maintainer>
<license>MIT License</license>

<test_depend>ament_copyright</test_depend>
<test_depend>ament_flake8</test_depend>
<test_depend>ament_pep257</test_depend>
<test_depend>python3-pytest</test_depend>

<depend>rclpy</depend>
<depend>rclpy.node</depend>
<depend>sensor_msgs.msg</depend>
<depend>cv_bridge</depend>
<depend>navigator_msgs</depend>
<depend>cv2</depend>
<depend>inference_sdk</depend>

<export>
<build_type>ament_python</build_type>
</export>
</package>
Empty file.
Empty file.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"""
Package: road_signs_classifier
File: road_signs_classifier.py
Author: Pranav Boyapati
"""

import rclpy
import base64
import os
from rclpy.node import Node
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
from navigator_msgs.msg import RoadSigns
from navigator_msgs.msg import RoadSignsDetection
import cv2
from inference_sdk import InferenceHTTPClient


class road_signs_classifier(Node):
pranavboyapati marked this conversation as resolved.
Show resolved Hide resolved
def __init__(self):
super().__init__('road_signs_classifier')

#instantiate model client
self.CLIENT = InferenceHTTPClient(api_url="http://localhost:6060", api_key="BmqYjCBXZD1iPIyq09sG")
pranavboyapati marked this conversation as resolved.
Show resolved Hide resolved

#create subscriptions
self.camera_sub = self.create_subscription(Image, '/cameras/camera0', self.image_callback, 10)

#create variables to store subscription info
self.bridge = CvBridge()

#create publisher
self.road_signs_publisher = self.create_publisher(RoadSignsDetection, '/road_signs/detections', 10)


#callbacks for subscriptions
def image_callback(self, msg : Image):
cv_image = self.bridge.imgmsg_to_cv2(msg, desired_encoding="passthrough")
cv2.imwrite("image.jpeg", cv_image)
self.classify_sign()


#main control function
def classify_sign(self):
#gets prediction
if (os.path.exists("image.jpeg")):
with open("image.jpeg", "rb") as img_file:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason why we write the image to disk and read it back instead of just passing it as a parameter?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was causing all sorts of errors when I tried to pass the image as a parameter, but those all disappeared when writing to disk and reading it back, so figured that was the best way to go about doing this

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tried something like:

_, jpeg_image = cv2.imencode('.jpg', cv_image)
base64.b64encode(jpeg_image).decode('utf-8')

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tried that and it works. Previously when I tried cv2.imencode, I did not do b64encode because the articles I had read said it is unnecessary in that case, but putting it in now made it work. I guess those articles were wrong

img_base64 = base64.b64encode(img_file.read()).decode('utf-8')
result = self.CLIENT.infer(img_base64, model_id="us-road-signs/71")
print(result)
pranavboyapati marked this conversation as resolved.
Show resolved Hide resolved

#create message and publish
if (len(result["predictions"]) > 0):

road_signs_detection_msg = RoadSignsDetection()
road_signs_detection_msg.header.stamp = self.get_clock().now().to_msg()
road_signs_detection_msg.header.frame_id = "camera_frame"

road_sign = RoadSigns()
road_sign.x = result["predictions"][0]['x']
road_sign.y = result["predictions"][0]['y']
road_sign.width = result["predictions"][0]['width']
road_sign.height = result["predictions"][0]['height']
road_sign.label = result["predictions"][0]['class']
road_sign.confidence = result["predictions"][0]['confidence']

road_signs_detection_msg.road_signs.append(road_sign)
pranavboyapati marked this conversation as resolved.
Show resolved Hide resolved

self.road_signs_publisher.publish(road_signs_detection_msg)


if __name__ == '__main__':
rclpy.init(args=None)
road_signs_classification = road_signs_classifier()
rclpy.spin(road_signs_classification)
rclpy.shutdown()
pranavboyapati marked this conversation as resolved.
Show resolved Hide resolved
4 changes: 4 additions & 0 deletions src/perception/road_signs_classifier/setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[develop]
script_dir=$base/lib/road_signs_classifier
[install]
install_scripts=$base/lib/road_signs_classifier
26 changes: 26 additions & 0 deletions src/perception/road_signs_classifier/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from setuptools import find_packages, setup

package_name = 'road_signs_classifier'

setup(
name=package_name,
version='1.0.0',
packages=find_packages(exclude=['test']),
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='root',
maintainer_email='[email protected]',
description='Tools to perform road sign classifications',
license='MIT License',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'road_signs_classifier = road_signs_classifier.road_signs_classifier:main'
],
},
)
25 changes: 25 additions & 0 deletions src/perception/road_signs_classifier/test/test_copyright.py
pranavboyapati marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2015 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from ament_copyright.main import main
import pytest


# Remove the `skip` decorator once the source file(s) have a copyright header
@pytest.mark.skip(reason='No copyright header has been placed in the generated source file.')
@pytest.mark.copyright
@pytest.mark.linter
def test_copyright():
rc = main(argv=['.', 'test'])
assert rc == 0, 'Found errors'
25 changes: 25 additions & 0 deletions src/perception/road_signs_classifier/test/test_flake8.py
pranavboyapati marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2017 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from ament_flake8.main import main_with_errors
import pytest


@pytest.mark.flake8
@pytest.mark.linter
def test_flake8():
rc, errors = main_with_errors(argv=[])
assert rc == 0, \
'Found %d code style errors / warnings:\n' % len(errors) + \
'\n'.join(errors)
23 changes: 23 additions & 0 deletions src/perception/road_signs_classifier/test/test_pep257.py
pranavboyapati marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright 2015 Open Source Robotics Foundation, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from ament_pep257.main import main
import pytest


@pytest.mark.linter
@pytest.mark.pep257
def test_pep257():
rc = main(argv=['.', 'test'])
assert rc == 0, 'Found code style errors / warnings'
Loading