• 二值图贴标签算法


    /*
        二值图处理 --- 贴标签法
        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);
    }





  • 相关阅读:
    构造函数、原型、实例化对象
    JS闭包的理解
    JQuery知识点
    面向对象
    学习使用Vuex
    Runtime详解
    ffmpeg各结构体之间关联 ---- AVPacket
    AVFrame
    block的底层原理
    performSelector
  • 原文地址:https://www.cnblogs.com/xiaomaLV2/p/2269991.html
Copyright © 2020-2023  润新知