Skip to content

Commit

Permalink
feat(53): Panoptic Segmentation
Browse files Browse the repository at this point in the history
  • Loading branch information
okrusch committed Nov 17, 2023
1 parent fbcae9e commit 8844b07
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 24 deletions.
4 changes: 2 additions & 2 deletions code/agent/launch/agent.launch
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@
</include>

<!-- planning -->

<include file="$(find planning_runner)/launch/planning_runner.launch">
</include>

<include file="$(find mock)/launch/mock.launch">
<arg name="control_loop_rate" value="$(arg control_loop_rate)"/>
<arg name="role_name" value="$(arg role_name)"/>
</include>

<!-- acting -->
<include file="$(find acting)/launch/acting.launch">
<arg name="control_loop_rate" value="$(arg control_loop_rate)"/>
<arg name="role_name" value="$(arg role_name)"/>
</include>


<node type="rviz" name="rviz" pkg="rviz" args="-d $(find agent)/config/rviz_config.rviz" />
<node type="rviz" name="rviz" pkg="rviz" args="-d $(find agent)/config/rviz_config.rviz" />
</launch>
15 changes: 12 additions & 3 deletions code/perception/launch/perception.launch
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,26 @@
<launch>
<arg name="role_name" default="hero" />
<arg name="control_loop_rate" default="0.1" />

<!--
<node pkg="perception" type="Position_Publisher_Node.py" name="Position_Publisher_Node" output="screen">
<param name="control_loop_rate" value="0.1" />
<param name="role_name" value="$(arg role_name)" />
</node>
<node pkg="perception" type="segmentation_node.py" name="SegmentationNode" output="screen">
<param name="role_name" value="$(arg role_name)" />
<param name="side" value="Center" />
</node>-->

<node pkg="perception" type="p_testing_node.py" name="PerceptionTestingNode" output="screen">
<param name="role_name" value="$(arg role_name)" />
<param name="side" value="Center" />
</node>


<node pkg="perception" type="global_plan_distance_publisher.py" name="GlobalPlanDistance" output="screen">
<!-- <node pkg="perception" type="global_plan_distance_publisher.py" name="GlobalPlanDistance" output="screen">
<param name="control_loop_rate" value="0.1" />
<param name="role_name" value="$(arg role_name)" />
</node>
Expand Down Expand Up @@ -46,5 +54,6 @@
<param name="max_z" value="0"/>
<param name="point_cloud_topic" value="/carla/hero/LIDAR_filtered_rear_left"/>
<param name="range_topic" value="/carla/hero/LIDAR_range_rear_left"/>
</node>
</node>-->

</launch>
102 changes: 102 additions & 0 deletions code/perception/src/p_testing_node.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/usr/bin/env python3

from ros_compatibility.node import CompatibleNode
import ros_compatibility as roscomp
import torch
from torchvision.models.segmentation import deeplabv3_resnet101
from torchvision.models.segmentation import DeepLabV3_ResNet101_Weights
import torchvision.transforms as t
import cv2
from rospy.numpy_msg import numpy_msg
from sensor_msgs.msg import Image
from cv_bridge import CvBridge


class PerceptionTestingNode(CompatibleNode):
def __init__(self, name, **kwargs):
# starting comment

super().__init__(name, **kwargs)
# self.model = torch.hub.load('pytorch/vision:v0.10.0',
# 'deeplabv3_resnet50', pretrained=True)

self.model = deeplabv3_resnet101(DeepLabV3_ResNet101_Weights)
# self.model.eval()
# print("Model Test: ", self.model(torch.zeros((1,3,720,1280))))

self.bridge = CvBridge()

self.role_name = self.get_param("role_name", "hero")
self.side = self.get_param("side", "Center")
self.setup_camera_subscriptions()
self.setup_camera_publishers()

def setup_camera_subscriptions(self):
self.new_subscription(
msg_type=numpy_msg(Image),
callback=self.handle_camera_image,
topic=f"/carla/{self.role_name}/{self.side}/image",
qos_profile=1
)

def setup_camera_publishers(self):
self.publisher = self.new_publisher(
msg_type=numpy_msg(Image),
topic=f"/paf/{self.role_name}/{self.side}/segmented_image",
qos_profile=1
)

def handle_camera_image(self, image):
self.model.eval()
self.loginfo(f"got image from camera {self.side}")

cv_image = self.bridge.imgmsg_to_cv2(img_msg=image,
desired_encoding='passthrough')
cv_image = cv2.cvtColor(cv_image, cv2.COLOR_RGB2BGR)
"""
image_array = np.frombuffer(image.data, dtype=np.uint8)
print(image_array.shape)
image_array = image_array.reshape((image.height, image.width, -1))
print(image_array.shape)
# remove alpha channel
image_array = image_array[:, :, :3]
print(image_array.shape)"""

preprocess = t.Compose([
t.ToTensor(),
t.Normalize(mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
input_image = preprocess(cv_image).unsqueeze(dim=0)
prediction = self.model(input_image)['out'][0]
# prediction = id2rgb(prediction)
# print(prediction)
print(prediction.shape)

masked_image = self.create_mask(prediction, input_image)
self.publisher.publish(self.bridge.cv2_to_imgmsg(masked_image))

pass

def create_mask(self, model_output, input_image):
palette = torch.tensor([2 ** 25 - 1, 2 ** 15 - 1, 2 ** 21 - 1])
colors = torch.as_tensor([i for i in range(21)])[:, None] * palette
colors = (colors % 255).numpy().astype("uint8")
r = Image.fromarray(model_output.byte().cpu().numpy())
r = r.resize(input_image.shape[2], input_image.shape[3])
r.putpalette(colors)
return r

def run(self):
self.spin()
pass
# while True:
# self.spin()


if __name__ == "__main__":
roscomp.init("PerceptionTestingNode")
# try:

node = PerceptionTestingNode("PerceptionTestingNode")
node.run()
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import torch
from torch.optim.lr_scheduler import ReduceLROnPlateau
from .fpn.two_way_fpn import TwoWayFpn
import pytorch_lightning as pl
import lightning as pl
from .backbone.modify_efficientnet import \
generate_backbone_EfficientPS, \
output_feature_size
Expand Down
48 changes: 30 additions & 18 deletions code/perception/src/segmentation_node.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python3

"""
import pathlib
import numpy as np
import ros_compatibility as roscomp
Expand All @@ -13,25 +13,25 @@
from panoptic_segmentation.efficientps import EfficientPS as EfficientPS
from panoptic_segmentation.train_net import add_custom_param
from panoptic_segmentation.efficientps.panoptic_segmentation_module import \
panoptic_segmentation_module
from panoptic_segmentation.efficientps.panoptic_segmentation_module
import panoptic_segmentation_module
from detectron2.config import get_cfg
import torchvision.transforms.functional as F
from detectron2.structures import Instances, BitMasks, Boxes
CFG_FILE_PATH = pathlib.Path(
__file__).parent / "panoptic_segmentation" / "config.yaml"
MODEL_PATH = pathlib.Path(
__file__).parent.parent / \
"models/panoptic_segmentation/efficientps.ckpt"
CFG_FILE_PATH = pathlib.Path(__file__).parent /
"panoptic_segmentation" / "config.yaml"
MODEL_PATH = pathlib.Path(__file__).parent.parent /
"src/panoptic_segmentation/efficientps/model.pth"
class SegmentationNode(CompatibleNode):
"""
This node runs the panoptic segmentation model on
the camera images and publishes the segmented results.
"""
def __init__(self, name, **kwargs):
super().__init__(name, **kwargs)
Expand All @@ -44,12 +44,13 @@ def __init__(self, name, **kwargs):
self.model, self.transform, self.model_cfg = self.load_model()
# warm up
self.predict(np.zeros((720, 1280, 3)))
#self.predict(np.zeros((720, 1280, 3)))
self.setup_camera_subscriptions()
self.setup_camera_publishers()
#self.setup_camera_subscriptions()
#self.setup_camera_publishers()
def setup_camera_subscriptions(self):
self.new_subscription(
msg_type=numpy_msg(Image),
callback=self.handle_camera_image,
Expand All @@ -58,6 +59,7 @@ def setup_camera_subscriptions(self):
)
def setup_camera_publishers(self):
self.publisher = self.new_publisher(
msg_type=numpy_msg(Image),
topic=f"/paf/{self.role_name}/{self.side}/segmented_image",
Expand All @@ -66,6 +68,7 @@ def setup_camera_publishers(self):
@staticmethod
def load_model():
cfg = get_cfg()
cfg['train'] = False
add_custom_param(cfg)
Expand All @@ -76,18 +79,21 @@ def load_model():
A.Normalize(mean=cfg.TRANSFORM.NORMALIZE.MEAN,
std=cfg.TRANSFORM.NORMALIZE.STD),
])

model = EfficientPS.load_from_checkpoint(
"model = EfficientPS.load_from_checkpoint(
cfg=cfg,
checkpoint_path=str(MODEL_PATH)
)
model = EfficientPS(cfg)
model.load_state_dict(torch.load(MODEL_PATH))
print(model)
model.eval()
model.freeze()
model.to(torch.device("cuda:0"))
model.to(torch.device("cuda:0")) #add device definition before
return model, transform, cfg
return model, transform, None
def predict(self, image: np.ndarray):
self.loginfo(f"predicting image shape: {image.shape}")
# expand
# image = np.expand_dims(image, axis=0)
Expand All @@ -113,7 +119,9 @@ def predict(self, image: np.ndarray):
result = segmented_result.cpu().numpy()
# self.loginfo(f"predictions: {prediction.shape}")
return result
return resultskip python linting
code/perception/src/p_testing_node.py:17:27: W291 trailing w
self.loginfo("predicting something")
def handle_camera_image(self, image):
self.loginfo(f"got image from camera {self.side}")
Expand Down Expand Up @@ -149,6 +157,8 @@ def handle_camera_image(self, image):
self.publisher.publish(msg)
self.loginfo(f"prediction shape: {prediction.shape}")
self.loginfo("reveived image from camera")
pass
def run(self):
self.spin()
Expand All @@ -168,3 +178,5 @@ def run(self):
# finally:
# roscomp.shutdown()
#
"""

0 comments on commit 8844b07

Please sign in to comment.