二值图贴标签算法
/*
二值图处理 --- 贴标签法
f(i,j) 检测图像 g(i,j) 标签图像初始值为设lab = 0
1. 从左到右从上到下扫描f(i,j)
2. 如果f图像点(i,j)不为指定的值而回到
看该点(i,j) 的在g图像的邻域内的lab值情况
如果值都为0 则lab +=1 , g(i,j) = lab;
如果不为0的值都相同则g(i,j) = lab;
如果不为0的值不同即lab2>lab1 (不会出现三个不同值),g(i,j) = lab1 , 所有lab2的值也都改为lab1 ;lab = lab -1 ;
3.扫描全部g图终止
*/
#include "stdafx.h"
void cvMark(unsigned char *arry,unsigned char *mask,int nwidth , int nheight , int threshold );
int _tmain(int argc, _TCHAR* argv[])
{
unsigned char arry[36] = {
0 , 1 , 0 , 0 , 0 , 0,
0 , 1 , 0 , 1 , 1 , 0,
0 , 0 , 1 , 0 , 0 , 0,
0 , 0 , 0 , 0 , 0 , 0,
0 , 1 , 1 , 0 , 1 , 1,
0 , 1 , 0 , 1 , 0 , 0
};
puts("原图");
for (int i = 0; i <6 ; ++i)
{
for (int j = 0; j <6; ++j)
{
printf("%4d",*(arry + i * 6 + j));
}
puts("");
}
puts("贴标签");
unsigned char data[36];
cvMark(arry,data,6,6,1);
for (int i = 0; i <6 ; ++i)
{
for (int j = 0; j <6; ++j)
{
printf("%4d",*(data + i * 6 + j));
}
puts("");
}
getchar();
return 0;
}
// 8 邻域标记
二值图处理 --- 贴标签法
f(i,j) 检测图像 g(i,j) 标签图像初始值为设lab = 0
1. 从左到右从上到下扫描f(i,j)
2. 如果f图像点(i,j)不为指定的值而回到
看该点(i,j) 的在g图像的邻域内的lab值情况
如果值都为0 则lab +=1 , g(i,j) = lab;
如果不为0的值都相同则g(i,j) = lab;
如果不为0的值不同即lab2>lab1 (不会出现三个不同值),g(i,j) = lab1 , 所有lab2的值也都改为lab1 ;lab = lab -1 ;
3.扫描全部g图终止
*/
#include "stdafx.h"
void cvMark(unsigned char *arry,unsigned char *mask,int nwidth , int nheight , int threshold );
int _tmain(int argc, _TCHAR* argv[])
{
unsigned char arry[36] = {
0 , 1 , 0 , 0 , 0 , 0,
0 , 1 , 0 , 1 , 1 , 0,
0 , 0 , 1 , 0 , 0 , 0,
0 , 0 , 0 , 0 , 0 , 0,
0 , 1 , 1 , 0 , 1 , 1,
0 , 1 , 0 , 1 , 0 , 0
};
puts("原图");
for (int i = 0; i <6 ; ++i)
{
for (int j = 0; j <6; ++j)
{
printf("%4d",*(arry + i * 6 + j));
}
puts("");
}
puts("贴标签");
unsigned char data[36];
cvMark(arry,data,6,6,1);
for (int i = 0; i <6 ; ++i)
{
for (int j = 0; j <6; ++j)
{
printf("%4d",*(data + i * 6 + j));
}
puts("");
}
getchar();
return 0;
}
// 8 邻域标记
void cvMark(unsigned char *arry,int *mask,int nwidth , int nheight , int threshold,int *count )
{
//memset(mask,0,nwidth * nheight);
int label = 0;
int lab1,lab2 = 0 ;
int data[4];
//遍历顺序从左到右,从上到下
for (int i = 0; i< nheight ; ++i)
{
for (int j = 0; j < nwidth ; ++j)
{
//f图不为threshold跳过
if ( *(arry + i * nwidth + j)!=threshold)
continue;
//扫描该点在g图邻域lab值,简化运算只计算
// i-1,i,j-1 , i+1,j-1
// i-1 , 即可
if ( i-1 < 0 || j -1 < 0)
data[0] = 0;
else
data[0] = *(mask + (i -1) * nwidth + j -1);
if (i-1 < 0)
data[1] =0;
else
data[1] = *(mask + (i-1)*nwidth + j);
if (i-1 < 0 || j+1>nwidth)
data[2] = 0;
else
data[2] = *(mask + (i-1)*nwidth + j+1);
if (j -1 < 0)
data[3] = 0;
else
data[3] = *(mask + i *nwidth + j-1);
lab1 = 0;
lab2 = 0;
for (int k = 0 ;k<4;++k)
{
if (data[k]!=0)
{
if (lab1 ==0)
{
lab1 = data[k];
}
else if(data[k] != lab1)
{
lab2 = data[k];
}
}
}
if (lab1 ==0 && lab2 ==0)
{
// 8 邻域全为0
label = label +1;
*(mask + i * nwidth + j) = label;
}
else if (lab2 ==0)
{
//8邻域lab 值相同
*(mask + i * nwidth + j) =lab1;
}
else
{
//8 邻域lab值不同
//取较小的lab值,大lab值全部复制为小lab值
if (lab1 > lab2)
{
lab1 = lab1 ^ lab2;
lab2 = lab1 ^ lab2;
lab1 = lab1 ^ lab2;
}
*(mask + i * nwidth + j) =lab1;
for (int l = 0 ; l< i*nwidth + j ; ++l)
{
if ( * (mask + l) == lab2)
{
*(mask + l) = lab1;
}
}
label = label - 1 ;
}
}
}
*count = label;
}
/*
函数:area_select
参数:mark -- 贴标签法得到的标记图 cvmark得到
img -- 二值图像
area -- 面积选择 小于area的将被删除
nwidth -- 图像宽度
nheight --- 图像高度
count --- 连通域个数 由cvmark得到
*/
void area_select( int * mark,unsigned char * img,int area,int nwidth,int nheight,int count)
{
int *acc = (int *)malloc((count+1) * sizeof(int));
memset(acc,0,(count+1) * sizeof(int));
//统计各连通域白点个数
for (int i = 0; i <nheight ;++i)
{
for (int j = 0 ; j<nwidth ;++j)
{
int base =*(mark + i * nwidth + j ) ;
if (base !=0)
{
acc[base]++;
}
}
}
//删除小于area的连通域
for (int i=0;i<nheight ;++i)
{
for (int j = 0 ; j < nwidth ; ++j)
{
int base = *(mark + i * nwidth + j );
if (base >0 && acc[base] <area)
{
*(img + i * nwidth + j) = 0;
}
}
}
free(acc);
}作者: 小马_xiao
出处:http://www.cnblogs.com/xiaomaLV2/>
关于作者:专注halcon\opencv\机器视觉
本文版权归作者,未经作者同意必须保留此段声明,且在文章页面明显位置给出 原文链接