[拆轮子] PaddleDetection 中的预处理 NormalizeBox、 BboxXYXY2XYWH 和 Permute

这篇博客介绍了图像处理中的两个关键步骤:NormalizeBox和BboxXYXY2XYWH。NormalizeBox将边界框坐标缩放到[0,1]区间,同时处理关键点的缩放。BboxXYXY2XYWH则将边界框从XYXY格式转换为XYWH格式。文章通过代码示例展示了如何在应用这些变换后进行可视化。Permute操作则简单地将图像通道从HWC转换为CHW。

NormalizeBoxNormalizeImage 很像,都是缩放到某个区间

NormalizeBox 就是把gt_bbox的位置缩放到 [0,1]

class NormalizeBox(BaseOperator):
    """Transform the bounding box's coornidates to [0,1]."""

    def __init__(self):
        super(NormalizeBox, self).__init__()

    def apply(self, sample, context):
        im = sample['image']
        gt_bbox = sample['gt_bbox']
        height, width, _ = im.shape
		
		# ------------ 缩放边界框 gt_bbox ------------
        for i in range(gt_bbox.shape[0]):
            gt_bbox[i][0] = gt_bbox[i][0] / width
            gt_bbox[i][1] = gt_bbox[i][1] / height
            gt_bbox[i][2] = gt_bbox[i][2] / width
            gt_bbox[i][3] = gt_bbox[i][3] / height
        sample['gt_bbox'] = gt_bbox
		
		# ------------ 缩放关键点部分 ------------
        if 'gt_keypoint' in sample.keys():
            gt_keypoint = sample['gt_keypoint']
			
			# 关键点的标注顺序 x1y1x2y2x3y3....
            for i in range(gt_keypoint.shape[1]):
                if i % 2:
                    gt_keypoint[:, i] = gt_keypoint[:, i] / height
                else:
                    gt_keypoint[:, i] = gt_keypoint[:, i] / width
            sample['gt_keypoint'] = gt_keypoint

        return sample
class BboxXYXY2XYWH(BaseOperator):
    """
    Convert bbox XYXY format to XYWH format.
    """

    def __init__(self):
        super(BboxXYXY2XYWH, self).__init__()

    def apply(self, sample, context=None):
        assert 'gt_bbox' in sample
        bbox = sample['gt_bbox']
        bbox[:, 2:4] = bbox[:, 2:4] - bbox[:, :2]       # 拿到宽高
        bbox[:, :2] = bbox[:, :2] + bbox[:, 2:4] / 2.   # 将左上角移动至中心
        sample['gt_bbox'] = bbox
        return sample

没传入该 apply 可视化:

im = sample['image']
img = (sample['image'] * [0.229, 0.224,0.225] + [0.485, 0.456, 0.406]) * 255
img = img.astype(int).astype("uint8")
h, w, _ = img.shape
gt_bboxes = sample['gt_bbox'] * [w, h, w, h]

gt_bboxes = gt_bboxes.astype(int)
x1, y1, x2, y2 = gt_bboxes[1]

xx = cv2.rectangle(img, (x1, y1), (x2, y2), 255, thickness=2, lineType=8)
cv2.imwrite("xxx.png", xx)

传出该 apply 可视化:

im = sample['image']
img = (sample['image'] * [0.229, 0.224,0.225] + [0.485, 0.456, 0.406]) * 255
img = img.astype(int).astype("uint8")
h, w, _ = img.shape
gt_bboxes = sample['gt_bbox'] * [w, h, w, h]

gt_bboxes = gt_bboxes.astype(int)
x_c, y_c, w, h = gt_bboxes[3]
x1, y1, x2, y2 = x_c-w//2, y_c-h//2, x_c+w//2, y_c+h//2

xx = cv2.rectangle(img, (x1, y1), (x2, y2), 255, thickness=2, lineType=8)
cv2.imwrite("xxx.png", xx)

注意此处的 sample['h'] sample['w'] 都是原图的尺寸

Permute 的话就很简单了,就是 HWC 转化为 CHW

class Permute(BaseOperator):
    def __init__(self):
        """
        Change the channel to be (C, H, W)
        """
        super(Permute, self).__init__()

    def apply(self, sample, context=None):
        im = sample['image']
        im = im.transpose((2, 0, 1))
        sample['image'] = im
        return sample
<think>好的,我现在要解决的问题是用户如何在两个不同的虚拟环境中部署YOLOv11PaddleDetection,并进行行人属性识别。首先,我需要理清楚用户的需求当前的环境配置。 用户提到YOLOv11PaddleDetection分别部署在两个不同的虚拟环境里。这可能是因为这两个框架的依赖库存在冲突,或者用户希望隔离它们的环境以避免版本问题。现在用户想进行行人属性识别,可能需要结合这两个框架的功能,或者分别使用它们的不同模块。 首先,我需要确认行人属性识别的具体流程。通常,这可能包括两个主要步骤:行人检测(使用YOLOv11)属性识别(可能使用PaddleDetection中的模型)。因此,用户可能需要先用YOLOv11检测图像中的行人,然后将检测到的行人区域输入到PaddleDetection的模型中识别属性。 接下来需要考虑如何在两个独立的环境中串联这两个步骤。由于环境隔离,直接在同一个Python脚本中调用两个环境的模型可能会有问题,因为依赖库Python版本可能不兼容。这时候可能需要一种跨环境通信的方法,比如将中间结果保存到磁盘,或者使用进程间通信。 可能的解决方案步骤: 1. **分别确认两个环境的配置**:确保YOLOv11PaddleDetection在各自环境中能正常运行。用户需要测试两个环境是否能独立完成检测任务。 2. **设计流程**:确定是先使用YOLOv11进行行人检测,再使用PaddleDetection进行属性识别。例如,先运行YOLOv11的检测脚本,保存检测到的行人区域图像,然后在另一个环境中运行PaddleDetection的脚本读取这些图像并进行属性分析。 3. **数据传递方式**:因为环境隔离,最直接的方式是通过文件系统传递中间数据。比如,YOLOv11检测到行人后,将每个行人区域保存为图片文件,或者将坐标信息保存到JSON文件中。然后,PaddleDetection的环境读取这些文件进行处理。 4. **编写脚本**:用户需要为每个环境编写相应的脚本。YOLOv11的脚本负责检测并输出结果,PaddleDetection的脚本负责读取结果并进行属性识别。可能需要处理数据格式的转换,比如坐标到图像的裁剪,或者处理不同的文件格式。 5. **处理依赖冲突**:如果用户希望在一个主程序中同时调用两个模型,可能需要在一个统一的环境中安装两个框架,但可能存在依赖冲突。这时候需要检查版本兼容性,或者使用虚拟环境切换的方法,比如在脚本中激活不同的环境来运行不同的部分。不过,这种方法在Python中比较复杂,通常需要子进程调用。 6. **子进程调用**:可以考虑在一个主脚本中使用subprocess模块调用两个环境的Python解释器。例如,主脚本先调用YOLOv11环境的Python执行检测脚本,保存结果,然后调用PaddleDetection环境的Python执行属性识别脚本。这样可以在不合并环境的情况下串联流程。 7. **测试调试**:用户需要逐步测试每个环节,确保检测属性识别都能正确执行,并且数据传递无误。可能需要处理图像路径、文件格式、坐标转换等问题。 潜在的问题注意事项: - **性能问题**:频繁的磁盘读写可能会影响整体速度,尤其是处理大量图片时。可以考虑使用内存中的临时文件或者更高效的数据交换方式,但跨环境可能限制较多。 - **版本兼容性**:如果两个环境中的某些库(如numpy、opencv)版本不一致,可能导致生成的图像或数据格式不兼容。需要确保两个环境在处理图像时使用相同的版本,或者进行必要的转换。 - **路径问题**:在不同环境中运行时,文件路径可能需要特别处理,尤其是绝对路径相对路径的问题。建议使用绝对路径或者统一的相对路径结构。 - **模型输出格式**:需要确保YOLOv11输出的检测结果(如边界框坐标)能够被PaddleDetection的脚本正确解析。可能需要统一坐标的格式(如xywh或xyxy)以及置信度阈值等参数。 可能的优化方向: 如果用户希望更高效地整合两个模型,可以考虑将其中一个环境迁移到另一个环境中,前提是依赖库可以兼容。例如,检查YOLOv11PaddleDetection的依赖是否可以在同一环境中共存。如果可行,合并环境可以简化流程,避免跨环境的数据传递开销。 总结来说,用户需要分步骤在两个环境中独立处理检测属性识别,通过中间文件传递数据,或者通过子进程调用串联流程。接下来,我需要将这些思路整理成结构化的步骤,帮助用户具体实施。</think>为了在两个独立的虚拟环境中使用YOLOv11PaddleDetection实现行人属性识别,可以按以下步骤操作: --- ### **步骤1:明确任务流程** 行人属性识别通常分为两个阶段: 1. **行人检测**:用YOLOv11定位图像中的行人并裁剪出目标区域。 2. **属性识别**:用PaddleDetection的预训练属性模型(如`PicoDet`+`PET`)分析裁剪后的行人区域。 --- ### **步骤2:配置环境独立运行** 确保两个环境各自能独立运行: - **YOLOv11环境**:测试行人检测脚本,输出边界框坐标或裁剪图像。 - **PaddleDetection环境**:验证属性识别模型(需安装`paddlepaddle``paddledetection`)。 --- ### **步骤3:跨环境数据传递** #### 方案一:通过文件传递中间结果 1. **YOLOv11输出检测结果**: - 保存裁剪后的行人图像到共享目录(如`./crop_pedestrians/`)。 - 或生成包含坐标的JSON文件(格式示例): ```json [{"image_path": "input.jpg", "bbox": [x1,y1,x2,y2]}] ``` 2. **PaddleDetection读取中间结果**: - 从共享目录加载裁剪图像,或根据JSON坐标裁剪原图。 #### 方案二:子进程调用(推荐) 在主机脚本中通过`subprocess`调用两个环境: ```python import subprocess # 在YOLOv11环境执行检测 yolo_cmd = "conda run -n yolov11_env python detect.py --source input.jpg --output crop_pedestrians/" subprocess.run(yolo_cmd, shell=True) # 在Paddle环境执行属性识别 paddle_cmd = "conda run -n paddle_env python attr.py --input crop_pedestrians/" subprocess.run(paddle_cmd, shell=True) ``` --- ### **步骤4:编写具体脚本** #### YOLOv11检测脚本 (`detect.py`) ```python # 示例:检测并保存裁剪图像 from yolov11 import YOLO import cv2 model = YOLO("yolov11s.pt") img = cv2.imread("input.jpg") results = model(img) for i, bbox in enumerate(results.xyxy[0]): x1, y1, x2, y2 = map(int, bbox[:4]) crop = img[y1:y2, x1:x2] cv2.imwrite(f"crop_pedestrians/ped_{i}.jpg", crop) ``` #### PaddleDetection属性识别脚本 (`attr.py`) ```python # 示例:加载属性模型预测 from paddledetection import PaddleDetector import cv2 model = PaddleDetector(model_name="pedestrian_attribute") for img_path in os.listdir("crop_pedestrians"): img = cv2.imread(img_path) attributes = model.predict(img) # 输出性别、年龄、衣着等属性 print(f"{img_path}: {attributes}") ``` --- ### **步骤5:解决依赖冲突(可选)** 若需合并环境,尝试: ```bash conda create -n merged_env python=3.8 conda activate merged_env pip install "yolov11-requirements.txt" # YOLOv11的依赖 pip install paddlepaddle paddledetection # Paddle的依赖 ``` 需检查`torch`与`paddlepaddle`版本是否兼容。 --- ### **注意事项** 1. **路径一致性**:确保两个环境访问的输入/输出路径一致(建议用绝对路径)。 2. **图像尺寸**:裁剪后的行人图像需符合PaddleDetection模型的输入尺寸要求。 3. **性能优化**:若处理视频流,可改用内存缓存(如Redis)代替文件传递。 --- 通过以上步骤,可有效隔离环境依赖并串联两个模型的推理流程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值