在二值化图像中,相互联结的黑像素集合成为一个(黑)区域,通过对图像内每个区域进行标记操作,求得区域的数目。
处理前的f是二值的,像素要么为0(黑),要么为255(白)
处理后每个像素的值即为其所处理区域的标号(1,2,3,。。。)
标记规则
1.初始化标记为0,从左到右,从上到下逐个像素扫描
2.若该点为物体颜色,则继续判断该点的左上、正上,右上及左前点是否都不为物体,则标号加1,若该点为背景色,则跳过。
3.优先级依次为右上点,正上点,左上点及左前点。右上点的优先级最高,左前点的优先级最低。
4.继续遍历图像,若右上点为物体,则该点标记上与右上点相同的值。
5.若右上不为物体,则判断正上点,左上点及左前点
特殊情况:当前点的右上点及左前点为不同标记,正上点和左上点不为物体,则当前点标记同右上点置相同的值,把所有标记与左前点相同的像素值都标记成与右上点同样的值。
如图下面的黑点,如果出现上面的特殊情况,可以这样处理:
int sign_count = 0; int sum[5] = {0}; int sign_temp; for(int y = 1; y<120 - 1;y++) for(int x = 1; x<180 - 1;x++) { //只有当像素点为物体,才进行下面的判断。 if(img[y][x] == 0) { //解决特殊情况 if(img[y-1][x+1] != img [y][x-1] && img[y-1][x-1] == img[y-1][x]) { img[y][x] = img[y - 1][x + 1]; sign_temp = img [y][x-1]; for(int i = 0; i<y; i ++) for(int j = 0; j<x;j++) { if(img[i][j] == sign_temp) img[i][j] = img[y][x] } } //如果该点周围四个点皆为背景,则说明该点新的物体,将标记累加,并将该点赋值为标记。 if((img[y][x - 1] + img[y - 1][x - 1] +img[y - 1][x] +img[y - 1][x + 1])/4 !=0) { sign_count+=1; img[y][x] =sign_count; } //如果该点周围有存在物体,则按优先级,将标号赋值给该点。 else{ if(img[y - 1][x + 1]!= 0) img[y][x] = img[y - 1][x + 1]; else if(img[y - 1][x] != 0) img[y][x] = img[y - 1][x]; else if(img[y - 1][x - 1] != 0) img[y][x] = img[y - 1][x - 1]; else img[y][x] = img[y][x - 1]; } } } //图像面积统计 for(int y = 1; y<120 - 1;y++) for(int x = 1; x<180 - 1;x++) { switch(img[y][x]) { case 0:{sum[0]++;break;} case 1:{sum[1]++;break;} case 2:{sum[2]++;break;} case 3:{sum[3]++;break;} case 4:{sum[4]++;break;} } } }
在二值化图像中,通过对图像内的每个像素进行标记操作,将物体的像素值改为标号,求各种标号的总和,即求得不同区域的面积数目。
在二值化区域标记的基础上,物体的像素值改为标号,再采用边界跟踪法,跟踪各封闭区域边界线(轮廓线)的每个黑像素的标号,记录二值图像物体边界。
再二值化图像的区域标记基础上,通过对图像内每个标记区域进行计算,求得总区域得数目,并求得每个区域面积(像素数)在阈值以下时,则消去该区域,全部置为255(白),由此得到新图形。
原文:https://www.cnblogs.com/-wenli/p/11722469.html