今天复习Otsu算法,它利用阈值奖图片转成黑白色。Otsu算法是二值算法,目的是求出一个Threshhold,来最小化Within-Class方差,这等价最大化between-class方差。下面用java来实现算法。

package com.lili.ots<pre name="code" class="java">package com.lili.otsu;
public class OtsuThresholder
{private int histData[];private int maxLevelValue;private int threshold;public OtsuThresholder(){histData = new int[256];}public int[] getHistData(){return histData;}public int getMaxLevelValue(){return maxLevelValue;}public int getThreshold(){return threshold;}public int doThreshold(byte[] srcData, byte[] monoData){int ptr;// Clear histogram data// Set all values to zeroptr = 0;while (ptr < histData.length) histData[ptr++] = 0;// Calculate histogram and find the level with the max value// Note: the max level value isn't required by the Otsu methodptr = 0;maxLevelValue = 0;while (ptr < srcData.length){int h = 0xFF & srcData[ptr];  histData[h] ++;if (histData[h] > maxLevelValue) maxLevelValue = histData[h];ptr ++;}// Total number of pixelsint total = srcData.length;                //48*57 image, total=48*57float sum = 0;for (int t=0 ; t<256 ; t++) sum += t * histData[t];float sumB = 0;int wB = 0;int wF = 0;float varMax = 0;threshold = 0;for (int t=0 ; t<256 ; t++){wB += histData[t];                 // Weight Background if (wB == 0) continue;   // 'cause divide           the number of pixle of backgroundwF = total - wB;                      // Weight Foregroundif (wF == 0) break;                sumB += (float) (t * histData[t]);float mB = sumB / wB;             // Mean Backgroundfloat mF = (sum - sumB) / wF;        // Mean Foreground// Calculate Between Class Variancefloat varBetween = (float)wB * (float)wF * (mB - mF) * (mB - mF); // Check if new maximum foundif (varBetween > varMax) {varMax = varBetween;threshold = t;}}// Apply threshold to create binary imageif (monoData != null){ptr = 0;while (ptr < srcData.length)            // 48*57{monoData[ptr] = ((0xFF & srcData[ptr]) >= threshold) ? (byte) 255 : 0;ptr ++;}}return threshold;}
}
package com.lili.otsu;import java.io.*;import java.util.*;
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;import com.lili.otsu.GreyFrame;
import com.lili.otsu.OtsuThresholder;public class OtsuDemo
{public OtsuDemo(String filename){// Load Source imageBufferedImage srcImage = null;try{File imgFile = new File(filename);srcImage = javax.imageio.ImageIO.read(imgFile);}catch (IOException ioE){System.err.println(ioE);System.exit(1);}int width = srcImage.getWidth();int height = srcImage.getHeight();// Get raw image dataRaster raster = srcImage.getData();DataBuffer buffer = raster.getDataBuffer();int type = buffer.getDataType();if (type != DataBuffer.TYPE_BYTE){System.err.println("Wrong image data type");System.exit(1);}if (buffer.getNumBanks() != 1){System.err.println("Wrong image data format");System.exit(1);}DataBufferByte byteBuffer = (DataBufferByte) buffer;byte[] srcData = byteBuffer.getData(0);// Sanity check imageif (width * height  != srcData.length) {System.err.println("Unexpected image data size. Should be greyscale image");System.exit(1);}// Output Image infoSystem.out.printf("Loaded image: '%s', width: %d, height: %d, num bytes: %d\n", filename, width, height, srcData.length);byte[] dstData = new byte[srcData.length];// Create Otsu ThresholderOtsuThresholder thresholder = new OtsuThresholder();int threshold = thresholder.doThreshold(srcData, dstData);System.out.printf("Threshold: %d\n", threshold);// Create GUIGreyFrame srcFrame = new GreyFrame(width, height, srcData);GreyFrame dstFrame = new GreyFrame(width, height, dstData);GreyFrame histFrame = createHistogramFrame(thresholder);JPanel infoPanel = new JPanel();infoPanel.add(histFrame);JPanel panel = new JPanel(new BorderLayout(5, 5));panel.setBorder(new javax.swing.border.EmptyBorder(5, 5, 5, 5));panel.add(infoPanel, BorderLayout.NORTH);panel.add(srcFrame, BorderLayout.WEST);panel.add(dstFrame, BorderLayout.EAST);panel.add(new JLabel("QingrouShui", JLabel.CENTER), BorderLayout.SOUTH);JFrame frame = new JFrame("QingrouShui");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.getContentPane().add(panel);frame.pack();frame.setVisible(true);// Save Imagestry{int dotPos = filename.lastIndexOf(".");String basename = filename.substring(0,dotPos);javax.imageio.ImageIO.write(dstFrame.getBufferImage(), "PNG", new File(basename+"_BW.png"));javax.imageio.ImageIO.write(histFrame.getBufferImage(), "PNG", new File(basename+"_hist.png"));}catch (IOException ioE){System.err.println("Could not write image " + filename);}}private GreyFrame createHistogramFrame(OtsuThresholder thresholder){int numPixels = 256 * 100;byte[] histPlotData = new byte[numPixels];int[] histData = thresholder.getHistData();int max = thresholder.getMaxLevelValue();int threshold = thresholder.getThreshold();for (int l=0 ; l<256 ; l++){int ptr = (numPixels - 256) + l;int val = (100 * histData[l]) / max;if (l == threshold){for (int i=0 ; i<100 ; i++, ptr-=256) histPlotData[ptr] = (byte) 128;}else{for (int i=0 ; i<100 ; i++, ptr-=256) histPlotData[ptr] = (val < i) ? (byte) 255 : 0;}}return new GreyFrame(256, 100, histPlotData);}public static void main(String args[]){new OtsuDemo("lili_icmv12.png");System.out.println("QingrouShui");
//      if (args.length<1) {
//          System.err.println("Provide image filename");
//          System.exit(1);
//      }}
}
<pre name="code" class="java">package com.lili.otsu;
import java.awt.*;import javax.swing.*;
import java.awt.image.*;
import java.awt.color.*;public class GreyFrame extends JComponent
{private int width;private int height;private Dimension size;private BufferedImage image;private String title;public GreyFrame(int width, int height, byte[] data){this(width, height, data, null);}public GreyFrame(int width, int height, byte[] data, String title){this.width = width;this.height = height;this.title = title;size = new Dimension(width, height);DataBufferByte dataBuffer = new DataBufferByte(data, data.length, 0);PixelInterleavedSampleModel sampleModel = new PixelInterleavedSampleModel(DataBuffer.TYPE_BYTE, width, height, 1, width, new int[] {0});ColorSpace colourSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);ComponentColorModel colourModel = new ComponentColorModel(colourSpace, new int[] {8}, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);WritableRaster raster = Raster.createWritableRaster(sampleModel, dataBuffer, null);image = new BufferedImage(colourModel, raster, false, null);}public Graphics2D getBufferImageGraphics(){return image.createGraphics();}public BufferedImage getBufferImage(){return image;}public Dimension getSize(){return size;}public Dimension getPreferredSize(){return size;}public void paint(Graphics g){super.paint(g);if (image != null) g.drawImage(image, 0, 0, this);if (title != null) {g.setColor(Color.RED);g.drawString(title, 5, height - 5);}}
}

<img src="https://img-blog.csdn.net/20150401123028357" alt="" /><img src="https://img-blog.csdn.net/20150401123001341" alt="" />

Otsu Thresholding相关推荐

  1. C#,图像二值化(06)——全局阈值的大津算法(OTSU Thresholding)及其源代码

    1.大津算法OTSU ALGORITHM OTSU算法效果很一般. 最大类间方差法是1979年由日本学者大津(Nobuyuki Otsu)提出的,是一种自适应阈值确定的方法,又叫大津法,简称OTSU, ...

  2. Image Thresholding

    摘自https://docs.opencv.org/4.2.0/d7/d4d/tutorial_py_thresholding.html Simple Thresholding The functio ...

  3. 训练过程出现trian_dice一直大于1(mask范围0-255转为0-1)

    文章目录 0. 背景知识 0.1 mask 0.2 SimpleITK快速入门 1. 使用Threshold类方法 1.1 sitk.RescaleIntensityImageFilter 1.1.1 ...

  4. python 椭圆检测_使用OpenCV和Python检测触摸/重叠圆/椭圆

    这是我检测圈子的尝试.综上所述 >执行BGR-> HSV转换,并使用V通道进行处理 V通道: >阈值,应用形态关闭,然后进行距离转换(我会称之为dist) 分区形象: >创建一 ...

  5. SimpleITK笔记本中ITK细分(Segmentation)介绍

    SimpleITK笔记本中ITK细分(Segmentation)介绍 目标:熟悉ITK中可用的基本分割算法,并以交互方式探索其参数空间. 图像分割滤波器处理图像,将其分割成(希望)有意义的区域.输出通 ...

  6. AnswerOpenCV(0826-0901)一周佳作欣赏

    1.OpenCV to detect how missing tooth in equipment Hello everyone. I am just starting with OpenCV and ...

  7. (病理图像质控)分割病理图像(whole slide images,WSI)中包含组织的区域,去掉空白区域

    文末有代码链接!!!!! 修改 2023-03-14 偷空写个帖子. 在处理全病理切片(WSI)的时候,经常会碰到一个问题.就是整个WSI很大,其中有很多空白的地方,深度学习或者传统的图像处理都不需要 ...

  8. 图像处理之二值化图像

    图像二值化就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果.将所有灰度大于或等于阈值的像素被判定为属于特定物体,其灰度值为255表示,否则这些像素点被排除在物体区域以 ...

  9. 人工智能——图像处理和Python深度学习的全教程(建议收藏)

    介绍 在这篇文章中,我们将学习如何执行图像处理.在整篇文章中,我们使用到的库是Scikit Image. 基础知识 1.什么是图像? 图像数据可能是文本之后最常见的数据.那么,电脑如何理解你在埃菲尔铁 ...

最新文章

  1. 算法笔记--数列分块
  2. 基于React-Native0.55.4的语音识别项目全栈方案
  3. Wireshark和TcpDump抓包分析心得
  4. 定制Dynamics CRM标准导出功能:不能导出指定列的值
  5. PDF目录书签生成器 PDG
  6. ipad横竖屏切换,页面适配方法
  7. C语言中将数字形式的字符串转换为数字的方法
  8. cad打开卡死_CAD点打开或者保存就卡死无响应的解决方法
  9. 政务区块链平台设计思路
  10. 【原创】QT5-卸载精灵v1.0-卸载windows软件-简易版
  11. IP5306是一款2.1A 充电 2.4 A 放电高集成度移动电源 SOC
  12. python编写一个汽车类_Python 类:以汽车为例
  13. 含有一般疑问句的歌_一般疑问句,特殊疑问句和否定句
  14. JavaScript-深浅拷贝
  15. SEO黑帽技术 - 蜘蛛池原理
  16. 频域分析中的三频段理论
  17. 发票查验平台验证码识别
  18. 用流对象的成员函数控制输出格式
  19. Android开发错误汇总
  20. Flowable流程引擎和各类表说明

热门文章

  1. 海贼王燃烧意志服务器维修,航海王燃烧意志48服-新世界开服时间表_航海王燃烧意志新区开服预告_第一手游网手游开服表...
  2. 使用mmap映射来读写文件
  3. linux vfs samba,vfs2 and samba(smb) version 2
  4. 【Swing 6】绝对定位—QQ登录界面
  5. RecyclerView条目多样式显示
  6. java郑渊洁游戏_童话大王郑渊洁:要让孩子感觉爸爸妈妈比游戏好玩
  7. acm用到的数学公式记录
  8. Android系统的使用量全面超过Windows
  9. 压力传感器的应用领域
  10. linux结构体转qbytearray,QByteArray储存二进制数据(包括结构体,自定义QT对象)