在常見的場景中,由於光照的影響,很難選定一個固定的閾值來使前景部分很好地被分割出來。
假定前景位於圖像的中間部分,四周爲背景,以四周的背景爲基礎,向中間擬合,獲得不包含前景的背景圖像。
void BackgroundFittingThreshold(IplImage * src, IplImage * dst)
{
IplImage *copy = cvCreateImage(cvSize(src->width, src->height), 8, 1);
cvCopy(src, copy);
int s_sum_v = 0, s_num_v = 0, s_delta_v = 0, e_sum_v = 0, e_num_v = 0, e_delta_v = 0;
int s_sum_h = 0, s_num_h = 0, s_delta_h = 0, e_sum_h = 0, e_num_h = 0, e_delta_h = 0;
int border = 2;
uchar *s_line_cur = (uchar *)(src->imageData + src->widthStep * border);
uchar *e_line_cur = (uchar *)(src->imageData + src->widthStep * (src->height - border));
uchar *s_line_pre, *e_line_pre; // *e_line_next, *s_line_next;
for (int i = border; i < src->height - border; i++) {
s_line_cur += src->widthStep; s_line_pre = s_line_cur - src->widthStep;
e_line_cur -= src->widthStep; e_line_pre = e_line_cur + src->widthStep;
s_sum_v = 0, s_num_v = 0; e_sum_v = 0, e_num_v = 0;
for (int j = border; j < src->width - border; j++){
int s_diff_v = s_line_cur[j] - s_line_pre[j];
if (abs(s_diff_v) < 10) {
s_sum_v += s_diff_v; s_num_v++;
}
if (s_diff_v < 0) {
s_line_cur[j] = (s_line_pre[j - 2] + s_line_pre[j - 1] + s_line_pre[j] +
s_line_pre[j + 1] + s_line_pre[j + 2]) * 0.2 + s_delta_v;
}
int e_diff_v = e_line_cur[j] - e_line_pre[j];
if (abs(e_diff_v) < 10) {
e_sum_v += e_diff_v; e_num_v++;
}
if (e_diff_v < 0) {
e_line_cur[j] = (e_line_pre[j - 2] + e_line_pre[j - 1] + e_line_pre[j] + e_line_pre[j + 1] + e_line_pre[j + 2]) * 0.2 + e_delta_v;
}
}
s_delta_v = 0;// (int)(((float)s_sum_v / (float)s_num_v) + 0.5); //上下兩層的灰度差
e_delta_v = 0;// (int)(((float)e_sum_v / (float)e_num_v) + 0.5); //上下兩層的灰度差
}
for (int i = 0; i < src->height; i++){
uchar *line_gray = (uchar *)(src->imageData + src->widthStep * i);
uchar *line_copy = (uchar *)(copy->imageData + copy->widthStep * i);
for (int j = 0; j < src->width; j++){
line_gray[j] = abs(line_gray[j] - line_copy[j]);
}
}
}