最大类间方差法OTSU+形态学处理实现数硬币

理论

最大类间方差法

部分搬运自文章:最大类间方差法(大津法OTSU)

简介

最大类间方差法是由日本学者大津于1979年提出的,是一种自适应的阈值确定的方法,又叫大津法,简称OTSU。它是按图像的灰度特性,将图像分成背景和目标2部分。背景和目标之间的类间方差越大,说明构成图像的2部分的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致2部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。

实现步骤

  1. 先计算图像的直方图,即将图像所有的像素点按照0~255共256个bin,统计落在每个bin的像素点数量。
  2. 归一化直方图,也即将每个bin中像素点数量除以总的像素点,使其限制在0~1之间
  3. 在这里设置一个分类的阈值i,也即一个灰度级,开始从0迭代
  4. 通过归一化的直方图,统计0~i 灰度级的像素(假设像素值在此范围的像素叫做前景像素) 所占整幅图像的比例 ω 0 ω_0 ω0,并统计前景像素的平均灰度 u 0 u_0 u0;统计i~255灰度级的像素(假设像素值在此范围的像素叫做背景像素) 所占整幅图像的比例 ω 1 ω_1 ω1,并统计背景像素的平均灰度 u 1 u_1 u1;在这里,设图像的总平均灰度为 u 2 u_2 u2,类间方差记为 g g g
    其中:
    u 2 = ω 0 u 0 + ω 1 u 1 u_2=ω_0 u_0+ω_1 u_1 u2=ω0u0+ω1u1
    g = ω 0 ( u 0 − u 2 ) 2 + ω 1 ( u 1 − u 2 ) 2 g=ω_0 (u_0-u_2)^2+ω_1 (u_1-u_2)^2 g=ω0(u0u2)2+ω1(u1u2)2
    u 2 u_2 u2带入 g g g中,可得:
    g = ω 0 ω 1 〖 ( u 0 − u 1 ) 〗 2 g=ω_0 ω_1 〖(u_0-u_1)〗^2 g=ω0ω1(u0u1)2
  5. 阈值的灰度值加1,并转到第4个步骤,直到i为256时结束迭代
  6. 将最大g相应的i值作为图像的全局阈值。

图像的形态学处理

参考文章

小白学习图像处理——图像的形态学处理(MATLAB)

膨胀、腐蚀、开、闭(matlab实现)

腐蚀

腐蚀在数学形态学运算中的作用是消除物体的边界点。在数字图像处理中,对于确定的结构元素,通过腐蚀运算可以消除小于结构元素的点。同时,若一个目标区域中含有细小的连接部分,那么通过笃实处理可以对区域进行分割。

膨胀

膨胀中以最大值来判断模板区域内原始图像到底是置于1还是置于0。到对于二值图像,用特定结构的模板去遍历图像上每一个位置,如果模板特定结构所在位置有一个点为1,则图像上对应特定结构的位置都是1 。对于灰度图像,则是将取1的位置赋值以特定结构重合部位的灰度值的最大值。对于彩色图像则是对三种颜色分量分别进行膨胀处理。

开运算和闭运算

开运算: A ○ S = ( A − S + S A○S=(A-S+S AS=AS+S (即对目标图像先腐蚀再膨胀)
闭运算: A ● S = ( A + S ) − S A●S=(A+S)-S AS=(A+S)S(即对目标图像先膨胀再腐蚀)
图像的开运算常常用来对目标图像进行消噪处理,同时,图像的开运算可以选择性地保留目标图像中符合结构原色几何性质的部分,而过滤掉相对结构元素而言残损的部分。
图像的闭运算常常用来对目标图像分开的区域进行连接及对图像中细小缝隙进行填补,通过适当地选择结构元素,图像的闭运算可以令图像的填补结果具有一点的几何特征,适当地对图像进行闭运算有时可以使图像变得更加清晰连贯,同时可以避免原图像中线条加粗。

实现步骤

  1. 使用最大类间方差法对图像进行阈值分割
  2. 根据阈值进行二值化处理
  3. 进行基础形态学处理(开运算,闭运算,腐蚀,膨胀等)
  4. 计算连通区域个数

代码

clc,clear
close all
I = imread('image/coins.png');
subplot(1,3,1)
imshow(I)
title('原图')
I = im2double(I);
[level,EM] = graythresh(I); % matlab自带的 最大类间方差法阈值分割

I2 = imbinarize(I,level); 
subplot(1,3,2)
imshow(I2)
title('阈值分割')

se = strel('disk',2);
I3 = imclose(I2,se); % 直接闭运算 闭:先膨胀再腐蚀,可以去掉目标内的孔。

se = strel('disk',10);
I3 = imerode(I3,se);  % 腐蚀

subplot(1,3,3)
imshow(I3)
title('形态学处理后')
[L,num] = bwlabel(I3);
num % 输出硬币个数
set(gcf,'units','normalized','position',[0.1,0.2,0.8,0.6])
saveas(gcf,'image/save.bmp')

处理效果

左一是要计数的图。中间的图是利用最大类间方差法阈值分割后的图。右图是再经过形态处理过的图。
在这里插入图片描述

github地址

项目地址:
https://github.com/Ackermannn/blog/tree/master/count_coins
下载:
https://github.com/Ackermannn/blog/raw/master/count_coins/count.zip

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Micropython中实现最大类间方差法Otsu)的方法如下: ``` import utime import sensor import image def otsu_threshold(img): hist = img.get_histogram() total_pixels = img.width() * img.height() sum_total = 0 for i in range(256): sum_total += i * hist[i] sum_back = 0 w_back = 0 w_fore = 0 var_max = 0 threshold = 0 for i in range(256): w_back += hist[i] if w_back == 0: continue w_fore = total_pixels - w_back if w_fore == 0: break sum_back += i * hist[i] mean_back = sum_back / w_back mean_fore = (sum_total - sum_back) / w_fore var_between = w_back * w_fore * (mean_back - mean_fore) ** 2 if var_between > var_max: var_max = var_between threshold = i return threshold sensor.reset() sensor.set_pixformat(sensor.GRAYSCALE) sensor.set_framesize(sensor.QQVGA) sensor.skip_frames(time=2000) while True: img = sensor.snapshot() threshold_value = otsu_threshold(img) img.binary([threshold_value]) img.show() utime.sleep(100) ``` 这段代码实现了使用Otsu算法进行图像二值化。在`otsu_threshold`函中,首先计算图像的直方图,然后根据直方图计算类间方差。通过遍历所有可能的阈值,找到最大的类间方差对应的阈值,作为最终的二值化阈值。在主循环中,读取图像并调用`otsu_threshold`函得到阈值,然后使用该阈值对图像进行二值化并显示。 请注意,这段代码是基于MicroPython语言编写的,并假设您已经正确配置了摄像头和传感器。确保在运行之前进行适当的硬件和软件设置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值