图像二值化语义分割

发布时间 2023-03-22 21:09:36作者: 辰令

图像语义分割(semantic image segmentation)

图像二值化图像二值化函数 
 根据图像的灰度特性,将图像分为前景和背景两个部分
 将图片(例如,视频,特别是监控视频的图片)分离成前景和背景的任务。具体地,涉及将运动前景对象与静态背景场景分离
   “背景减除”就是这样一种传统方法,它基于当前图片与参考图片之间的“差异”,通常称为“背景模型

基于阈值的分割方法、基于区域的分割方法、基于边缘检测的分割方法以及基于深度模型的分割方法等	

代码

import cv2         
import numpy as np    
  
# 输入
image1 = cv2.imread(r'.\FC02.jpg')
# 转换为灰度图像
img = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)

#图像二值化函数cv2.threshold函数的介绍-applying a signal processing technique to an image processing task
#	图像的二值化,就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的只有黑和白的视觉效果(灰度值0:黑,灰度值255:白).
#    在图像中除了目标物体和背景区域,还有噪声,通过图像二值化函数将多值的数字图像中直接提取出目标图像 象素群
# 阈值的作用是根据设定的值处理图像的灰度值,比如灰度大于某个数值像素点保留    Simple Thresholding and Adaptive Thresholding w
# src是灰度图像 thresh是起始阈值 maxval是最大值 type是定义如何处理数据与阈值的关系 
# # cv2.threshold(src, thresh, maxval, type[, dst]) 
#  0 当前灰度值  maxval cv2.THRESH_OTSU使用最小二乘法处理像素点
# v2.THRESH_BINARY一起使用。当使用cv2.THRESH_OTSU或cv2.THRESH_TRIANGLE时,阈值是动态的,会根据计算结果返回相应的数值
ret, thresh1 = cv2.threshold(img, 120, 255, cv2.THRESH_BINARY + 
                                            cv2.THRESH_OTSU)     

# the window showing output image         
# with the corresponding thresholding         
# techniques applied to the input image 

# 相同大小图像水平拼接
wind_nm = 'Otsu_Threshold'
cv2.namedWindow(wind_nm, 0)
cv2.resizeWindow(wind_nm, 400,300)   
cv2.imshow(wind_nm, thresh1) 

cv2.namedWindow(wind_nm+"ori", 0)
cv2.resizeWindow(wind_nm+"ori", 400,300)   
cv2.imshow(wind_nm+"ori", image1)   
       
# De-allocate any associated memory usage         
if cv2.waitKey(0) & 0xff == 27:
    cv2.destroyAllWindows()

思路:

数据分类、地图分级(Classification)
01.Otsu Thresholding Algorithm== Between-class variance method 
 在直方图Python中找到两个最高峰值的中心值 	-foreground and background
  1.to flatten the image (2D signal) and change it into a 1D one.
  2. the distribution of our 1D Signal 
     have two normal distributions. The underlying idea is that the background and the subject of the image
  3.Choose a threshold	 
  4. minimizing intra-class intensity variance, or equivalently, by maximizing inter-class variance
其他类似	
02.Fisher判别分析,线性判别分析(linear discriminant analysis,LDA) 
       • 最大化类间距离Maximize the between-class distance (means)
       • 最小化类内距离Minimize the within-class variability (scatter)	
     方法:
          先计算每个类的均值-使得投影间距离最大化:
     	  类间散度矩阵-类内散度矩阵-最小化投影

Jenks optimization method  
    Fisher-Jenks algorithm, Jenks Optimisation Method or Fisher exact optimization method
	Natural breaks的分类原则是组间方差尽可能大,并且组内方差尽可能小
		R中的ClassInt包来使用Natural breaks对一维数据进行分类
		Jenks Natural Breaks通过优化方差拟合优度(0到1,其中0 =不适合且1 =完美适合)来工作
globally optimal k-means

地图配色方案

地图配色最佳cheat sheet。
  https://gistbok.ucgis.org/bok-topics/2019-quarter-02/statistical-mapping-enumeration-normalization-classification   	
Defined Interval 定义间隔分类
Equal Interval   等距分类
Quantile  等量分类。又叫分位数分类 每一类的数目一样
Standard Deviation 标准差分类。显然适合正态分布的数据,用于表现与均值相异的程度
Natural Breaks(Jenks)  自然断点分类。一般来说,分类的原则就是差不多的放在一起,分成若干类。统计上可以用方差来衡量,
     通过计算每类的方差,再计算这些方差之和,用方差和的大小来比较分类的好坏
Geometry Interval	
对数分段、开方分段	
默认提供等距分段	
Pretty Breaks	
Unique Values	  Unique: 外部标准。 与数据集无关,和相关数据的业内标准有关。

附录

 Simple Thresholding
 Adaptive Thresholding  cv2.adaptiveThreshold
 Otsu Thresholding)

K-Means对一维数据聚类

 from sklearn.cluster import KMeans
 import numpy as np
 x = np.random.random(10000)
 y = x.reshape(-1,1)
 km = KMeans()
 km.fit(y)
#核心的操作是y = x.reshape(-1,1),含义为将一维数据变成只有1列,
#行数不知道多少(-1代表根据剩下的维度计算出数组的另外一个shape属性值)。

方案二:采用一维聚类方法Jenks Natural Breaks

   Jenks Natural Breaks(自然断点分类)。一般来说,分类的原则就是差不多的放在一起,分成若干类。统计上可以用方差来衡量,
   通过计算每类的方差,再计算这些方差之和,用方差和的大小来比较分类的好坏。因而需要计算各种分类的方差和,
   其值最小的就是最优的分类结果(但并不唯一)。这也是自然断点分类法的原理。
   另外,当你去看数据的分布时,可以比较明显的发现断裂之处,这些断裂之处和Jenks Natural Breaks方法算出来也是一致的。
   因而这种分类法很“自然”。
   
   Jenks Natural Breaks和K Means在一维数据时,完全等价。它们的目标函数一样,
   但是算法的步骤不完全相同。K Means是先设定好K个初始随机点。
   而Jenks Breaks则是用遍历的方法,一个点一个点地移动,直到达到最小值。
   
   Natural Breaks算法又有两种:
   
   Jenks-Caspall algorithm(1971),是Jenks和Caspall发明的算法。原理就如前所述,实现的时候要将每种分类情况都计算一遍,找到方差和最小的那一种,计算量极大。n个数分成k类,就要从n-1个数中找k-1个组合,这个数目是很惊人的。数据量较大时,如果分类又多,以当时的计算机水平根本不能穷举各种可能性。
   Fisher-Jenks algorithm(1977),Fisher(1958)发明了一种算法提高计算效率,不需要进行穷举。Jenks将这种方法引入到数据分类中。但后来者几乎只知道Jenks而不知Fisher了。
   具体算法实现:
   
   Jenks-Caspall algorithm:https://github.com/domlysz/Jenks-Caspall.py
   Fisher-Jenks algorithm:https://github.com/mthh/jenkspy
  和K-Means一样,使用Jenks Natural Breaks需要先确定聚类数量K值。
 常见的方法是:GVF(The Goodness of Variance Fit)。GVF,翻译过来是“方差拟合优度”, 
   其中,SDAM是the Sum of squared Deviations from the Array Mean,即原始数据的方差;
        SDCM是the Sum of squared Deviations about Class Mean,即每一类方差的和。
		显然,SDAM是一个常数,而SDCM与分类数k有关。一定范围内,GVF越大,分类效果越好。
		SDCM越小,GVF越大,越接近于1。而SDCM随k的增大而大,当k等于n时,SDMC=0,GVF=1。
		GVF用于判定不同分类数的分类效果好坏。以k和GVF做图可得:

   代码示例:
   
   from jenkspy import jenks_breaks
   import numpy as np

方案三:核密度估计Kernel Density Estimation

所谓核密度估计,就是采用平滑的峰值函数(“核”)来拟合观察到的数据点,从而对真实的概率分布曲线进行模拟。
核密度估计更多详细内容,可以先前的Mean Shift聚类中的相关说明。

###使用示例:
import numpy as np
from scipy.signal import argrelextrema
import matplotlib.pyplot as plt
from sklearn.neighbors.kde import KernelDensity

a = np.array([10, 11, 9, 23, 21, 11, 45, 20, 11, 12]).reshape(-1, 1)
kde = KernelDensity(kernel=\'gaussian\', bandwidth=3).fit(a)
s = np.linspace(0, 50)
e = kde.score_samples(s.reshape(-1, 1))
plt.plot(s, e)
plt.show()

mi, ma = argrelextrema(e, np.less)[0], argrelextrema(e, np.greater)[0]
print(\"Minima:\", s[mi])
print(\"Maxima:\", s[ma])
print(a[a < mi[0]], a[(a >= mi[0]) * (a <= mi[1])], a[a >= mi[1]])

plt.plot(s[:mi[0] + 1], e[:mi[0] + 1], \'r\',
         s[mi[0]:mi[1] + 1], e[mi[0]:mi[1] + 1], \'g\',
         s[mi[1]:], e[mi[1]:], \'b\',
         s[ma], e[ma], \'go\',
         s[mi], e[mi], \'ro\')
plt.show()

参考

Hands on Otsu Thresholding Algorithm for Image Background Segmentation, using Python
 https://towardsdatascience.com/hands-on-otsu-thresholding-algorithm-for-image-background-segmentation-using-python-9fa0575ac3d2
 Otsu‘s Thresholding的工作原理 https://blog.csdn.net/u014281392/article/details/122923280	
 https://www.geeksforgeeks.org/python-thresholding-techniques-using-opencv-set-3-otsu-thresholding/	 
 Image Thresholding https://docs.opencv.org/4.x/d7/d4d/tutorial_py_thresholding.html
 https://en.wikipedia.org/wiki/Otsu%27s_method
 https://en.wikipedia.org/wiki/Kernel_density_estimation
 https://en.wikipedia.org/wiki/Jenks_natural_breaks_optimization
 http://scikit-learn.org/stable/auto_examples/neighbors/plot_kde_1d.html
 https://jakevdp.github.io/blog/2013/12/01/kernel-density-estimation/