小发言
本着从来不写水文的态度,一份二值化来了。
本份代码完全自写,由于要输入输出图片,故采用的是matlab语言,但是除了使用imread()和imshow()函数之外,所有代码全部是自己写的,并且与matlab自带库函数做了对比。这样的话,也方便了大家用C移植,如果搞懂原理的话,移植也就是20分钟的事。
上来就整原理
T
T
T:阈值
n
0
n_0
n0:小于阈值的像素,也就是前景
n
1
n_1
n1:大于阈值的像素,也就是背景
h
h
h:图像高
w
w
w:图像宽
n
0
+
n
1
=
h
×
w
=
N
n_0+n_1=h\times w=N
n0+n1=h×w=N
w 0 = n 0 N w_0=\frac{n_0}{N} w0=Nn0:前景像素占总数比
w
1
=
n
1
N
w_1=\frac{n_1}{N}
w1=Nn1:背景像素占总数比
w
0
+
w
1
=
1
w_0+w_1=1
w0+w1=1
u
0
u_0
u0:前景平均灰度
u
1
u_1
u1:背景平均灰度
u
u
u:整幅图像平均灰度
u
=
w
0
u
0
+
w
1
u
1
u=w_0u_0+w_1u_1
u=w0u0+w1u1
g
g
g:类间方差
g
=
w
0
(
u
0
−
u
)
2
+
w
1
(
u
1
−
u
)
2
g=w_0(u_0-u)^2+w_1(u_1-u)^2
g=w0(u0−u)2+w1(u1−u)2
化简
g
=
w
0
w
1
(
u
0
−
u
1
)
2
g=w_0w_1(u_0-u_1)^2
g=w0w1(u0−u1)2
当类间方差最大时。此时的灰度值就是我们需要求得最佳阈值。因此只需要对每个灰度值依次遍历,并计算g值,加以比较从而求出最适阈值。
干货从这里开始
首先读取图片
y_img=imread("pic.jpg");
imshow(y_img);
然后转换为灰度
h_img:灰度图像
h_img=rgb2gray(y_img);
imshow(h_img);
绘制灰度直方图
[h,w]=size(h_img);
N=h*w;
直方图统计并绘出直方图
对于这里的h_img(i,j)+1 做个特别说明,是由于在matlab 里面,数组的索引是从1开始的,没有0,而对于灰度值(0到255)来说,是有0的,因此用Histogram(1)表示灰度值为0的像素点个数,同样,用Histogram(256)表示灰度值为255的像素点个数。
Histogram=zeros(1,256);
for i=1:h
for j=1:w
Histogram(h_img(i,j)+1)=Histogram(h_img(i,j)+1)+1;
end
end
createfigure(Histogram);%自定义绘制直方图函数
求总的灰度值
graySum=0;
for i=1:256
graySum = graySum + Histogram(i)*(i-1);
end
计算最佳阈值
n0=0;
n0sum=0;
temp=0;
for i=1:256
n0 =n0+ Histogram(i); %阈值为i时前景个数
n1 = N - n0; %阈值为i时背景个数
w0 = n0/N; %前景像素占总数比
w1 = n1/N;%背景像素占总数比
if n0==0
continue
end
if n1==0
break
end
%前景平均灰度
n0sum = n0sum+Histogram(i)*(i-1);
u0 = n0sum/n0;
%背景平均灰度
n1sum = graySum-n0sum;
u1 = n1sum/n1;
g = w0*w1*(u0-u1)*(u0-u1);
if g > temp
temp = g;
T = i-1;
end
end
比较,进行二值化
bw=zeros(h,w);
for i=1:h
for j=1:w
if h_img(i,j)>T
bw(i,j)=255;
else
bw(i,j)=0;
end
end
end
imshow(bw)
matlab自带二值化
t1=graythresh(h_img);
F=imbinarize(h_img,t1);
imshow(F)
总结
把自己写的二值化与matlab自带的比较,可见两者几乎完全一样,可见效果还是很好的。对于二值化,方法还有好几种,我这里只是选了一种应用最广的大津法进行了介绍,至于对于特定的场合,不同的二值化有着不同的效果,因此,至于怎样用,还是靠各位小伙伴深入探究了。后续可能会对各种二值化方法一一介绍哦,还是那句话,要么就不写,绝不写水文。想要获取完整代码的小伙伴,请在文末留言。
欢迎关注本人公众号
D
e
c
o
d
e
技
术
站
Decode技术站
Decode技术站