opencv入门基础(四)灰度,彩色直方图
一.基本概念
定义:直方图是图像中像素强度分布的图形表达方式。
特征:直方图不再表征任何的图像纹理信息,而是对图像像素的统计。由于同一物体无论是旋转还 是平移在图像中都具有相同的灰度值,因此直方图具有平移不变性、缩放不变性等优点。
关键函数:
cv2.calcHist(images,channels,mask,histSize,ranges[hist[,accumulate]])
images:整型类型(uint8和float32)的原图(list形式显示)
channels:通道的索引,[0]代表灰度图片,[0],[1],[2]代表多通道
mask:计算指定区域的直方图,如果为none,那么计算全图
histSize(bins):每个色调(0-255)对应的像素数量/频率
range:强度值的范围,[0-255]、
具体功能可见下面例程。
import cv2
import matplotlib.pyplot as plt
import numpy as np
# 显示图片
def show_image(image,title,pos): # 参数:图片,名称,位置
# 顺序转换:由BGR转换为RGB
image_RGB = image[:,:,::-1] # 前两个参数height,width不变,channel变换
# 也可以用
# b,g,r = cv2.split(image)
# image_new = cv2.merge([r,g,b])
plt.title(title)
plt.subplot(2,3,pos)
plt.imshow(image_RGB)
# 显示图片的灰度直方图
def show_histogram(hist,title,pos,color):
# 显示标题
plt.title(title)
plt.subplot(2,3,pos)
plt.xlabel("Bins")
plt.ylabel("Pixels")
plt.xlim([0,256])
plt.plot(hist,color=color)
# 主函数main()
def main():
# 创建画布
plt.figure(figsize=(15,6))
plt.suptitle("Gray Image Histogram",fontsize=14,fontweight="bold")
# 加载图片
img = cv2.imread("BIT.jpg")
# 灰度转换
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 计算灰度图的直方图
hist_img = cv2.calcHist([img_gray],[0],None,[256],[0,256])
# 展示直方图
img_BGR = cv2.cvtColor(img_gray,cv2.COLOR_GRAY2BGR)
show_image(img_BGR ,"BGR image",1)
show_histogram(hist_img,"gray image histogram",4,"m")
# 对图片中的每个像素增加50
M = np.ones(img_gray.shape,np.uint8)*50
added_img = cv2.add(img_gray,M)
added_img_hist = cv2.calcHist([added_img],[0],None,[256],[0,256])
added_img_BGR = cv2.cvtColor(added_img,cv2.COLOR_GRAY2BGR)
show_image(added_img_BGR,"added image",2)
show_histogram(added_img_hist,"added image hist",5,"m")
# 对图片中的每个像素减少50
subtract_img = cv2.subtract(img_gray,M)
subtract_img_hist = cv2.calcHist([subtract_img],[0],None,[256],[0,256])
subtract_img_BGR = cv2.cvtColor(subtract_img,cv2.COLOR_GRAY2BGR)
show_image(subtract_img_BGR,"substracted image",3)
show_histogram(subtract_img_hist,"substracted image hist",6,"m")
plt.show()
main()
结果如下(对原图进行所有像素加50和减50,看直方图变化):
二.mask掩膜
简单来说,mask就是以一个特定的形状,去提取图像中我们感兴趣的特定区域,再在该区域进行直方图统计。
mport cv2
import matplotlib.pyplot as plt
import numpy as np
def show_image(image,title,pos):
img_RGB = image[:,:,::-1]
plt.title(title)
plt.subplot(2,2,pos)
plt.imshow(img_RGB)
def show_histogram(hist,title,pos,color):
plt.subplot(2,2,pos)
plt.title(title)
plt.xlim([0,256])
plt.plot(hist,color=color)
def main():
plt.figure(figsize=(12,7))
plt.suptitle("Gray Image and Histogram with mask",fontsize=20,fontweight="bold")
img_gray = cv2.imread("BIT.jpg",cv2.COLOR_RGB2GRAY)
img_gray_hist = cv2.calcHist([img_gray],[0],None,[256],[0,256])
show_image(img_gray,"image_gray",1)
show_histogram(img_gray_hist,"image gray histogram",2,"m")
# 创建mask,计算位图,直方图
mask = np.zeros(img_gray.shape[:2],np.uint8)
mask[130:500,600:1400]=255 # 255表示颜色
img_mask_hist = cv2.calcHist([img_gray],[0],mask,[256],[0,256])
# 通过与运算计算带有mask的灰度图片
mask_img = cv2.bitwise_and(img_gray,img_gray,mask=mask)
show_image(mask_img,"gray image with mask",3)
show_histogram(img_gray_hist,"histogram with marked gray image",4,"m")
plt.show()
main()
三.彩色直方图
import cv2
import matplotlib.pyplot as plt
import numpy as np
# 显示图片
def show_image(image,title,pos):
plt.subplot(3,2,pos)
plt.title(title)
image_RGB = image[:,:,::-1]
plt.imshow(image_RGB)
plt.axis("off")
# 显示彩色直方图
def show_histogram(hist,title,pos,color):
plt.subplot(3,2,pos)
plt.title(title)
plt.xlim([0,256]) # 因为是RGB三条线,所以要用循环显示
for h,c in zip(hist,color): # color:(b,g,r)
plt.plot(h,color=c)
# 计算直方图
def calc_color_hist(image):
hist = []
hist.append(cv2.calcHist([image],[0],None,[256],[0,256]))
hist.append(cv2.calcHist([image],[1],None,[256],[0,256]))
hist.append(cv2.calcHist([image],[2],None,[256],[0,256]))
return hist
# 主函数
def main():
plt.figure(figsize=(12,8))
plt.suptitle("Color Histogram",fontsize=4,fontweight="bold")
img = cv2.imread("BIT.jpg")
img_hist = calc_color_hist(img)
show_image(img,"RGB Image",1)
show_histogram(img_hist,"RGB Image Hist",2,('b','g','r'))
# 原始图片中每个像素增加50个像素值
M = np.ones(img.shape,dtype="uint8")*50
added_image = cv2.add(img,M)
added_image_hist = calc_color_hist(added_image)
show_image(added_image,"added image",3)
show_histogram(added_image_hist,"added_image_hist",4,('b','g','r'))
# 原始图片中每个像素减少50个像素值
subtracted_image = cv2.subtract(img,M)
subtracted_image_hist = calc_color_hist(subtracted_image)
show_image(subtracted_image,"substracted image",5)
show_histogram(subtracted_image_hist,"substracted_image_hist",6,('b','g','r'))
plt.show()
main()
结果为(对全图像素增加50以及减少50后的颜色直方图显示):