高级目标检测技术:从基础到实践
立即解锁
发布时间: 2025-09-01 01:57:41 阅读量: 2 订阅数: 12 AIGC 

### 高级目标检测技术:从基础到实践
#### 1. 目标检测基础回顾
在目标检测的早期方法中,R - CNN和Fast R - CNN技术利用区域建议来预测图像中物体的位置和类别。然而,这些方法存在推理速度瓶颈,因为它们使用两个不同的模型:一个用于生成区域建议,另一个用于目标检测。例如,之前的代码执行需要1.5秒,主要原因就在于此。
#### 2. 现代目标检测算法组件
现代目标检测算法致力于训练单个神经网络,以在一次前向传播中检测所有物体。其主要组件包括:
- **锚框(Anchor boxes)**:
- 大多数物体具有相似的形状,例如人的边界框通常高度大于宽度,卡车的边界框宽度大于高度。通过检查数据集中物体边界框的真实值,我们可以大致了解物体的高度和宽度。
- 通常使用K - means聚类对图像中物体的真实边界框进行处理,以定义代表数据集中大多数物体边界框的锚框。
- 使用方法:
1. 将每个锚框从图像的左上角滑动到右下角。
2. 与物体有高交并比(IoU)的锚框标记为包含物体,其他标记为0。
- 除了基本的锚框,还会创建不同尺度的锚框,以适应图像中物体的不同尺度。
- **区域建议网络(Region proposal network,RPN)**:
- 以224 x 224 x 3的图像和8 x 8的锚框为例,步长为8像素时,每行可获取224 / 8 = 28个图像裁剪块,一张图像总共可获取28 * 28 = 576个裁剪块。将这些裁剪块通过RPN,RPN会指示该裁剪块是否包含物体。
- 与SelectiveSearch相比,SelectiveSearch基于像素值计算生成区域候选,而RPN基于锚框和滑动步长生成区域候选。
- RPN训练模型识别可能包含物体的区域建议的步骤如下:
1. 在图像上滑动不同长宽比和大小的锚框,获取图像裁剪块。
2. 计算图像中物体的真实边界框与上一步获取的裁剪块之间的IoU。
3. 准备训练数据集,使IoU大于阈值的裁剪块标记为包含物体,小于阈值的标记为不包含物体。
4. 训练模型识别包含物体的区域。
5. 执行非极大值抑制,识别最有可能包含物体的区域候选,并消除与之高度重叠的其他区域候选。
- **感兴趣区域池化(Region of interest,RoI)**:在之前的章节已经讨论过,用于确保所有区域的特征图形状一致。
#### 3. 分类和回归
在识别物体和调整边界框的过程中,前面的步骤存在两个问题:
- 区域建议不能紧密贴合物体(RPN中IoU > 0.5为阈值)。
- 只识别了区域是否包含物体,未识别区域中物体的类别。
为解决这些问题,将之前获得的统一形状的特征图通过一个网络,该网络预测区域内物体的类别以及区域对应的偏移量,以确保边界框尽可能紧密地围绕图像中的物体。如果数据中有20个类别,神经网络的输出总共包含25个输出:21个类别(包括背景类)和4个应用于边界框高度、宽度和两个中心坐标的偏移量。
#### 4. Faster R - CNN工作流程总结
```mermaid
graph LR
A[输入图像] --> B[GeneralizedRCNNTransform]
B --> C[BackboneWithFPN]
C --> D[RegionProposalNetwork]
D --> E[RoIHeads]
E --> F[输出类别和边界框]
```
#### 5. 在自定义数据集上训练Faster R - CNN
以下是在自定义数据集上训练Faster R - CNN的详细步骤:
##### 5.1 下载数据集
```python
!pip install -qU torch_snippets
import os
%%writefile kaggle.json
{"username":"XXX", "key":"XXX"}
!mkdir -p ~/.kaggle
!cp kaggle.json ~/.kaggle/
!chmod 600 /root/.kaggle/kaggle.json
!kaggle datasets download -d sixhky/open-images-bus-trucks/
!unzip -qq open-images-bus-trucks.zip
!rm open-images-bus-trucks.zip
```
##### 5.2 读取包含图像元数据、边界框和类别的DataFrame
```python
from torch_snippets import *
from PIL import Image
IMAGE_ROOT = 'images/images'
DF_RAW = df = pd.read_csv('df.csv')
```
##### 5.3 定义标签和目标对应的索引
```python
label2target = {l:t+1 for t,l in enumerate(DF_RAW['LabelName'].unique())}
label2target['background'] = 0
target2label = {t:l for l,t in label2target.items()}
background_class = label2target['background']
num_classes = len(label2target)
```
##### 5.4 定义图像预处理函数
```python
def preprocess_image(img):
img = torch.tensor(img).permute(2,0,1)
return img.to(device).float()
```
##### 5.5 定义数据集类
```python
class OpenDataset(torch.utils.data.Dataset):
w, h = 224, 224
def __init__(self, df, image_dir=IMAGE_ROOT):
self.image_dir = image_dir
self.files = glob.glob(self.image_dir+'/*')
self.df = df
self.image_infos = df.ImageID.unique()
def __getitem__(self, ix):
# load images and masks
image_id = self.image_infos[ix]
img_path = find(image_id, self.files)
img = Image.open(img_path).convert("RGB")
img = np.array(img.resize((self.w, self.h),
resample=Image.BILINEAR))/255.
data = df[df['ImageID'] == image_id]
labels = data['LabelName'].values.tolist()
data = data[['XMin','YMin','XMax','YMax']].values
# Convert to absolute coordinates
data[:,[0,2]] *= self.w
data[:,[1,3]] *= self.h
boxes = data.astype(np.uint32).tolist()
# torch FRCNN expects ground truths as
# a dictionary of tensors
target = {}
target["boxes"] = torch.Tensor(boxes).float()
target["labels"]= torch.Tensor([label2target[i] \
for i in labels]).long()
img = preprocess_image(img)
return img, target
def collate_fn(self, batch):
return tuple(zip(*batch))
def __len__(self):
return len(self.image_infos)
```
##### 5.6 创建训练和验证数据加载器和数据集
```python
from sklearn.model_selection import train_test_split
trn_ids, val_ids = train_test_split(df.ImageID.unique(),
test_size=0.1, random_state=99)
trn_df, val_df = df[df[
```
0
0
复制全文
相关推荐









