关闭 x
IT技术网
    技 采 号
    ITJS.cn - 技术改变世界
    • 实用工具
    • 菜鸟教程
    IT采购网 中国存储网 科技号 CIO智库

    IT技术网

    IT采购网
    • 首页
    • 行业资讯
    • 系统运维
      • 操作系统
        • Windows
        • Linux
        • Mac OS
      • 数据库
        • MySQL
        • Oracle
        • SQL Server
      • 网站建设
    • 人工智能
    • 半导体芯片
    • 笔记本电脑
    • 智能手机
    • 智能汽车
    • 编程语言
    IT技术网 - ITJS.CN
    首页 » 算法设计 »改进的二值图像像素标记算法及程序实现

    改进的二值图像像素标记算法及程序实现

    2014-08-19 00:00:00 出处:博客园
    分享

    笔者实现了一个论文里面的算法程序,论文(可以网上搜索到,实在搜不到可以联系笔者或留下邮箱发给你)讲解比较到位,按照作者的思路写完了代码,测试效果很好,在此分享一下算法思路及实现代码。

    此算法优于一般的像素标记算法,只需扫描一遍就可以得出图像边界、面积等等,大大减少了计算量。

    算法描述:

    一、全图扫描

    对二值图像全图扫描,左到右,上到下,一遇到像素边界就进行判断。像素边界指当前像素灰度为1,其他8领域至少有一个灰度值为0。

    1.先依次判断当前像素(i,j)的左侧、左上侧、上侧像素和右上侧像素是否被已标记,一旦遇到已标记则说明当前像素(i,j)和这个已标记像素属于同一个目标,赋予Edge[i][j]相同的标记值,结束本像素标记,如四个像素都未标记则进入第二步。

    2.当前像素右移一部,即变为(i,j+1),进入一子循环,每次循环判断当前像素右上侧像素是否已标记。如已标记则赋予Edge[i][j]相同的标记值并跳出循环结束,如当前像素右上侧像素未标记则右移一位像素继续判断,直到到达这一行像素的右侧边界,跳出循环说明像素(i,j)属于新目标。则原来最大目标标记值temp加1并赋予Edge[i][j],结束本像素标记。

    这一大步需要注意可能会有同一类别被分到不同目标,需要全图扫描时进行判断,主要是凹形。

    二、扫描后处理

    1.归类。前面记录的等价标记数组只是记录了两两等价情况,而实际可能超过两个,如三个等价。这里需要补充的是,Same2数组是一个tempX1的数组,第几行就对应第几个目标处理情况。依次扫描Same1数组每一行,在Same2中修改类别值,保证统一类的值归为一类。

    2.标以正确的目标值。经过上一步,属于同一目标的像素标记值都已归为一类,有几类就有几个带下凹的目标,再加上0的个数(不带下凹的目标个数)就是实际目标总数。顺序扫描Same2,遇到0说明该行号表示的目标位没有下凹的,result+1赋予Same3的同一行,遇到非零数字,则看它是否第一次出现,假如第一次出现,result+1并赋予Same3同一行,如Same2这一行的值不是第一次出现,则把前面具有相同数字那一行在Same3中同行的值赋予Same3的这一行,直到检测完Same2。最后在Same3的最后数字表示的就是目标数。

    3.根据得到目标数进行目标划分,整个图像就被分到了几个目标值。得到的目标值可以统计目标数目、实现面积、周长和质心等特征值。

    程序代码:

    //改进的像素标记算法实现代码及注释
    //作者用这个算法来绘制目标外接矩形用的
    //返回找到图像目标处理凹形数目,参数frame是原始二值图像,num为处理前凹形找到目标数目,s和e分别表示绘制矩形的开始点和结束点
    int pixelFlag(cv::Mat &frame,int &num,vector<Point2f> &s,vector<Point2f> &e)//返回个数
    {
    //frame.
    int kind=0,kindEnd=0,kindResult=0;//归类类别
    vector<int> same1[2];//可疑边界目标

    int edge[frame.rows][frame.cols];//表明边界属于哪个类
    memset(edge,0,sizeof(edge));
    //qDebug()<<frame.channels();
    //扫描每个像素判断
    for(int i=1;i<frame.rows-1;i++)
    for(int j=1;j<frame.cols-1;j++)
    {
    if((frame.at<uchar>(i,j)!=0)&&(!frame.at<uchar>(i-1,j)||!frame.at<uchar>(i-1,j-1)||!frame.at<uchar>(i-1,j+1)
    ||!frame.at<uchar>(i,j-1)||!frame.at<uchar>(i,j+1)||!frame.at<uchar>(i+1,j-1)
    ||!frame.at<uchar>(i+1,j)||!frame.at<uchar>(i+1,j+1)))//判断边界点
    {
    if(edge[i][j-1])//判断是否紧邻已被标物体 左
    {
    edge[i][j]=edge[i][j-1];
    }
    else
    if(edge[i-1][j-1])//左上
    {
    edge[i][j]=edge[i-1][j-1];
    }
    else
    if(edge[i-1][j])//上
    {
    edge[i][j]=edge[i-1][j];
    }else
    if(edge[i-1][j+1])//右上
    {
    edge[i][j]=edge[i-1][j+1];
    }else
    {
    int f=0;
    while(frame.at<uchar>(i,j+f)&&((j+f)<frame.cols-1))//右移判断
    {
    if(edge[i-1][j+f+1])
    {
    edge[i][j]=edge[i-1][j+f+1];
    break;
    }
    else
    {
    f++;
    }
    }
    if(!frame.at<uchar>(i,j+f))//未找到处理
    {
    kind++;
    edge[i][j]=kind;

    }
    }
    if(edge[i][j]&&edge[i-1][j+1])//假如当前点和右上不在一个类别就记录
    {
    if(edge[i][j]!=edge[i-1][j+1])
    {
    same1[0].push_back(edge[i][j]);
    same1[1].push_back(edge[i-1][j+1]);
    }
    }

     

    }
    }

    //处理扫描后的结果
    int same2[kind];memset(same2,0,sizeof(same2));
    int sameEnd[kind];memset(sameEnd,0,sizeof(sameEnd));
    //QDebug debug;
    if(!same1[0].empty())
    {
    for(uint i=0;i<same1[0].size();i++)
    {
    if((!same2[same1[0][i]-1])&&(!same2[same1[1][i]-1]))//假如都没有处理,种类加1
    {
    kindEnd++;
    same2[same1[0][i]-1]=kindEnd;
    same2[same1[1][i]-1]=kindEnd;
    }else
    if(same2[same1[0][i]-1]&&same2[same1[1][i]-1])
    {
    same2[same1[0][i]-1]=same2[same1[1][i]-1];

    }else
    if(!same2[same1[0][i]-1]&&same2[same1[1][i]-1])
    {
    same2[same1[0][i]-1]=same2[same1[1][i]-1];
    }else if(same2[same1[0][i]-1]&&!same2[same1[1][i]-1])
    {
    same2[same1[1][i]-1]=same2[same1[0][i]-1];
    }

    }
    }

    for(int i=0;i<kind;i++)//复制到sameend
    {

    if(!same2[i])
    {
    kindResult++;
    sameEnd[i]=kindResult;
    }
    else
    //if(same2)
    {
    int j=0;
    while(j<i)
    {
    if(same2[j]==same2[i])
    {
    break;
    }
    j++;
    }
    if(j<i)
    {
    sameEnd[i]=sameEnd[j];
    }else
    {
    kindResult++;
    sameEnd[i]=kindResult;
    }

    }
    }
    num=kind;
    //对边界进行处理
    for(int i=1;i<frame.rows-1;i++)
    for(int j=1;j<frame.cols-1;j++)
    {
    if(edge[i][j])
    {
    edge[i][j]=sameEnd[edge[i][j]-1];
    }
    }
    for(int i=0;i<kindResult;i++)
    {
    s.push_back(Point2f(1000,1000));
    e.push_back(Point2f(0,0));
    }
    for(int i=1;i<frame.rows-1;i++)//求边界对角点
    for(int j=1;j<frame.cols-1;j++)
    {
    if(edge[i][j])
    {
    if(s[edge[i][j]-1].y>i)
    {
    s[edge[i][j]-1].y=i;
    }
    if(s[edge[i][j]-1].x>j)
    {
    s[edge[i][j]-1].x=j;
    }
    if(e[edge[i][j]-1].y<i)
    {
    e[edge[i][j]-1].y=i;
    }

    if(e[edge[i][j]-1].x<j)
    {
    e[edge[i][j]-1].x=j;
    }
    }
    }
    return kindResult;

    }

    效果如下:

    上一篇返回首页 下一篇

    声明: 此文观点不代表本站立场;转载务必保留本文链接;版权疑问请联系我们。

    别人在看

    正版 Windows 11产品密钥怎么查找/查看?

    还有3个月,微软将停止 Windows 10 的更新

    Windows 10 终止支持后,企业为何要立即升级?

    Windows 10 将于 2025年10 月终止技术支持,建议迁移到 Windows 11

    Windows 12 发布推迟,微软正全力筹备Windows 11 25H2更新

    Linux 退出 mail的命令是什么

    Linux 提醒 No space left on device,但我的空间看起来还有不少空余呢

    hiberfil.sys文件可以删除吗?了解该文件并手把手教你删除C盘的hiberfil.sys文件

    Window 10和 Windows 11哪个好?答案是:看你自己的需求

    盗版软件成公司里的“隐形炸弹”?老板们的“法务噩梦” 有救了!

    IT头条

    公安部:我国在售汽车搭载的“智驾”系统都不具备“自动驾驶”功能

    02:03

    液冷服务器概念股走强,博汇、润泽等液冷概念股票大涨

    01:17

    亚太地区的 AI 驱动型医疗保健:2025 年及以后的下一步是什么?

    16:30

    智能手机市场风云:iPhone领跑销量榜,华为缺席引争议

    15:43

    大数据算法和“老师傅”经验叠加 智慧化收储粮食尽显“科技范”

    15:17

    技术热点

    商业智能成CIO优先关注点 技术落地方显成效(1)

    用linux安装MySQL时产生问题破解

    JAVA中关于Map的九大问题

    windows 7旗舰版无法使用远程登录如何开启telnet服务

    Android View 事件分发机制详解

    MySQL用户变量的用法

      友情链接:
    • IT采购网
    • 科技号
    • 中国存储网
    • 存储网
    • 半导体联盟
    • 医疗软件网
    • 软件中国
    • ITbrand
    • 采购中国
    • CIO智库
    • 考研题库
    • 法务网
    • AI工具网
    • 电子芯片网
    • 安全库
    • 隐私保护
    • 版权申明
    • 联系我们
    IT技术网 版权所有 © 2020-2025,京ICP备14047533号-20,Power by OK设计网

    在上方输入关键词后,回车键 开始搜索。Esc键 取消该搜索窗口。