OpenCV - 均值迭代分割

2023-05-16

【题外话】:之前在博客中写过一篇“区域生长”的博客,区域生长在平时经常用到,也比较容易理解和代码实现,所以在很多情况下大家会选择这种方法。但是区域生长有一个最致命的点就是需要选取一个生长的种子点。
为了交流学习,同时也为了后面查阅方便,准备陆续将基于直方图的几种分割算法加以总结。

1、均值迭代算法的描述

对一幅图像 M ,均值迭代算法就是要迭代计算得到一个灰度值T,使得这个灰度值 T 将图像分成的两类A,B。满足条件: A 类的均值和B类的均值,再求均值正好等于 T
用直方图可以很直观的描述:

这里写图片描述

图示表示某个图像的灰度直方图,均值迭代就是为找到一个T,使得 T 左侧的积分面积中均值T1和右侧积分面的均值 T2 相等。

2、算法的步骤

  1. 选择一个初始化阈值 T ,通常取整张图灰度值的平均值;
  2. 计算T分成的两个部分的灰度均值 u1 u2
  3. 更新 Tu1+u2/2
  4. 重复步骤2~3,直到相邻两次计算的结果相等,或者两次结果的差值小于预先设定的值某个值;
  5. 用这个 T 对图像进行分割。

3、OpenCV下的实现

//Mat src: 待分割灰度图像
//int n:   初始阈值
void IsodataSeg(Mat &src, int n)
{
    int threshold = 0;                          //历史阈值
    int MeansO = 0;                             //前景灰度均值
    int nObject = 0;                            //实质像素点个数
    int MeansB = 0;                             //背景灰度均值
    int nBack = 0;                              //背景像素点个数
    int nCol = src.cols * src.channels();       //每行的像素个数
    while (abs(threshold - n) > 10)             //迭代停止条件
    {
        threshold = n;
        for (int i=0; i<src.rows; ++i)
        {
            uchar* pData = src.ptr<uchar>(i);
            for (int j=0; j<nCol; ++j)
            {
                if (pData[j] < threshold)   //背景
                {
                    ++nBack;
                    MeansB += pData[j];
                }
                else                        //物体
                {
                    ++nObject;
                    MeansO += pData[j];
                }
            }
        }
        if (nBack == 0 || nObject == 0)     //防止出现除以0的计算
            continue;
        n = (MeansB/nBack + MeansO/nObject) / 2;
    }
    cv::threshold(src, src, n, 255, 0);     //进行阈值分割
}

4、进一步探究

在实际的应用中常常会发现一幅图像中,我们真正想去分割的并不是整个的矩形。比如下面的图:


这里写图片描述

假设我们想要将整个奇怪的人的眼睛,嘴巴和他们脸分开,而并不关心整个图的背景部分。(当然有很多种方法可以直接去掉黑色的背景,现在仅仅讨论整个图)在算法的思路中我们可以看到,我们统计的是整个图的像素,试想如果我们不去统计哪些我们已经知道是背景颜色的像素点,那么整个问题不就转化成了我们已经能解决的问题了么?!
所以,我们仅仅在代码的实现中讲哪些我们已知是不要统计的颜色排除在外就可以了。
这里我们假定背景是纯黑的(像素值为0)。这样上述代码仅仅需要作很小的改动就能满足应用的要求了。

void IsodataSeg(Mat &src, int n)
{
    int threshold = 0;                          //历史阈值
    int MeansO = 0;                             //前景灰度均值
    int nObject = 0;                            //实质像素点个数
    int MeansB = 0;                             //背景灰度均值
    int nBack = 0;                              //背景像素点个数
    int nCol = src.cols * src.channels();       //每行的像素个数

    while (abs(threshold - n) > 10)             //迭代停止条件
    {
        threshold = n;
        for (int i=0; i<src.rows; ++i)
        {
            uchar* pData = src.ptr<uchar>(i);
            for (int j=0; j<nCol; ++j)
            {
                //黑色区域为多余的像素,不参与计算
                if (pData[j] == 0)
                    continue;

                if (pData[j] < threshold)   //背景
                {
                    ++nBack;
                    MeansB += pData[j];
                }
                else                        //物体
                {
                    ++nObject;
                    MeansO += pData[j];
                }
            }
        }
        if (nBack == 0 || nObject == 0)
            continue;
        n = (MeansB/nBack + MeansO/nObject) / 2;
    }
    cv::threshold(src, src, n, 255, 0);                             //进行阈值分割
}

5、均值迭代在哪好用

从算法的描述步骤中可以看到,均值迭代算法的收敛速度是很快的。也就意味了在合适的场景下,使用均值迭代算法是具有绝对优势的。但是也需要注意一点均值迭代一般比较使用直方图为典型的“双峰”的图像。这一特征也是基于直方图统计类算法的共同特征。
可以体会到均值迭代算法其实是一种简单的聚类,它每次将样本分成两类,两类的均值作为两类的聚类中心,每一次计算的 T 与两类均值的距离为聚类的半径。

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

OpenCV - 均值迭代分割 的相关文章

  • VIm自动生成python的文件头

    VIm自动生成python的文件头 我实现的效果如图所示 xff1a 思路是在vimrc配置文件中写相关的函数 xff0c 代码在下面贴出 按 wq保存退出以后 xff0c 会自动更新上次修改时间 34 新建py文件时插入文件头 autoc
  • 使用Dokcer配置Tensorflow-1.15环境并使用VSCode开发

    使用Dokcer配置Tensorflow 1 15环境 目前学术界大部分深度学习的开源代码都是基于Pytorch的 xff0c 但还有少部分工作或者以前的工作是基于Tensorflow 1 x的 xff0c 由于tensorflow的版本和
  • 使用VNC可视化Docker容器

    使用VNC可视化Docker容器 0 前言环境 xff1a 1 容器端配置1 1 启动Docker容器1 2 安装x111 3 安装桌面环境1 4 安装tightvncserver 2 配置VNC Server2 1 首先停止刚刚新建的虚拟
  • STM32 串口ISP下载方式解读

    xfeff xfeff http blog sina com cn s blog b09739ab0102v4rm html Flash Loader Demonstrator 下 载工具的安装 1 xff0e 硬件的连接和设置 串口ISP
  • with异常处理

    class A 39 39 39 此类的对象可以用 xff57 xff49 xff54 xff48 语句进行管理 39 39 39 def enter self print 34 已经进入with语句 34 return self def
  • telegram android 源码分析 (一)自动设置代理

    比如自动设置mtproxy代理 xff0c 冗长的代码我们怎么去找 xff1f 1 xff09 首先我们发现点代理链接能弹对话框 xff0c 们可以在strings xml中搜索得到 xff1a lt string name 61 34 U
  • NS3 的 ipv4-static-routing-test-suite 源码分析

    下面进行源码注释 xff1a End to end tests for Ipv4 static routing include 34 ns3 boolean h 34 include 34 ns3 config h 34 include 3
  • c语言向上取整计算方法

    用整数N 除以 M xff0c 要求向上取整数 1 xff09 int n 61 N 43 M 1 M xff1b 简化后就是 xff1a 2 xff09 int n 61 N 1 M 43 1 xff1b 最笨的办法 3 int n 61
  • 比std::qsort还快的快速排序(1千万整数1.7秒)——(快速排序栈溢出与递归优化)

    前几天发现老外的开源项目中事件队列中用的就是std qsort排序 xff0c 后续插入时候使用了堆方式 快速排序实际应用中是比堆排序要快的 xff0c 这主要是因为硬件层次会对数据执行高速缓存 xff0c 数据使用一二三级高速缓存比访问内
  • C#使用ProtoBuf

    1 Google ProtoBuf 经过测试 xff0c protobuf比json存储效率还是要高 xff0c 即时号称最快的fastjson也没有protobuf快 xff0c 这里为了使用 c 做一个客户端兼容 xff0c 所以也需要
  • 多线程如何实现高性能计数器(无锁)

    多线程协作免不了使用计数器 xff0c 通常的代码 xff0c c 43 43 一般会使用锁 xff0c 或者原子变量操作 xff1a std mutex mutexCounter int count void add std lock g
  • ubuntu18/20 下如何生成core文件

    ubuntu18 20 下如何生成core文件 一 设置 原理 xff1a https blog csdn net Sunnyside article details 118439302 原来在ubuntu14 ubuntu16上只需要一步
  • c++的字节序与符号位的问题

    看这样一道题 xff1a include lt stdio h gt int main void int w h int i 61 0xa1b2c3d4 char p 61 char amp i for int j 61 0 j lt 4
  • docker镜像之带vnc的ubuntu

    docker镜像 之 带vnc图形界面ubuntu 前言 xff1a 为了在图形界面中使用firefox xff0c 需要找一个带rdp或者vnc的ubuntu xff0c 最好是gnome的界面 xff0c 折腾了3天 xff0c 终于找
  • STM32中,关于中断函数调用全局变量的问题

    xfeff xfeff https blog csdn net leo liu006 article details 79334905 首先是问题的描述 xff1a 硬件单片机型号 xff0c STM32F103VET6 xff0c IDE
  • python使用selenium以及selenium-wire做质量与性能检测

    python天生就是适合用来做爬虫 xff0c 结合selenium真是如虎添翼 xff1b 1 安装库 pip install selenium pip install selenium wire 2 xff09 添加驱动 xff0c 比
  • 编写http workshop脚本从网页缓存里解析音乐

    前一篇文章 编写http workshop脚本从网站下载音乐 示范了如何使用HttpClient访问API 以及Json数据的解析 今天我们通过解析一个网页展示如何使用内置的LibXml2的功能解析HTML 提取我们关心的内容 这里随便搜了
  • pytorch环境搭建若干

    备注 xff1a 不要使用python3 11不支持 xff0c pip会说找不到合适的版本 xff1b python官网不提供旧版的下载了 xff0c 说是win7以后无法使用 xff0c 都是扯淡 xff0c 有其他地方可以下载pyth
  • ffmpeg常用方法

    FFmpeg 是一款开源的音视频处理工具 xff0c 可以处理各种格式的音视频文件 xff0c 并且可以进行格式转换 剪切 合并 添加水印等多种操作 下面是 FFmpeg 的一些常用命令及其用法 xff1a 视频转码 将一个视频文件转换为另
  • RFC2152 UTF-7 中文

    RFC2152 UTF 7 中文 翻译 xff1a 李静南 时间 xff1a 2006 03 29 EMAIL xff1a robin fox 64 sohu com 版权 xff1a 可以用于非商业用途自由转载 xff0c 但请保留本文档

随机推荐

  • 第九章0.4的CMakeLists.txt结构

    最开始看这一章的时候 xff0c 将CMakeLists txt部分跳过了 xff0c 没有看 后来看高博RGBD SLAM时候 xff0c 第一讲降到了cmake的用法 xff0c 发现有新的东西 xff0c 又回头看 xff1a 最原始
  • ROS 中setup.bash

    好久没写了 xff0c 最近搞了辆小车 xff0c 瞅了瞅ROS的相关内容 xff0c 没有写ROS的内容 xff0c 刚开始看 xff0c 写的话基本就成了书本粘贴 不过最近由ROS引出来的一些Linux相关的东西 xff0c 然后又回头
  • ros_hostname与ros_ip

    在ROS的环境变量中 xff0c 需要在 bashrc中设置的并不多 xff08 此处是指在wiki的基本教程中出现的 xff0c 大牛请无视 xff09 xff0c 大概只有三个 xff1a ROS MASTER URI ROS HOST
  • git图形化代码冲突处理

    当代码量少的时候使用 xff0c 使用vimdiff或者手动处理冲突 xff0c 都很方便 xff0c 但是当代码量大还是图形化处理更方便 xff0c 这里推荐使用kdiff3 首先下载kdiff3 xff0c 网上不好找的话 xff0c
  • Apache httpd 目录列表禁用配置(options indexes)

    Apache httpd服务器在缺省的情况下 xff0c 开启了基于目录列表的访问 xff0c 这是一个存在安全隐患的问题 xff0c 因此可以关闭这个功能 在Apache 2 4的版本中 xff0c 不在支持使用 indexes来配置 x
  • cmake学习笔记6-catkin的CmakeList.txt讲解

    https www jianshu com p 551d6949b49d 引用 cmake学习笔记 cmakelist txt创建项目示例 cmake的介绍和使用 Cmake实践 推荐cmake手册详解 严重推荐CMake构建系统的骨架 c
  • ROS中使用Intel RealSense D455或L515深度相机

    目的 在ROS平台上 xff0c 使用深度相机作为传感器设计自主避障机器人 1 安装驱动 测试环境 软件 xff1a Ubuntu 16 04 ROS Kinetic 硬件 xff1a Intel RealSense D455 或 L515
  • ROS机器人操作系统底层原理及代码剖析

    0 目的 本文介绍ROS机器人操作系统 xff08 Robot Operating System xff09 的实现原理 xff0c 从最底层分析ROS代码是如何实现的 1 序列化 把通信的内容 xff08 也就是消息message xff
  • RS232,RS485波形分析

    通过观察波形可以确定以下情况 xff1a 是否有数据接收或发送 xff1b 数据是否正确 xff1b 波特率是否正确 xff1b 一 串行数据的格式 异步串行数据的一般格式是 xff1a 起始位 43 数据位 43 停止位 xff0c 其中
  • GPU渲染管线之旅|05 图元处理、Clip/Cull, 投影和视图变换

    上一篇中我们讨论了关于 纹理和采样 xff0c 这一篇我们回到3D管线的前端 在执行完顶点着色之后 xff0c 就可以实际的渲染东西了 xff0c 对吗 xff1f 暂时还不行 xff0c 因为在我们实际开始光栅化图元之前 xff0c 仍然
  • 谈谈OpenCV中的四边形

    首先抛出一个问题 xff0c 给定一系列二维平面上的的点 xff0c 这些点是可以组成一个封闭的二维图形 因为这些点是矩形区域拍摄图像后识别得到的图形的边界点 xff0c 所以我们要抽象出来这个矩形 xff0c 也就是我们要反映出这个矩形
  • GPU渲染管线之旅|07 深度处理、模板处理

    在这一篇中 xff0c 我们来讨论Z pipline的前端部分 简称它为early Z 以及它是在光栅化中怎么起作用的 和上一篇一样 xff0c 本篇也不会按实际的管道顺序进行讨论 xff1b 我将首先描述基础算法 xff0c 然后再补充管
  • GPU渲染管线之旅|08 Pixel Shader

    在这一部分中 xff0c 我们来谈谈像素处理的前半部分 dispatch和实际的像素着色 事实上 xff0c 这部分是大多数图形开发者在谈到PS stage时所关心的内容 有关alpha blend和Late Z的内容则会下一篇文章中去探讨
  • MFC基于CSplitterWnd类的多窗口分割

    使用平台 xff1a win7 64bit 使用环境 xff1a VS2012 1 CSplitterWnd介绍 上图是从MSDN中截取的类的继承图表 xff0c CSplitterWnd类继承自CWnd类 这个类主要就是提供窗口分割的功能
  • OpenCV - 区域生长算法

    1 理论基础 区域生长算法的基本思想是将有相似性质的像素点合并到一起 对每一个区域要先指定一个种子点作为生长的起点 xff0c 然后将种子点周围领域的像素点和种子点进行对比 xff0c 将具有相似性质的点合并起来继续向外生长 xff0c 直
  • 不规则Contours内部像素的操作

    在findContours函数使用了之后 xff0c 有时候就会面临对Contours内部区域的访问 由于contours不一定是凸图形 xff0c 所以使用循环操作的时候总感觉不那么方便 比如在下图中 xff0c 已经使用findCont
  • ros代码中添加使用opencv库,cv::Mat和ros image之间的相互转换

    https blog csdn net sunyoop article details 78630024 ros中很多时候要用到图形处理 xff0c 这时就需要使用opencv库 xff0c 本篇主要将怎么在ros现成node上使用open
  • Ubuntu 16.04 使用

    这篇博客用来专门记录尝试搬迁工作环境到Linux下的使用笔记 xff0c 主要包含有常用软件的安装 xff0c 配置 1 安装输入法 ubuntu 16 04中支持ibus输入系统 1 系统 gt 首选项 gt IBus设置 在弹出的IBu
  • 牛顿迭代法求解方程

    说明 xff1a 该篇博客源于博主的早些时候的一个csdn博客中的一篇 xff0c 由于近期使用到了 xff0c 所以再次作一总结 原文地址 概述 牛顿迭代法 xff08 Newton s method xff09 又称为牛顿 拉夫逊 xf
  • OpenCV - 均值迭代分割

    题外话 之前在博客中写过一篇 区域生长 的博客 xff0c 区域生长在平时经常用到 xff0c 也比较容易理解和代码实现 xff0c 所以在很多情况下大家会选择这种方法 但是区域生长有一个最致命的点就是需要选取一个生长的种子点 为了交流学习