本文共享自华为云社区《[Python从零到壹] 五十二.图画增强及运算篇之图画掩膜直方图和HS直方图》,作者: eastmount。

一.图画掩膜直方图

假如要核算图画的某一部分直方图,就需求运用掩码(蒙板)来进行核算。假设即将核算的部分设置为白色,其余部分设置为黑色,然后运用该掩膜进行直方图制作,其完好代码如下所示。

# -*- coding: utf-8 -*-
# By:Eastmount
import cv2  
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
#读取图画
img = cv2.imread('luo.png')
#转化为RGB图画
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
#设置掩膜
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 100:300] = 255
masked_img = cv2.bitwise_and(img, img, mask=mask)
#图画直方图核算
hist_full = cv2.calcHist([img], [0], None, [256], [0,256]) #通道[0]-灰度图
#图画直方图核算(含掩膜)
hist_mask = cv2.calcHist([img], [0], mask, [256], [0,256])
plt.figure(figsize=(8, 6))
#设置字体
matplotlib.rcParams['font.sans-serif']=['SimHei']
#原始图画
plt.subplot(221)
plt.imshow(img_rgb, 'gray')
plt.axis('off')
plt.title("(a)原始图画")
#制作掩膜
plt.subplot(222)
plt.imshow(mask, 'gray')
plt.axis('off')
plt.title("(b)掩膜")
#制作掩膜设置后的图画
plt.subplot(223)
plt.imshow(masked_img, 'gray')
plt.axis('off')
plt.title("(c)图画掩膜处理")
#制作直方图
plt.subplot(224)
plt.plot(hist_full)
plt.plot(hist_mask)
plt.title("(d)直方图曲线")
plt.xlabel("x")
plt.ylabel("y")
plt.show()

其运转成果如图1所示,它运用了一个200200像素的掩膜进行实验。其间图1(a)表明原始图画,图1(b)表明200200像素的掩膜,图1表明原始图画进行掩膜处理,图1(d)表明直方图曲线,蓝色曲线为原始图画的灰度值直方图散布情况,绿色波动更小的曲线为掩膜直方图曲线。

Python从零到壹丨图像增强及运算:图像掩膜直方图和HS直方图

二.图画HS直方图

为了描写图画中颜色的直观特性,常常需求剖析图画的HSV空间下的直方图特性。HSV空间是由颜色(Hue)、饱和度(Saturation)、以及亮度(Value)构成,因此在进行直方图核算时,需求先将源RGB图画转化为HSV颜色空间图画,然后将对应的H和S通道进行单元区分,再其二维空间上核算相对应直方图,再核算直方图空间上的最大值并归一化制作相应的直方图信息,然后形成颜色-饱和度直方图(或H-S直方图)。该直方图一般使用在方针检测、特征剖析以及方针特征跟踪等场景[1-2]。

由于H和S重量与人感触颜色的方式是严密相连,V重量与图画的五颜六色信息无关,这些特色使得HSV模型十分适合于借助人的视觉体系来感知五颜六色特性的图画处理算法。

下面的代码是具体的完成代码,运用matplotlib.pyplot库中的imshow()函数来制作具有不同颜色映射的2D直方图。

# -*- coding: utf-8 -*-
# By:Eastmount
import cv2  
import numpy as np
import matplotlib.pyplot as plt
#读取图画
img = cv2.imread('luo.png')
#转化为RGB图画
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
#图画HSV转化
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
#核算H-S直方图
hist = cv2.calcHist(hsv, [0,1], None, [180,256], [0,180,0,256])
#原始图画
plt.figure(figsize=(8, 6))
plt.subplot(121), plt.imshow(img_rgb, 'gray'), plt.title("(a)"), plt.axis('off')
#制作H-S直方图
plt.subplot(122), plt.imshow(hist, interpolation='nearest'), plt.title("(b)")
plt.xlabel("x"), plt.ylabel("y")
plt.show()

图2(a)表明原始输入图画,图2(b)是原图画对应的五颜六色直方图,其间X轴表明饱和度(S),Y轴表明颜色(H)。在直方图中,能够看到H=140和S=130邻近的一些高值,它对应于美丽的颜色。

Python从零到壹丨图像增强及运算:图像掩膜直方图和HS直方图

三.直方图判别白日黑夜

接着讲述一个使用直方图的案例,经过直方图来判别一幅图画是黑夜或白日。常见的办法是经过核算图画的灰度平均值、灰度中值或灰度规范差,再与自定义的阈值进行比照,然后判别是黑夜仍是白日[3-4]。

  • 灰度平均值:该值等于图画中一切像素灰度值之和除以图画的像素个数。
  • 灰度中值:对图画中一切像素灰度值进行排序,然后获取一切像素最中心的值,即为灰度中值。
  • 灰度规范差:又常称均方差,是离均差平方的算术平均数的平方根。规范差能反映一个数据集的离散程度,是总体各单位规范值与其平均数离差平方的算术平均数的平方根。假如一幅图看起来灰蒙蒙的, 那灰度规范差就小;假如一幅图看起来很鲜艳,那比照度就很大,规范差也大。

下面的代码是核算灰度“Lena”图的灰度平均值、灰度中值和灰度规范差。

# -*- coding: utf-8 -*-
# By:Eastmount
import cv2  
import numpy as np
import matplotlib.pyplot as plt
#函数: 获取图画的灰度平均值
def fun_mean(img, height, width):
    sum_img = 0
    for i in range(height):
        for j in range(width):
            sum_img = sum_img + int(img[i,j])
    mean = sum_img / (height * width)
    return mean
#函数: 获取中位数
def fun_median(data):
    length = len(data)
    data.sort()
    if (length % 2)== 1: 
        z = length // 2
        y = data[z]
    else:
        y = (int(data[length//2]) + int(data[length//2-1])) / 2
    return y
#读取图画
img = cv2.imread('lena-hd.png')
#图画灰度转化
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#获取图画高度和宽度
height = grayImage.shape[0]
width = grayImage.shape[1]
#核算图画的灰度平均值
mean = fun_mean(grayImage, height, width)
print("灰度平均值:", mean)
#核算图画的灰度中位数
value = grayImage.ravel() #获取一切像素值
median = fun_median(value)
print("灰度中值:", median)
#核算图画的灰度规范差
std = np.std(value, ddof = 1)
print("灰度规范差", std)

其运转成果如图3所示,图3(a)为原始图画,图3(b)为处理成果。其灰度平均值为123,灰度中值为129,灰度规范差为48.39。

Python从零到壹丨图像增强及运算:图像掩膜直方图和HS直方图

下面讲解另一种用来判别图画是白日仍是黑夜的办法,其根本过程如下:

  • (1)读取原始图画,转化为灰度图,并获取图画的一切像素值;
  • (2)设置灰度阈值并核算该阈值以下的像素个数。比方像素的阈值设置为50,核算低于50的像素值个数;
  • (3)设置份额参数,比照该参数与低于该阈值的像素占比,假如低于参数则猜测为白日,高于参数则猜测为黑夜。比方该参数设置为0.8,像素的灰度值低于阈值50的个数占整幅图画一切像素个数的90%,则认为该图画偏暗,故猜测为黑夜;不然猜测为白日。

具体完成的代码如下所示。

# -*- coding: utf-8 -*-
# By:Eastmount
import cv2  
import numpy as np
import matplotlib.pyplot as plt
#函数: 判别黑夜或白日
def func_judge(img):
    #获取图画高度和宽度
    height = grayImage.shape[0]
    width = grayImage.shape[1]
    piexs_sum = height * width
    dark_sum = 0  #偏暗像素个数
    dark_prop = 0 #偏暗像素所占份额
    for i in range(height):
        for j in range(width):
            if img[i, j] < 50: #阈值为50
                dark_sum += 1
    #核算份额
    print(dark_sum)
    print(piexs_sum)
    dark_prop = dark_sum * 1.0 / piexs_sum 
    if dark_prop >=0.8:
        print("This picture is dark!", dark_prop)
    else:
        print("This picture is bright!", dark_prop)
#读取图画
img = cv2.imread('day.png')
#转化为RGB图画
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
#图画灰度转化
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#核算256灰度级的图画直方图
hist = cv2.calcHist([grayImage], [0], None, [256], [0,255])
#判别黑夜或白日
func_judge(grayImage)
#显现原始图画和制作的直方图
plt.subplot(121), plt.imshow(img_rgb, 'gray'), plt.axis('off'), plt.title("(a)")
plt.subplot(122), plt.plot(hist, color='r'), plt.xlabel("x"), plt.ylabel("y"), plt.title("(b)")
plt.show()

第一张测企图输出的成果如图4所示,其间图4(a)为原始图画,图4(b)为对应直方图曲线。

Python从零到壹丨图像增强及运算:图像掩膜直方图和HS直方图

终究输出成果为“(‘This picture is bright!’, 0.010082704388303882)”,该猜测为白日。

Python从零到壹丨图像增强及运算:图像掩膜直方图和HS直方图

第二张测企图输出的成果如图6所示,其间图6(a)为原始图画,图6(b)为对应直方图曲线。

Python从零到壹丨图像增强及运算:图像掩膜直方图和HS直方图

终究输出成果为“(‘This picture is dark!’, 0.8511824175824175)”,该猜测为黑夜。

Python从零到壹丨图像增强及运算:图像掩膜直方图和HS直方图

四.总结

本章首要讲解图画直方图相关知识点,包括掩膜直方图和HS直方图,并经过直方图判别黑夜与白日,经过案例共享直方图的实践使用。期望对您有所协助,后续将进入图画增强相关知识点。

参考文献:

  • [1]冈萨雷斯. 数字图画处理(第3版)[M]. 北京:电子工业出版社, 2013.
  • [2]张恒博, 欧宗瑛. 一种根据颜色和灰度直方图的图画检索办法[J]. 核算机工程, 2004.
  • [3]Eastmount. [数字图画处理] 四.MFC对话框制作灰度直方图[EB/OL]. (2015-05-31). blog.csdn.net/eastmount/a….
  • [4]ZJE_ANDY. python3+opencv 利用灰度直方图来判别图片的亮暗情况[EB/OL]. (2018-06-20). blog.csdn.net/u014453898/….
  • [5]阮秋琦. 数字图画处理学(第3版)[M]. 北京:电子工业出版社, 2008.
  • [6]Eastmount. [Python图画处理] 十一.灰度直方图概念及OpenCV制作直方图[EB/OL]. (2018-11-06). blog.csdn.net/Eastmount/a….

点击关注,第一时间了解华为云新鲜技能~