颜色分割
普通读取的图片都是RGB格式,就意味着每种颜色都是由三种RGB组合而成。同样的常用的格式还有HSV,具体的看下面的百度贴过来的:
色调H
用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,紫色为300°;
饱和度S
饱和度S表示颜色接近光谱色的程度。一种颜色,可以看成是某种光谱色与白色混合的结果。其中光谱色所占的比例愈大,颜色接近光谱色的程度就愈高,颜色的饱和度也就愈高。饱和度高,颜色则深而艳。光谱色的白光成分为0,饱和度达到最高。通常取值范围为0%~100%,值越大,颜色越饱和。
明度V
明度表示颜色明亮的程度,对于光源色,明度值与发光体的光亮度有关;对于物体色,此值和物体的透射比或反射比有关。通常取值范围为0%(黑)到100%(白)。
下面展示使用HSV对图片进行颜色分割,要分割的图片如下:
HSV格式中,H表示与颜色有关的,所以如果基于颜色分割的话,主要是对H通道进行阈值分割。看图片鸟为一种颜色,背景大致为一种颜色,大致可以猜测H通道的直方图有两个波峰,且背景像素对于小鸟像素,所以选择幅值较小的波峰即为小鸟所在区域:
下面编写代码实现相关的内容:
img_hsv = cv2.cvtColor(img2,cv2.COLOR_BGR2HSV)
H,S,V = cv2.split(img_hsv)
plt.bar([i for i in range(256)],calHist(H))
plt.show()
首先来看一下H通道的直方图:
和预测结果相同,可以看到小波峰主要集中在100附近,所以阈值选择需要在100两边:
下面我们来试试不同阈值选择的结果:不同的阈值为【50,120】、【80-120】、【100,120】
可以看出只要将小波峰完全包进阈值选择范围内就可以选择出来小鸟。
然后利用这个掩码对图像做位与操作:
res = cv2.bitwise_and(img,img,mask=mask)
得到分割出来的小鸟:
完整的代码如下:
def split_baseColor(img):
img_blur = cv2.blur(img,ksize=(5,5))
img_median = cv2.medianBlur(img_blur,5)
img_gaussian = cv2.GaussianBlur(img_median,(5,5),0)
img2 = cv2.bilateralFilter(img_gaussian,9,75,75)
img_hsv = cv2.cvtColor(img2,cv2.COLOR_BGR2HSV)
H,S,V = cv2.split(img_hsv)
plt.bar([i for i in range(256)],calHist(H))
plt.bar([i for i in range(256)],calHist(S))
plt.bar([i for i in range(256)],calHist(V))
plt.show()
low = np.array([50,0,0])
high = np.array([120,255,255])
mask = cv2.inRange(img_hsv,low,high)
res = cv2.bitwise_and(img,img,mask=mask)
s = np.hstack((img,res))
s = cv2.pyrDown(s)
show(s)