图像处理之三角法图像二值化

2023-10-29

图像处理之三角法图像二值化

三角法求阈值最早见于Zack的论文《Automatic measurement of sister chromatid exchange frequency》主要是用于染色体的研究,该方法是使用直方图数据,基于纯几何方法来寻找最佳阈值,它的成立条件是假设直方图最大波峰在靠近最亮的一侧,然后通过三角形求得最大直线距离,根据最大直线距离对应的直方图灰度等级即为分割阈值,图示如下:
这里写图片描述
对上图的详细解释:
在直方图上从最高峰处bmx到最暗对应直方图bmin(p=0)%构造一条直线,从bmin处开始计算每个对应的直方图b到直线的垂直距离,知道bmax为止,其中最大距离对应的直方图位置即为图像二值化对应的阈值T。

扩展情况:
有时候最大波峰对应位置不在直方图最亮一侧,而在暗的一侧,这样就需要翻转直方图,翻转之后求得值,用255减去即得到为阈值T。扩展情况的直方图表示如下:
这里写图片描述

二:算法步骤
1. 图像转灰度
2. 计算图像灰度直方图
3. 寻找直方图中两侧边界
4. 寻找直方图最大值
5. 检测是否最大波峰在亮的一侧,否则翻转
6. 计算阈值得到阈值T,如果翻转则255-T

三:代码实现

package com.gloomyfish.filter.study;

import java.awt.image.BufferedImage;

public class TriangleBinaryFilter extends AbstractBufferedImageOp{

    public TriangleBinaryFilter() {
        System.out.println("triangle binary filter");
    }

    @Override
    public BufferedImage filter(BufferedImage src, BufferedImage dest) {
        int width = src.getWidth();
        int height = src.getHeight();

        if ( dest == null )
            dest = createCompatibleDestImage( src, null );
        // 图像灰度化
        int[] inPixels = new int[width*height];
        int[] outPixels = new int[width*height];
        getRGB( src, 0, 0, width, height, inPixels );
        int index = 0;
        for(int row=0; row<height; row++) {
            int ta = 0, tr = 0, tg = 0, tb = 0;
            for(int col=0; col<width; col++) {
                index = row * width + col;
                ta = (inPixels[index] >> 24) & 0xff;
                tr = (inPixels[index] >> 16) & 0xff;
                tg = (inPixels[index] >> 8) & 0xff;
                tb = inPixels[index] & 0xff;
                int gray= (int)(0.299 *tr + 0.587*tg + 0.114*tb);
                inPixels[index]  = (ta << 24) | (gray << 16) | (gray << 8) | gray;
            }
        }
        // 获取直方图
        int[] histogram = new int[256];
        for(int row=0; row<height; row++) {
            int tr = 0;
            for(int col=0; col<width; col++) {
                index = row * width + col;
                tr = (inPixels[index] >> 16) & 0xff;
                histogram[tr]++;
            }
        }


        int left_bound = 0, right_bound = 0, max_ind = 0, max = 0;
        int temp;
        boolean isflipped = false;
        int i=0, j=0;
        int N = 256;

        // 找到最左边零的位置
        for( i = 0; i < N; i++ )
        {
            if( histogram[i] > 0 )
            {
                left_bound = i;
                break;
            }
        }
     // 位置再移动一个步长,即为最左侧零位置 
        if( left_bound > 0 )
            left_bound--;

        // 找到最右边零点位置
        for( i = N-1; i > 0; i-- )
        {
            if( histogram[i] > 0 )
            {
                right_bound = i;
                break;
            }
        }
        // 位置再移动一个步长,即为最右侧零位置 
        if( right_bound < N-1 )
            right_bound++;

        // 在直方图上寻找最亮的点Hmax
        for( i = 0; i < N; i++ )
        {
            if( histogram[i] > max)
            {
                max = histogram[i];
                max_ind = i;
            }
        }

        // 如果最大值落在靠左侧这样就无法满足三角法求阈值,所以要检测是否最大值是否靠近左侧
        // 如果靠近左侧则通过翻转到右侧位置。
        if( max_ind-left_bound < right_bound-max_ind)
        {
            isflipped = true;
            i = 0;
            j = N-1;
            while( i < j )
            {
                // 左右交换
                temp = histogram[i]; histogram[i] = histogram[j]; histogram[j] = temp;
                i++; j--;
            }
            left_bound = N-1-right_bound;
            max_ind = N-1-max_ind;
        }

        // 计算求得阈值
        double thresh = left_bound;
        double a, b, dist = 0, tempdist;
        a = max; b = left_bound-max_ind;
        for( i = left_bound+1; i <= max_ind; i++ )
        {
            // 计算距离 - 不需要真正计算
            tempdist = a*i + b*histogram[i];
            if( tempdist > dist)
            {
                dist = tempdist;
                thresh = i;
            }
        }
        thresh--;

        // 对已经得到的阈值T,如果前面已经翻转了,则阈值要用255-T
        if( isflipped )
            thresh = N-1-thresh;

        // 二值化
        System.out.println("final threshold value : " + thresh);
        for(int row=0; row<height; row++) {
            for(int col=0; col<width; col++) {
                index = row * width + col;
                int gray = (inPixels[index] >> 8) & 0xff;
                if(gray > thresh)
                {
                    gray = 255;
                    outPixels[index]  = (0xff << 24) | (gray << 16) | (gray << 8) | gray;
                }
                else
                {
                    gray = 0;
                    outPixels[index]  = (0xff << 24) | (gray << 16) | (gray << 8) | gray;
                }

            }
        }


        // 返回二值图像
        setRGB(dest, 0, 0, width, height, outPixels );
        return dest;
    }

}

四:运行结果
这里写图片描述

2016年最后一篇,这里祝大家元旦快乐,欢迎在2017继续关注本博客,分享有用实用的图像处理知识本人会一直坚持到永远!
学习图像处理基础入门课程 - 点击这里

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

图像处理之三角法图像二值化 的相关文章

随机推荐

  • java中文转unicode码

    http open weibo com wiki index php Location get addr转载地址 http www iteye com topic 471901 http blog csdn net zhengjianqi
  • Ubuntu20.0.0安装docker容器

    一 Docker介绍 Docker 是一个开源的应用容器引擎 基于 Go 语言 并遵从 Apache2 0 协议开源 Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级 可移植的容器中 然后发布到任何流行的 Linux 机器上
  • 用友出纳通服务器修改系统日期,用友T3软件出纳通里面如何修改账户的建账日...

    用友T3软件出纳通里面如何修改账户的建账日以下文字资料是由 历史新知网www lishixinzhi com 小编为大家搜集整理后发布的内容 让我们赶快一起来看一下吧 用友T3软件出纳通里面如何修改账户的建账日 启用之后就无法修改了 除非你
  • 大众点评数据

    数据名称 大众点评POI数据 数据年份 2022最新版 数据量 4000w 数据范围 全国范围 数据变量 id 店铺id 店铺名称 店铺位置 店铺区县 店铺商圈 小类 大类 城市id 城市名 是否外卖 均价 人气 分数 星级 状态 电话 位
  • CMake + VTK

    编译VTK本身没有太多的坑 我使用的是VS2015 x64 Native Tools Command Prompt 基本上就是典型的 cmake G Visual Studio 14 Win64 即可 使用编译后的结果时主要是要注意VTK
  • 数据库入门书籍推荐

    数据库入门书籍推荐 书籍书籍 数据库系统概论 内容简介 数据库理论入门必读 本书系统全面的阐述了数据库系统的基础理论 基本技术和基本方法 我国第一部系统阐述数据库原理 技术和方法的教材 适时反映数据库领域的新成果和应用新方向 内容丰富 概念
  • QLineEdit的信号与槽用法

    QLineEdit一共有6个信号函数 并不多 很好理解 1 void cursorPositionChanged intold intnew 当鼠标移动时发出此信号 old为先前的位置 new为新位置 在文本框中输入一个字符 光标移动一格
  • 封神台靶场-第四章

    第四章 为了更多的权限 Tips 1 存储型Xss 2 flag在cookie里 格式为zkz xss bot 每10秒访问一次页面 3 自建Xss平台源码 http www zkaq org t 99 html 登陆后根据提示要进行存储型
  • 程序性能

    文章目录 1 程序性能 1 1 空间效率 1 2 时间效率 1 3 f n 程序性能表示 程序性能包括两个部分 空间效率和时间效率 1 程序性能 1 1 空间效率 一个运行的程序所占用的内存 1 栈 函数调用时操作系统自动分配的内存 函数调
  • commitlint配置

    聊一下如何配置commit lint 其实这个问题一直困扰我很久 看了好多文章 都无济于事今天狠下心来终于解决 废话不多说 先上代码 最后阐述原因 因为有的小伙伴就是想找到解决问题办法 至于原因不太关心 注意 npm 版本大于 7 安装 h
  • 网站服务器被攻击的形式,服务器被攻击的不同表现类型以及应对策略

    服务器被攻击的不同表现类型以及应对策略 许多网站站长都遇到过网络服务器被攻击的状况 被攻击之后也大多数都只有束手待毙 由于大伙儿广泛对攻击不足掌握 很多人把多很多的攻击和防御力挂在嘴上 却压根不清楚网络服务器是怎么被攻击的 更不要说怎样应对
  • MyBatis-Plus-自定义模板-生成代码

    MyBatis Plus代码生成器所需jar包
  • windows无法访问FTP服务器的各种报错解决

    本文转载自windows无法访问FTP服务器的各种报错解决 对于windows无法访问FTP服务 原因有很多 但首先要保证 你的服务配置无误 用户有访问资源的权限 防火墙拦截 服务器防火墙通行了 忽略了客户端的防火墙可不行 对于不信任的连接
  • special effects - 樱花飘落背景特效

    樱花飘落背景特效 一 效果图 二 实现代码 一 效果图 二 实现代码
  • VPS是虚拟专用服务器,部署VPS包括以下步骤

    VPS是虚拟专用服务器 部署VPS包括以下步骤 购买VPS主机 选择可靠的云服务提供商 如亚马逊AWS 谷歌云 腾讯云或阿里云 并注册账户和创建VPS实例 为了确保您的应用程序在运行过程中具有快速的性能和可靠的服务级别协议 请评估不同主机计
  • Intel TBB简介及在Windows7 VS2013上源码的编译过程

    Intel TBB Intel Threading Building Blocks 是Intel线程构建块开源库 它的License是Apache 2 0 Intel TBB是一种用于并行编程的基于C 语言的框架 它是一套C 模板库 它提供
  • 【http协议】超详细介绍

    文章目录 一 协议 1 1 Method 1 1 1 HEAD 1 2 Status 1 3 Http Head Http 头 1 3 1 Http Request Body 1 3 1 1 Content Type 1 3 1 2 miu
  • 浅谈Web用户体验(二)

    在所有网页或浏览器的GUI中我最喜欢的是google的用户体验效果 平时我们只把它作为搜索工具 从没仔细欣赏过它的设计细节 有篇博客对google的用户体验总结的非常好 google的设计一向以简单著称 让页面清爽优雅地呈现 一方面减少页面
  • Notepad++找回缓存的内容

    场景 在使用Notepad 的时候 有一个非常方便的自动保存功能 也就是你在新建一个文档后 输入你的内容 在你没有手动保存前 Notepad 会帮你保存当前内容 当你没有保存就退出Notepad 下次进来Notepad 会自动把你上次编辑的
  • 图像处理之三角法图像二值化

    图像处理之三角法图像二值化 三角法求阈值最早见于Zack的论文 Automatic measurement of sister chromatid exchange frequency 主要是用于染色体的研究 该方法是使用直方图数据 基于纯