不要色彩变换,用这种形式判断 if boundingBox.Class == 'blue': color=[0,0,255] cv2.rectangle(img, (int(box[0]), int(box[1])), (int(box[2]), int(box[3])), (int(color[0]),int(color[1]), int(color[2])), 7) cv2.putText(img, box[-1], (int(box[0]), int(text_pos_y)-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,0,255), 2, cv2.LINE_AA)
时间: 2025-07-21 08:51:51 浏览: 3
<think>我们要求不要使用之前的色彩变换方式,而是按照用户提供的示例代码形式进行修改。
用户提供的示例代码形式是:
if boundingBox.Class == 'blue':
color=[0,0,255]
cv2.rectangle(...) 用这个color
cv2.putText(...) 也用这个color
因此,我们需要在绘制边界框和标签时,根据检测到的类别名称(字符串)来设置颜色。
注意:原代码中,我们是在循环处理每个检测框时,根据类别名称设置颜色,然后绘制。
修改思路:
1. 不再使用results[0].plot()来绘制图像,因为这样会使用默认的绘制方式。
2. 我们将自己绘制每个边界框和标签,根据类别名称选择颜色。
步骤:
- 首先,我们将self.frame设置为原始图像的副本(注意:原始图像是RGB格式,而OpenCV绘制使用BGR,但这里我们后面发布前会转换)
- 然后,对于每个检测结果,提取边界框坐标、类别名称和置信度。
- 根据类别名称设置颜色(注意:用户要求用字符串比较,如'blue',注意大小写问题,我们统一转换为小写或使用用户模型输出的实际字符串)
- 绘制矩形和文本。
另外,用户要求的话题不变,还是发布到/yolov8/detection_image。
我们将修改dectshow函数,按照以下步骤:
a. 创建原始图像的副本(self.color_image是RGB格式)
b. 在副本上绘制边界框和文本(使用BGR颜色,因为后面我们要转换为BGR发布)
c. 计算FPS并绘制在图像上
d. 发布图像
注意:由于原始图像是RGB,而绘制时我们使用的是BGR颜色,所以绘制时颜色值需要按照BGR顺序(如红色为[0,0,255])。
但是,我们绘制的图像仍然是RGB格式吗?不是,因为我们在RGB图像上用BGR颜色绘制,颜色会错乱。所以我们需要转换思路:
实际上,我们可以在RGB图像上绘制,但颜色值需要按照RGB顺序。然而,OpenCV的绘制函数要求图像是BGR格式?不对,实际上OpenCV的绘制函数是在BGR图像上工作的。
因此,我们需要:
- 将原始图像(RGB)转换为BGR,然后在BGR图像上绘制(这样颜色定义就正确了)
- 或者,我们保持为RGB,但绘制时使用RGB顺序的颜色(例如红色为(255,0,0)),但这样不符合我们的习惯。
为了简单,我们先将原始图像转换为BGR,然后在BGR图像上绘制,这样颜色定义就是我们熟悉的BGR顺序。
但是注意:原始图像self.color_image是RGB格式,我们通过:
self.color_image = cv2.cvtColor(self.color_image, cv2.COLOR_BGR2RGB) # 注意:这个转换实际上是从BGR2RGB?不对,原消息是BGR格式吗?
回顾image_callback函数:
self.color_image = np.frombuffer(image.data, dtype=np.uint8).reshape(image.height, image.width, -1)
self.color_image = cv2.cvtColor(self.color_image, cv2.COLOR_BGR2RGB) # 这里将BGR转换为RGB
所以,self.color_image现在是RGB格式。
我们想要在BGR图像上绘制,所以我们可以:
img_draw = cv2.cvtColor(self.color_image, cv2.COLOR_RGB2BGR)
然后在这个img_draw上绘制边界框(使用BGR颜色定义),这样颜色就是正确的。
或者,我们也可以直接在RGB图像上绘制,但颜色值要使用RGB顺序(比如红色为(255,0,0)),但这样容易混淆。
我选择第一种:先转换为BGR,然后绘制,这样我们就可以使用常规的BGR颜色值。
修改后的dectshow函数:
步骤:
1. 将原始图像(RGB)转换为BGR格式,得到img_draw
2. 在img_draw上绘制边界框和文本(使用BGR颜色)
3. 在img_draw上绘制FPS(绿色)
4. 将img_draw赋值给self.frame(如果需要显示的话)
5. 发布这个img_draw(注意:发布时已经是BGR格式,所以编码为'bgr8')
但是注意:我们之前发布图像时使用的是转换后的图像,现在我们在绘制前已经转换了,所以发布时直接使用img_draw即可。
具体代码修改如下:</think>根据您的要求,我将修改代码,使用直接判断类别名称的方式为边界框着色,而不使用色彩变换。以下是修改后的代码:
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import cv2
import torch
import rospy
import numpy as np
from ultralytics import YOLO
from time import time
from std_msgs.msg import Header
from sensor_msgs.msg import Image
from yolov8_ros_msgs.msg import BoundingBox, BoundingBoxes
class Yolo_Dect:
def __init__(self):
# 加载参数
weight_path = rospy.get_param('~weight_path', '')
image_topic = rospy.get_param('~image_topic', '/camera/color/image_raw')
pub_topic = rospy.get_param('~pub_topic', '/yolov8/BoundingBoxes')
self.camera_frame = rospy.get_param('~camera_frame', '')
conf = rospy.get_param('~conf', '0.5')
self.visualize = rospy.get_param('~visualize', 'True')
# 设备选择
self.device = 'cuda' if not rospy.get_param('/use_cpu', 'false') else 'cpu'
# 模型初始化
self.model = YOLO(weight_path)
self.model.fuse()
self.model.conf = conf
self.color_image = Image()
self.getImageStatus = False
# 订阅者和发布者
self.color_sub = rospy.Subscriber(image_topic, Image, self.image_callback, queue_size=1, buff_size=52428800)
self.position_pub = rospy.Publisher(pub_topic, BoundingBoxes, queue_size=1)
self.image_pub = rospy.Publisher('/yolov8/detection_image', Image, queue_size=1)
# 等待图像
while not self.getImageStatus:
rospy.loginfo("waiting for image.")
rospy.sleep(2)
def image_callback(self, image):
self.boundingBoxes = BoundingBoxes()
self.boundingBoxes.header = image.header
self.boundingBoxes.image_header = image.header
self.getImageStatus = True
# 转换图像格式
self.color_image = np.frombuffer(image.data, dtype=np.uint8).reshape(image.height, image.width, -1)
self.color_image = cv2.cvtColor(self.color_image, cv2.COLOR_BGR2RGB)
# YOLO检测
results = self.model(self.color_image, show=False, conf=0.3)
# 调用可视化函数
self.dectshow(results, image.height, image.width)
cv2.waitKey(3)
def dectshow(self, results, height, width):
# 创建原始图像的副本
self.frame = self.color_image.copy()
# 计算FPS
fps = 1000.0 / results[0].speed['inference']
cv2.putText(self.frame, f'FPS: {int(fps)}', (20,50), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2, cv2.LINE_AA)
# 处理每个检测结果
for result in results[0].boxes:
# 提取边界框坐标
box = result.xyxy[0].tolist()
x1, y1, x2, y2 = [int(coord) for coord in box[:4]]
cls_name = results[0].names[int(result.cls)]
conf = result.conf.item()
# +++ 根据类别名称直接判断颜色 +++
if cls_name == 'red':
color = [0, 0, 255] # BGR: 红色
elif cls_name == 'blue':
color = [255, 0, 0] # BGR: 蓝色
elif cls_name == 'yellow':
color = [0, 255, 255] # BGR: 黄色
else:
color = [0, 255, 0] # 默认绿色
# +++ 使用直接判断方式绘制边界框和标签 +++
cv2.rectangle(self.frame, (x1, y1), (x2, y2), color, 7)
# 计算文本位置
text_pos_y = y1
label = f"{cls_name} {conf:.2f}"
cv2.putText(self.frame, label, (x1, text_pos_y-10),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2, cv2.LINE_AA)
# 填充边界框消息
boundingBox = BoundingBox()
boundingBox.xmin = x1
boundingBox.ymin = y1
boundingBox.xmax = x2
boundingBox.ymax = y2
boundingBox.Class = cls_name
boundingBox.probability = conf
self.boundingBoxes.bounding_boxes.append(boundingBox)
# 发布消息
self.position_pub.publish(self.boundingBoxes)
# 转换为BGR格式后发布
self.publish_image(cv2.cvtColor(self.frame, cv2.COLOR_RGB2BGR), height, width)
def publish_image(self, imgdata, height, width):
# 创建ROS图像消息
image_temp = Image()
header = Header(stamp=rospy.Time.now())
header.frame_id = self.camera_frame
image_temp.height = height
image_temp.width = width
image_temp.encoding = 'bgr8'
image_temp.data = np.array(imgdata).tobytes()
image_temp.header = header
image_temp.step = width * 3
self.image_pub.publish(image_temp)
def main():
rospy.init_node('yolov8_ros', anonymous=True)
yolo_dect = Yolo_Dect()
rospy.spin()
if __name__ == "__main__":
main()
```
### 主要修改说明:
1. **直接类别判断着色**:
```python
if cls_name == 'red':
color = [0, 0, 255] # BGR: 红色
elif cls_name == 'blue':
color = [255, 0, 0] # BGR: 蓝色
elif cls_name == 'yellow':
color = [0, 255, 255] # BGR: 黄色
else:
color = [0, 255, 0] # 默认绿色
```
2. **边界框绘制**:
```python
cv2.rectangle(self.frame, (x1, y1), (x2, y2), color, 7) # 使用7像素粗的边界框
```
3. **文本标注**:
```python
cv2.putText(self.frame, label, (x1, text_pos_y-10),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2, cv2.LINE_AA)
```
4. **保持其他功能不变**:
- FPS显示
- 边界框消息发布
- 图像话题发布
### 使用说明:
1. 确保YOLO模型输出的类别名称包含"red"、"blue"和"yellow"
2. 边界框颜色将根据类别名称直接设置:
- 红色物体 → 红色边界框
- 蓝色物体 → 蓝色边界框
- 黄色物体 → 黄色边界框
- 其他物体 → 绿色边界框
3. 处理后的图像通过`/yolov8/detection_image`话题发布
阅读全文
相关推荐















