win10+Python3.7.3+OpenCV3.4.1入门学习(十三)————13.4 使用掩膜绘制直方图

Python版本是Python3.7.3,OpenCV版本OpenCV.3.4.1,开发环境为PyCharm

13.4 使用掩模绘制直方图

在函数cv2.calcHist()中,参数mask用于标识是否使用掩模图像。当使用掩模图像获取直方图时,仅获取掩模参数mask指定区域的直方图。

1.掩模处理是怎么回事
首先,我们来看掩模处理的基本形式。在下图中,左图是原始图像O,中间的是掩模图像M,右图是使用掩模图像M对原始图像O进行掩模运算的结果图像R。
在这里插入图片描述

为了方便理解,可以将掩模图像看作一块玻璃板,玻璃板上的白色区域是透明的,黑色区域是不透明的。掩模运算就是将该玻璃板覆盖在原始图像上,透过玻璃板显示出来的部分就是掩模运算的结果图像。
在掩模运算中,使用了“与”和“或”运算,我们用下图所示的电路图进行说明。
在这里插入图片描述

● 与运算(AND)和串联电路是对应的。在图13-17的左图所示的串联电路中,只有当两个开关都闭合时,电路才是连通的。对应在数值运算上,只有参与运算的数值都是1时,与运算结果才是1,如下表所示。

算子1算子2结果规则
000and(0,0)=0
010and(0,1)=0
100and(1,0)=0
111and(1,1)=0

● 或运算(OR)和并联电路是对应的。在图13-17的右图所示的并联电路中,任意一个开关闭合,电路都是连通的。对应在数值运算上,参与运算的数值只要有一个值是1时,或运算结果就是1,如下表所示。

算子1算子2结果规则
000or(0,0)=0
010or(0,1)=1
100or(1,0)=1
111or(1,1)=1

将下图中左侧的原始图像O与中间的掩模图像M,进行与运算,得到右侧的结果图像R。经过与运算后,在原始图像O中,只有深色背景区域中的值被保留,其余的值都被处理为0。
在这里插入图片描述

得到上述运算结果是因为:
● 原始图像O的深色背景区域,所对应掩模图像中深色背景区域的值均为1,对这两个深色背景区域进行与运算时,根据运算规则,原始图像O深色背景区域的值被保留。
● 原始图像O的白色背景区域,所对应掩模图像中白色背景区域的值均为0,对这两个白色背景区域进行与运算时,根据运算规则,原始图像O白色背景区域的值被处理为0。
上述与运算是直接对两个数值进行运算的,理解起来比较方便,但是在实际处理中较为烦琐。在实际处理中,通常将掩模图像白色区域的值设置为255,然后让掩模图像与原始图像进行按位与运算,得到结果图像。下面简单介绍一下按位与运算的基本原理,更多内容请参考第3章。
OpenCV提供了bitwise_and函数,用于两个像素值之间的按位与运算。按位与运算,是指将两个像素值按照二进制位的关系,逐位进行与运算。例如,A的像素值为35, B的像素值为126,将A和B进行按位与运算,所得结果如下表所示。在进行按位与运算时,需要先将参与运算的值转换为二进制数,然后将对应位上的值进行运算

数值十进制数二进制值
数值11981100 0110
数值2219110 11011
按位与运算结果1941100 0010

根据与运算的规则,任意一个数值与数值1进行与运算,结果等于其自身的值。因此,任意一个8位像素值与二进制数“1111 1111”进行按位与运算,得到的都是自身的值。二进制值“1111 1111”对应的十进制值是“255”,所以任意一个8位像素值与“255”进行按位与运算,得到的都是自身原来的值。例如,像素点X的值为58,像素点Y的值为135,将这两个值与255进行按位与运算后,得到的是它们自身的值,如下表所示。
在这里插入图片描述

当然,任意数值与数值0进行与的运算结果都是0,如下表所示。
在这里插入图片描述

根据上述分析,可以将掩模图像的白色背景部分设置为255,黑色背景部分设置为0,如下图所示。

在这里插入图片描述
综上所述,将一幅图像与如图中所示的掩模图像进行按位与运算后,得到的结果图像分为以下两部分。
第1部分:与掩模图像中黑色背景位置对应的部分,该部分的像素值都被置为零。
第2部分:与掩模图像中白色背景位置对应的部分,该部分的像素保留原有值。

当在一个函数F中使用了掩模时,就意味着要先将参与运算的图像与掩模图像进行按位与运算,得到掩模运算结果(处理过程如图13-16所示)。然后,再将掩模运算结果,作为函数F的参数完成函数F所指定的运算。例如,有函数F、原始图像I、掩膜图像M和运算结果R,则:
● R = F(I)表示直接使用函数F对图像I进行处理。
● R = F(I, M)表示先将I和M进行按位与,然后再使用函数F对上述按位与的结果进行处理。
上述过程就是掩模处理的原理和方式。不过,在实际使用中我们只需要构造掩模图像就可以了,至于掩模图像如何起作用,并不需要我们的操心,是由函数来实现的。

2.如何构造掩模图像
在构造掩模图像时,通常先构造一个像素值都是0的二维数组,再将数组中指定区域的像素值设定为255,就得到了掩模图像。下面通过一个例子来说明如何构造掩模图像。

eg1:构造一个中心点是白色区域的掩模图像。
根据题目的要求,首先使用函数np.zeros()构造一个像素值都是0的二维数组,然后将其中间部分的值设置为255,代码如下:

import cv2
import numpy as np
mask=np.zeros([600,600],np.uint8)
mask[200:400,200:400]=255
cv2.imshow('mask',mask)
cv2.waitKey()
cv2.destroyAllWindows()

运行上述程序,生成如下图所示的掩模图像。

在这里插入图片描述

3.使用掩模绘制直方图
绘制掩模图像时,首先将函数cv2.calcHist()的mask参数设置为掩模图像,得到掩模处理的直方图信息,再使用plot()函数完成直方图的绘制。
回顾一下函数cv2.calcHist()的语法格式:

hist = cv2.calcHist( images, channels, mask, histSize, ranges, accumulate )

其中,mask参数就是掩模图像。
下面通过一个例子演示如何绘制掩模结果图像的直方图。

eg2:演示绘制掩模结果图像的直方图。
根据题目的要求,首先构造一个掩模图像,然后使用函数cv2.calcHist()计算掩模结果图像的统计直方图信息,最后使用函数plot()绘制掩模图像的直方图。
掩模图像要保持与原始图像相等的大小,这里使用参数image.shape表示构造与原始图像等大小的掩模图像。
代码如下:

import cv2
import numpy as np
import matplotlib.pyplot as plt
image=cv2.imread("image\\girl.bmp",cv2.IMREAD_GRAYSCALE)
mask=np.zeros(image.shape,np.uint8)
mask[200:400,200:400]=255
histImage=cv2.calcHist([image],[0],None,[256],[0,255])
histMI=cv2.calcHist([image],[0],mask,[256],[0,255])
plt.plot(histImage)
plt.plot(histMI)
plt.show(  )   # 显示图像

运行上述程序,生成如下图所示的直方图。其中,上方的曲线是原始图像的直方图,下方的曲线是掩模结果图像的直方图。

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值