Opencv求取连通区域重心

2023-10-27

我们有时候需要求取某一个物体重心,这里一般将图像二值化,得出该物体的轮廓,然后根据灰度重心法,计算出每一个物体的中心。
步骤如下:
1)合适的阈值二值化
2)求取轮廓
3)计算重心

otsu算法求取最佳阈值
otsu法(最大类间方差法,有时也称之为大津算法)使用的是聚类的思想,把图像的灰度数按灰度级分成2个部分,使得两个部分之间的灰度值差异最大,每个部分之间的灰度差异最小,通过方差的计算来寻找一个合适的灰度级别来划分,otsu算法被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响。因此,使类间方差最大的分割意味着错分概率最小。

计算轮廓
opencv中函数findContours函数

findContours(二值化图像,轮廓,hierarchy,轮廓检索模式,轮廓近似办法,offset

灰度重心法
利用灰度重心法计算中心,灰度重心法将区域内每一像素位置处的灰度值当做该点的“质量”,其求区域中心的公式为:
这里写图片描述
这里写图片描述
其中,f(u,v)是坐标为(u,v)的像素点的灰度值, 是目标区域集合, 是区域中心坐标,灰度重心法提取的是区域的能量中心。

//otsu算法实现函数
int Otsu(Mat &image)
{
    int width = image.cols;
    int height = image.rows;
    int x = 0, y = 0;
    int pixelCount[256];
    float pixelPro[256];
    int i, j, pixelSum = width * height, threshold = 0;

    uchar* data = (uchar*)image.data;

    //初始化  
    for (i = 0; i < 256; i++)
    {
        pixelCount[i] = 0;
        pixelPro[i] = 0;
    }

    //统计灰度级中每个像素在整幅图像中的个数  
    for (i = y; i < height; i++)
    {
        for (j = x; j<width; j++)
        {
            pixelCount[data[i * image.step + j]]++;
        }
    }


    //计算每个像素在整幅图像中的比例  
    for (i = 0; i < 256; i++)
    {
        pixelPro[i] = (float)(pixelCount[i]) / (float)(pixelSum);
    }

    //经典ostu算法,得到前景和背景的分割  
    //遍历灰度级[0,255],计算出方差最大的灰度值,为最佳阈值  
    float w0, w1, u0tmp, u1tmp, u0, u1, u, deltaTmp, deltaMax = 0;
    for (i = 0; i < 256; i++)
    {
        w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;

        for (j = 0; j < 256; j++)
        {
            if (j <= i) //背景部分  
            {
                //以i为阈值分类,第一类总的概率  
                w0 += pixelPro[j];
                u0tmp += j * pixelPro[j];
            }
            else       //前景部分  
            {
                //以i为阈值分类,第二类总的概率  
                w1 += pixelPro[j];
                u1tmp += j * pixelPro[j];
            }
        }

        u0 = u0tmp / w0;        //第一类的平均灰度  
        u1 = u1tmp / w1;        //第二类的平均灰度  
        u = u0tmp + u1tmp;      //整幅图像的平均灰度  
                                //计算类间方差  
        deltaTmp = w0 * (u0 - u)*(u0 - u) + w1 * (u1 - u)*(u1 - u);
        //找出最大类间方差以及对应的阈值  
        if (deltaTmp > deltaMax)
        {
            deltaMax = deltaTmp;
            threshold = i;
        }
    }
    //返回最佳阈值;  
    return threshold;
}

int main()
{
    Mat White=imread("white.tif");//读取图像
    int threshold_white = otsu(White);//阈值计算,利用otsu
    cout << "最佳阈值:" << threshold_white << endl;
    Mat thresholded = Mat::zeros(White.size(), White.type());
    threshold(White, thresholded, threshold_white, 255, CV_THRESH_BINARY);//二值化
    vector<vector<Point>>contours;
    vector<Vec4i>hierarchy;
    findContours(thresholded, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);//查找轮廓

    int i = 0;
    int count = 0;
    Point pt[10];//假设有三个连通区域
    Moments moment;//矩
    vector<Point>Center;//创建一个向量保存重心坐标
    for (; i >= 0; i = hierarchy[i][0])//读取每一个轮廓求取重心
    {
        Mat temp(contours.at(i));
        Scalar color(0, 0, 255);
        moment = moments(temp, false);
        if (moment.m00 != 0)//除数不能为0
        {
            pt[i].x = cvRound(moment.m10 / moment.m00);//计算重心横坐标
            pt[i].y = cvRound(moment.m01 / moment.m00);//计算重心纵坐标

        }
            Point p = Point(pt[i].x, pt[i].y);//重心坐标
            circle(White, p, 1, color, 1, 8);//原图画出重心坐标
            count++;//重心点数或者是连通区域数
            Center.push_back(p);//将重心坐标保存到Center向量中
        }
    }
    cout << "重心点个数:" << Center.size() << endl;
    cout << "轮廓数量:" << contours.size() << endl;
    imwrite("Center.tif", White);
}

原图:

这里写图片描述

二值化:

这里写图片描述

重心点:

这里写图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Opencv求取连通区域重心 的相关文章

随机推荐

  • VS调试技巧

    下面有从浅入深的6个问题 您可以尝试回答一下 一个如下的语句for int i 0 i lt 10 i if i 5 j 5 什么都写在一行 你怎么在j 5前面插入断点 在一个1000次的循环体内部设置断点 你希望当循环进行到900次后中断
  • TeamViewer介绍:远程控制计算机

    TeamViewer是一个可以远程控制计算机的程序 它也可以进行远程文件传输 TeamViewer支持的平台比较多 如Windows Mac Linux ChromeOs Android iOS等 最新发布版本为14 x 它有个人免费和商业
  • Linux系统管理(七)——用户文件权限设置

    系列文章往期回顾 Linux系统管理 一 Linux虚拟机在VMware上的安装 Linux系统管理 二 VMware使用文件共享功能 Linux系统管理 三 Shell以及基本命令 Linux系统管理 四 Shell编程资料分享以及示例演
  • vue3路由二次跳转后echarts不显示需要重新刷新才能显示

    第一次进进入这个页面正常页面数据都显示 再次进入路由后 echarts不显示 并且报警告 There is a chart instance already initialized on the dom dom上已经初始化了一个图表实例 通
  • 20220610 C++的析构函数返回值?

    起始 今天想到一个问题 析构函数明明没有返回值 为什么实例化一个类的时候 又可以用指针访问呢 经过一番查找 得出 其实是new关键字的作用 原文如下 参考内容 https blog csdn net raoqiang19911215 art
  • 物联网技术标准

    3GPP是什么 为了解决各国2G蜂窝通信系统互不兼容的问题 各国通信标准化组织在1998年12月成立了3GPP 最初成立的目标是实现由2G网络到3G网络的平滑过渡 保证未来技术的后向兼容性 支持系统间的漫游 现在3GPP已经发展成为最具权威
  • redis安装问题

    环境 centos7 redis 5 0 解决方案仅供参考 如不能解决问题 请查找请他方案 1 不能编译没有GCC 编译工具 make报错 make 1 persist settings Error 2 ignored CC adlist
  • 让你的Win 10更好用(scoop wt oh-my-posh carnac)

    前言 之前我讲过一篇如何使得自己的Linux子系统或者服务器的命令行变得更加美观 今天主要讲几个工具来让你的Windows变得更加强大 Scoop window的包管理工具中 scoop其实只是个后起之秀 我们可能熟知的有chocolaty
  • 网络基础学习----交换机,VLAN之间通信,链路聚合,路由器,协议等

    一 知识点总结 1 交换机 原理 交换机有一张Mac地址表 当收到一个数据帧的时候会识别MAC地址并查找Mac地址表中对应的接口进行转发 MAC地址表具有自动学习的功能 二层交换机 三层交换机 二层交换机没有路由功能 三层交换机可以具有部分
  • 530、我的CSDN创作纪念日 - 2022.04.23(河南 郑州)

    机缘 我是2018年04月20号开启的CSDN博客创作之旅的 至今已坚持4年的写作 共创作536篇文章 我的第一篇文章是记录我个人学习Python的心得体会 后面又记录了前端 Java 数据库 扫码点餐系统等一系列的自我学习的文章 这其中学
  • 论文笔记:基于手机基站数据的混合地图匹配算法研究

    2014 交通运输系统工程与信息 本文提出混合地图匹配算法 通过对车载手机行驶在不同的路网时所产生的基站切换数据信息 进行地图匹配 1 混合地图匹配算法 1 1 基站切换 数据库 1 1 1 基站切换 手机注册到通信网络后 随着 车辆的移动
  • 【BTC】数据结构

    BTC 中对交易数据的存储主要涉及到了两种数据结构 一种是区块链 一种是 Merkle Tree 这两种数据结构组成了 BTC 中完整的区块链结构 如下图所示 共同完成对数据的存储和验证 确保交易的有效性 一 区块链 所谓的区块链是由一个个
  • CO_XT_COMPONENT_CHANGE 修改工单组件行

    DATA is order key TYPE coxt ord key is order component key TYPE coxt s ord comp key l mode TYPE char1 VALUE A DATA wa re
  • win10麦克风无法使用,视频连线时对方听不到我的声音——解决办法

    问题描述 晚上用笔记本微信视频 发现无论是连耳机还是用系统麦克风 对方都无法收到我的声音 打开 win10 内置语音录音机录音依旧无法拾音 解决方案 首先 判断是不是隐私问题 允许使用麦克风要确保打开 设置 隐私 麦克风 其次 电脑右下角声
  • 最好的浏览器排行榜_趣享3个极简App关于浏览器-二次元-护眼

    Hello大家好 我是知雨 上一次给大家分享了3个高质量的App关于 高效背单词 墨墨背单词 时间管理 简黑时钟 实用工具箱App 自己也尝试用了一下 记住了好多单词 有效率给自己时间规划管理还有内置的几百款实用的小工具实用工具箱 他们真的
  • WDK学习笔记_Python操作MySql+Pytorch的LSTM使用

    文章目录 摘要 一 Mysql 项目 1 1 数据库基本操作 1 2 数据库的增删查改 1 3 Python操作MySql数据库 二 Pytorch的nn LSTM层 深度学习 2 1 nn RNN层 2 2 nn LSTM层 摘要 项目
  • Windows 在VMware16.x安装Win11系统详细教程

    文章目录 一 准备 二 创建虚拟机 1 创建新的虚拟机 2 选择虚拟机硬件兼容性 3 安装客户机操作系统 4 选择客户机操作系统 5 命名虚拟机 6 固件类型 7 处理器配置 8 此虚拟机内存 9 网络类型 10 选择I O控制器类型 11
  • 基于MVC架构访问数据库写一个登录系统

    题目 在C 中基于MVC架构写一个通过网页输入账号名密码 访问数据库 如果存在则创建该用户的系统 先完成基本功能 再往上加注册 返回数据库数据 文件处理等内容 这不是一个成熟项目 而是通过学习不断更新 并记录自己的思路 环境 Visual
  • 常见的APM(Application Performance Management应用性能管理)

    我也来对比下pinpoint和skyWalking 主流开源APM Zipkin Pinpoint SkyWalking全面对比 常见APM技术选型
  • Opencv求取连通区域重心

    我们有时候需要求取某一个物体重心 这里一般将图像二值化 得出该物体的轮廓 然后根据灰度重心法 计算出每一个物体的中心 步骤如下 1 合适的阈值二值化 2 求取轮廓 3 计算重心 otsu算法求取最佳阈值 otsu法 最大类间方差法 有时也称