边缘零交叉二值化原理:
通过LoG算子检测出边缘并将二侧的局部象素划分为背景和目标2类;当局部均为目标或者背景(这时不存在边缘)时,先将其确定为待定区域,然后进行连通区域标记,最后根据标记后连通区域周围象素的属性判断归属将其正确地进行二值化。
1.Log算子边缘检测
log边缘检测非常好理解,先进行高斯平滑处理,再进行拉普拉斯边缘检测,最终得到的图像数据为含有正负号的二次导数的图像。
2.分类
依据LoG算子计算后对图像的边缘零交叉结果h(x,y),对图像像素进行分类,借助局部区域图像象素灰度的极大值和极小值的差值s来判断该区域属于均一区域还是真正的边缘,分为前景(目标),背景和待定区。
(1)当s大于某个阈值且h(x,y)>0时,令该象素为背景 -1。
(2)当s大于某个阈值且h(x,y)<0时,令该象素为目标 1。
(3)当前二者条件都不满足时,令该象素为待定区域‘0’。
此时的待定区可以用使用otsu算法再次进行分类,采用这种方法的话,第三步将省略。
差值计算代码:
int getNeighborMaxDiff(Mat src, Point center_point, int half_size)
{
int max = 0;
int min = 256;
int max_diff = 0;
int nr = src.rows;
int nc = src.cols * src.channels();
int start_x = 0;
int end_x = 0;
int start_y = 0;
int end_y = 0;
if(center_point.x - half_size < 0)
{
start_x = 0;
}
else
{
start_x = center_point.x - half_size;
}
if(center_point.x + half_size > nc)
{
end_x = nc;
}
else
{
end_x = center_point.x + half_size;
}
if(center_point.y - half_size < 0)
{
start_y = 0;
}
else
{
start_y = center_point.y - half_size;
}
if(center_point.y + half_size > nr)
{
end_y = nr;
}
else
{
end_y = center_point.y + half_size;
}
for(int i=start_y; i<end_y; i++)
{
uchar *data = src.ptr<uchar>(i);
for(int j=start_x; j<end_x; j++)
{
int current_data = data[j];
if(current_data > max)
{
max = data[j];
}
if(current_data < min)
{
min = data[j];
}
}
cout << endl;
}
max_diff = max - min;
if(max_diff < 0)
{
return -1;
}
return max_diff;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
3.待定区分类
采用基于邻域统计的方法来对待定区进行分类。对每个待定区域象素进行4连通区域标记,并分别统计每个标记区域周围的8连接目标象素个数numA与8连接背景象素的个数numB。利用numA和numB进行二值化,规则如下:
(1)当该区域的8连接目标象素个数numA大于8连接的背景象素个数numB时,令该区域象素为目标 1。
(2)当该区域的8连接目标象素个数numA小于等于8连接的背景象素个数numB时,令该区域象素为背景 -1。
经过以上步骤得到背景和目标分开的二值图像。
|