图像处理学习笔记(3)——图像分割

Ostu阈值分割

算法思想
  1. 计算直方图,将图像中所有的像素点按照0-255共256个bin,统计落在每个bin的像素点数量;
  2. 对直方图进行归一化处理,即计算每个灰度级的像素数目占整幅图像的比例
  3. i表示分类的阈值,也即一个灰度级,从0开始迭代;
  4. 通过归一化的直方图,统计0~i 灰度级的像素(假设像素值在此范围的像素叫做前景像素) 所占整幅图像的比例w1,并统计前景像素的平均灰度mu1;统计i~255灰度级的像素(假设像素值在此范围的像素叫做背景像素) 所占整幅图像的比例w2,并统计背景像素的平均灰度mu2;
  5. 计算前景像素和背景像素的方差 sigma = w1 * w2 * (mu1 - mu2) * (mu1 - mu2)
  6. i++;转到4,直到i为256时结束迭代;
  7. 将最大的方差sigma相应的i值作为图像的全局阈值;
  8. 二值化图像;
程序
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Drawing.Imaging;
namespace segmentation
{
    class Program
    {
        static void Main(string[] args)
        {
            //设置保存路径,这里用@指后面的\不需要转义,否则不能正确找到地址
            string savePath = @"E:\Desktop\66ns.jpg";
            //定义一个bitmap类的新实例,后面是图片的地址
            Bitmap img = new Bitmap(@"E:\Desktop\1n.jpg");
            //调用threshold,参数是图片img
            Bitmap a = threshold(img);
            //保存到某路径
            a.Save(savePath);
        }
        public static Bitmap threshold(Bitmap image)
        {
            //存储一组整数,初始化新实例
            Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);
            //位图锁定到系统内存
            BitmapData bmpData = image.LockBits(rect, ImageLockMode.ReadWrite, image.PixelFormat);
            //位图中的第一个扫描行
            IntPtr ptr = bmpData.Scan0;
            //int bytes = image.Width * image.Height;  
            //获得图片总的扫描像素,扫描行数*扫描宽度,不能用上面注释的来计算总的像素,否则图像只能处理一部分
            int bytes = bmpData.Height * bmpData.Stride;
            byte[] grayValues = new byte[bytes];
            System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);
            byte T = 0;
            byte[] neighb = new byte[bytes];
            byte temp = 0;
            //初始化最大最小的灰度值
            byte maxGray = 0;
            byte minGray = 255;
            int[] countPixel = new int[256];
            //计算直方图,将图像所有的像素点按照0~255共256个bin,统计落在每个bin的像素点数量
            for (int i = 0; i < grayValues.Length; i++)
            {
                temp = grayValues[i];
                countPixel[temp]++;
                if (temp > maxGray)
                {
                    maxGray = temp;
                }
                if (temp < minGray)
                {
                    minGray = temp;
                }
            }
            double mu1, mu2;
            int numerator;
            double sigma;
            double tempMax = 0;
            double w1 = 0, w2 = 0;
            double sum = 0;
            numerator = 0;
            //像素的总灰度(本算法没有进行归一化处理,也是可以的)
            for (int i = minGray; i <= maxGray; i++)
            {
                sum += i * countPixel[i];
            }
            for (int i = minGray; i < maxGray; i++)
            {
                //w1:0~i 灰度级的像素(假设像素值在此范围的像素叫做前景像素) 所占整幅图像的比例
                w1 += countPixel[i];
                numerator += i * countPixel[i];
                //前景像素的平均灰度
                mu1 = numerator / w1;
                //i~255灰度级的像素(假设像素值在此范围的像素叫做背景像素) 所占整幅图像的比例
                w2 = grayValues.Length - w1;
                //统计背景像素的平均灰度
                mu2 = (sum - numerator) / w2;
                //计算前景像素和背景像素的方差 sigma = w1 * w2 * (mu1 - mu2) * (mu1 - mu2)
                sigma = w1 * w2 * (mu1 - mu2) * (mu1 - mu2);
                //将最大的方差sigma相应的i值作为图像的全局阈值
                if (sigma > tempMax)
                {
                    tempMax = sigma;
                    T = Convert.ToByte(i);
                }
            }
            //二值化图像
            for (int i = 0; i < bytes; i++)
            {
                if (grayValues[i] < T)
                    grayValues[i] = 0;
                else
                    grayValues[i] = 255;
            }
            //释放返回图像
            System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
            image.UnlockBits(bmpData);
            return (image);
        }
    }
}
结果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值