背景分割技术:码本模型、连通分量清理及方法比较
立即解锁
发布时间: 2025-08-21 01:23:49 阅读量: 1 订阅数: 7 


OpenCV 3计算机视觉实战指南
# 背景分割技术:码本模型、连通分量清理及方法比较
## 1. 码本背景模型的使用
码本背景分割技术是一种常用的背景建模方法,使用该技术通常需要遵循以下步骤:
1. **学习背景基本模型**:使用 `updateCodebook()` 函数,在几秒或几分钟内学习背景的基本模型。
2. **清理陈旧条目**:调用 `clearStaleEntries()` 函数,清除码本中陈旧的条目。
3. **调整阈值**:调整 `minMod` 和 `maxMod` 阈值,以最佳地分割已知的前景。
4. **维护高级场景模型**:如之前讨论的那样,维护一个更高级的场景模型。
5. **分割前景和背景**:使用学习到的模型,通过 `backgroundDiff()` 函数将前景从背景中分割出来。
6. **定期更新背景像素**:定期更新学习到的背景像素,以适应场景的变化。
7. **缓慢清理陈旧条目**:以较慢的频率,再次使用 `clearStaleEntries()` 函数清理码本中的陈旧条目。
### 码本模型的更多思考
码本方法在许多条件下都能很好地工作,并且训练和运行速度相对较快。然而,它在处理不同的光照模式(如早晨、中午和傍晚的阳光)或室内灯光的开关时表现不佳。为了解决这种全局变化的问题,可以使用多个不同的码本模型,每个模型对应一种特定的条件,并根据当前条件选择激活的模型。
## 2. 前景清理的连通分量分析
在比较平均法和码本方法之前,我们需要讨论如何使用连通分量分析来清理原始分割图像。这种分析方法对于有噪声的输入掩码图像非常有用,因为噪声在实际应用中是很常见的。
### 连通分量分析的基本思想
连通分量分析的基本思想是先使用形态学开运算将小噪声区域缩小为 0,然后使用形态学闭运算重建在开运算中丢失的存活分量区域。之后,找到存活段的“足够大”的轮廓,并对所有这些段进行统计分析。最后,检索最大的轮廓或所有大小超过某个阈值的轮廓。
### 连通分量清理的实现
以下是实现连通分量分析的代码:
```cpp
// This cleans up the foreground segmentation mask derived from calls
// to backgroundDiff
//
void findConnectedComponents(
cv::Mat& mask, // Is a grayscale (8-bit depth) "raw" mask image
// that will be cleaned up
int poly1_hull0 = 1, // If set, approximate connected component by
// (DEFAULT) polygon, or else convex hull (0)
float perimScale = 4, // Len = (width+height)/perimScale. If contour
// len < this, delete that contour (DEFAULT: 4)
vector<cv::Rect>& bbs // Ref to bounding box rectangle return vector
vector<cv::Point>& centers // Ref to contour centers return vector
);
```
### 代码解释
1. **形态学开运算和闭运算**:使用 `cv::morphologyEx()` 函数进行形态学开运算和闭运算,以清除小像素噪声并重建侵蚀区域。
```cpp
cv::morphologyEx(
mask, mask, cv::MOP_OPEN, cv::Mat(), cv::Point(-1,-1), CVCLOSE_ITR
);
cv::morphologyEx(
mask, mask, cv::MOP_CLOSE, cv::Mat(), cv::Point(-1,-1), CVCLOSE_ITR
);
```
2. **查找轮廓**:使用 `cv::findContours()` 函数查找所有轮廓。
```cpp
vector< vector<cv::Point> > contours_all; // all contours found
vector< vector<cv::Point> > contours; // just the ones we want to keep
cv::findContours(
mask,
contours_all,
CV_RETR_EXTERNAL,
CV_CHAIN_APPROX_SIMPLE
);
```
3. **筛选轮廓**:丢弃太小的轮廓,并使用多边形或凸包近似其余轮廓。
```cpp
for(
vector< vector<cv::Point> >::iterator c = contours_all.begin();
c != contours.end();
++c
) {
int len = cv::arcLength( *c, true );
double q = (mask.rows + mask.cols) / DP_EPSILON_DENOMINATOR;
if( len >= q ) {
vector<cv::Point> c_new;
if( poly1_hull0 ) {
cv::approxPolyDP( *c, c_new, len/20.0, true );
} else {
cv::convexHull( *c, c_new );
}
contours.push_back(c_new );
}
}
```
4. **计算质心和边界框**:计算每个轮廓的质心和边界框,并将其存储在相应的向量中。
```cpp
int idx = 0;
cv::Moments moments;
cv::Mat scratch = mask.clone();
for(
vector< vector<cv::Point> >::iterator c = contours.begin();
c != contours.end;
c++, idx++
) {
cv::drawContours( scratch, contours, idx, CVX_WHITE, CV_FILLED );
moments = cv::moments( scratch,
```
0
0
复制全文
相关推荐









