OpenCV——直方图

本文介绍了图像的位深度和色深的区别,位深度表示每个像素的位数,色深则指像素可表示的颜色数量。直方图用于统计图像颜色分布,bin是直方图的颜色区间。直方图均衡化能提升图像对比度,包括全局和局部均衡化。此外,文章还探讨了直方图比较和反向投影技术,直方图比较用于图像相似性评估,直方图反向投影则用于图像检索和内容匹配。
摘要由CSDN通过智能技术生成

前言

直方图

完成下面的操作先,记得先pip install matplotlib

图像色深(bit depth)和位深度的区别

位深是指存储每个像素所用的位数,例如一副32位100100像素的图片,其大小为:100100*32/8=40000 个字节, 原来一直以为图像色深就是位深度,后来网上搜了下才知道这2个是完全不同的概念。图像深度是指存储每个象素所用的位数,也用于量度图像的色彩分辨率.图像深度确定彩色图像的每个象素可能有的颜色数,或者确定灰度图像的每个象素可能有的灰度级数.它决定了彩色图像中可出现的最多颜色数,或灰度图像中的最大灰度等级.比如一幅单色图像,若每个象素有8位,则最大灰度数目为2的8次方,即256.一幅彩色图像RGB3个温良的象素位数分别为4,4,2,则最大颜色数目为2的4+4+2次方,即1024,就是说象素的深度为10位,每个象素可以是1024种颜色中的一种.
色深(Color Depth),也称之为色位深度,在某一分辨率下,每一个像素点可以有多少种色彩来描述,它的单位是“bit”(位)。典型的色深是8-bit、16-bit、24-bit和32-bit。深度数值越高,可以获得更多的色彩。

这个概念会跟下面的image.ravel()中的参数有关,要注意。

图像直方图

图像直方图中bin的概念

(1)直方图中bin的含义:计算颜色直方图需要将颜色空间划分为若干小的颜色区间,即直方图的bin,通过计算颜色在每个小区间内德像素得到颜色直方图,bin越多,直方图对颜色的分辨率越强,但增加了计算机的负担。即(上图所分10个竖条区域,每个竖条区域称为一个bin)
(2)简单来说直方图就是对数据进行统计,将统计值组织到一系列事先定义好的bin中。bin中的数值就是从数据中计算出的特征的统计量,这些数据可以是诸如梯度、方向、色彩或任何其他特征。无论如何,直方图获得的是数据分布的统计图。直方图实际上是一个方便表示图像特征的手段。
在这里插入图片描述
code:

import cv2 as cv
import numpy as np
from matplotlib import  pyplot as plt

def plot_demo(image):
    plt.hist(image.ravel(),256,[0,256])#ravel对image进行统计,统计出256个bin
    plt.show()#ravel是将numpy数组扁平化成一维数组

def image_hist(image):#反应了图像的一些主要特征
    color = ('blue','green','red')
    for i,color in enumerate(color):#从容器中进行迭代
        hist = cv.calcHist(image,[i],None,[256],[0,256])
        plt.plot(hist,color=color)
        plt.xlim([0,256])
    plt.show()


src = cv.imread("../images/lena.jpg")
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow('input image', src)
plot_demo(src)
image_hist(src)
cv.waitKey(0)  # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口

cv.destroyAllWindows()

效果图
原图像:
在这里插入图片描述

上面两个函数对图像的处理:
在这里插入图片描述
在这里插入图片描述

直方图的应用

直方图均匀化
全局
  1. 效果图
    原图:
    在这里插入图片描述
    效果图:
    在这里插入图片描述

  2. API解释:
    函数原型:
    void equalizeHist(InputArray src,OutputArray dst)
    参数详解:
    src:源图像。图像必须是灰度图。
    dst:目标图像。
    函数作用:直方图均衡化,,用于提高图像的质量。直方图均衡化是通过拉伸像素强度分布范围来增强图像对比度的一种方法.

  3. Code

import cv2 as cv
import numpy as np

def equalHist_demo(image):
    gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
    dst = cv.equalizeHist(gray)#直方图均衡化
    cv.imshow("equalHist_demo",dst)

src = cv.imread("../images/noise_rice.png")
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow('input image', src)
equalHist_demo(src)
cv.waitKey(0)  # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口

cv.destroyAllWindows()
局部
  1. 上面那个是对整张图片进行增强,而下面这个是对局部进行增强,你可以注意看那些米粒,只有部分的增强,而不是全部变强。
    原图
    在这里插入图片描述

效果图
在这里插入图片描述

  1. API介绍
    cv2.createCLAHA(clipLimit=8.0, titleGridSize=(8, 8)) 用于生成自适应均衡化图像
    参数说明:clipLimit颜色对比度的阈值, titleGridSize进行像素均衡化的网格大小,即在多少网格下进行直方图的均衡化操作

  2. code

import cv2 as cv
import numpy as np

def equalHist_demo(image):
    gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
    dst = cv.equalizeHist(gray)#直方图均衡化
    cv.imshow("equalHist_demo",dst)

def clahe_demo(image):
    gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
    clahe = cv.createCLAHE(clipLimit=5.0,tileGridSize=(8,8))
    # 用于生成自适应均衡化图像
    # 参数说明:clipLimit颜色对比度的阈值, titleGridSize进行像素均衡化的网格大小,即在多少网格下进行直方图的均衡化操作
    dst = clahe.apply(gray)
    cv.imshow("clahe_demo",dst)


src = cv.imread("../images/noise_rice.png")
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow('input image', src)
# equalHist_demo    (src)
clahe_demo(src)
cv.waitKey(0)  # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口

cv.destroyAllWindows()
直方图比较

这里采用的巴氏距离,相关性,卡方三种。
直接看代码:

import cv2 as cv
import numpy as np

def equalHist_demo(image):
    gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
    dst = cv.equalizeHist(gray)#直方图均衡化
    cv.imshow("equalHist_demo",dst)

def clahe_demo(image):
    gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
    clahe = cv.createCLAHE(clipLimit=5.0,tileGridSize=(8,8))
    # 用于生成自适应均衡化图像
    # 参数说明:clipLimit颜色对比度的阈值, titleGridSize进行像素均衡化的网格大小,即在多少网格下进行直方图的均衡化操作
    dst = clahe.apply(gray)
    cv.imshow("clahe_demo",dst)

def create_rgb_hist(image):
    h,w,c = image.shape
    rgbHist = np.zeros([16*16*16,1],np.float32)
    bsize = 256/16
    for row in range(h):
        for col in range(w):
            b = image[row,col,0]
            g = image[row,col,1]
            r = image[row,col,2]
            index = np.int(b/bsize)*16*16+np.int(g/bsize)*16+np.int(r/bsize)
            rgbHist[np.int(index),0] = rgbHist[np.int(index),0]+1

    return rgbHist

def hist_compare(image1,image2):
    hist1 = create_rgb_hist(image1)
    hist2 = create_rgb_hist(image2)
    match1 = cv.compareHist(hist1,hist2,cv.HISTCMP_BHATTACHARYYA)
    match2 = cv.compareHist(hist1,hist2,cv.HISTCMP_CORREL)
    match3 = cv.compareHist(hist1,hist2,cv.HISTCMP_CHISQR)
    print("巴氏距离:%s,相关性:%s,卡方:%s"%(match1,match2,match3))


src = cv.imread("../images/noise_rice.png")
image1 = cv.imread("../images/lena.jpg")
image2 = cv.imread("../images/plane.jpg")
cv.imshow("image1",image1)
cv.imshow("image2",image2)

hist_compare(image1,image2)
# cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
# cv.imshow('input image', src)
# equalHist_demo    (src)
# clahe_demo(src)
cv.waitKey(0)  # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口

cv.destroyAllWindows()

结果
在这里插入图片描述

直方图反向投影

直方图的反向投影是利用直方图模型计算给定图像像素点的特征。 反向投影在某一位置的值是源图像在对应位置的像素值的累计。 反向投影操作可实现检测输入源图像给定图像块的最匹配区域,一般可用于基于图像内容的检索或查找特定的内容。 对于原始灰度图像f(x,y),计算相应的灰度直方图时,可利用直方图变换bin来计算相应的反向投影。
code

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

def hist2d_dmeo(image):
    hsv = cv.cvtColor(image,cv.COLOR_BGR2HSV)
    hist = cv.calcHist([image],[0,1],None,[180,256],[0,180,0,256])#有两个通道,所以,要有两个数
    plt.imshow(hist,interpolation="nearest")
    plt.title("2D Histogram")
    plt.show()
# 一、images(输入图像)参数必须用方括号括起来。
# 二、计算直方图的通道。
# 三、Mask(掩膜),一般用None,表示处理整幅图像。
# 四、histSize,表示这个直方图分成多少份(即多少个直方柱)。
# 五、range,直方图中各个像素的值,[0.0, 256.0]表示直方图能表示像素值从0.0256的像素。
# 六、最后是两个可选参数,由于直方图作为函数结果返回了,所以第六个hist就没有意义了(待确定) 最后一个accumulate是一个布尔值,用来表示直方图是否叠加。
def back_project_demo():
    sample = cv.imread("../images/roi.png")
    target = cv.imread("../images/lena.jpg")
    roi_hsv = cv.cvtColor(sample,cv.COLOR_BGR2HSV)
    target_hsv = cv.cvtColor(target,cv.COLOR_BGR2HSV)

    # show image
    cv.imshow("sample",sample)
    cv.imshow("target",target)

    roiHist = cv.calcHist([roi_hsv],[0,1],None,[36,48],[0,180,0,256])
    cv.normalize(roiHist,roiHist,0,255,cv.NORM_MINMAX)
#void cv::normalize(InputArry src,InputOutputArray dst,double alpha=1,double beta=0,int norm_type=NORM_L2,int dtype=-1,InputArray mark=noArry())
    # src:输入数组;
    # dst:输出数组,数组的大小和原数组一致;
    # alpha:用来规范值,2.规范范围,并且是下限;
    # beta:只用来规范范围并且是上限;
    # norm_type:归一化选择的数学公式类型;
    # dtype:当为负,输出在大小深度通道数都等于输入,当为正,输出只在深度与输如不同,不同的地方游dtype决定;
    # mark:掩码。选择感兴趣区域,选定后只能对该区域进行操作。
    dst = cv.calcBackProject([target_hsv],[0,1],roiHist,[0,180,0,256],1)
    
    cv.imshow("backProjectionDemo",dst)

src = cv.imread("../images/lena.jpg")
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE)
cv.imshow('input image', src)
hist2d_dmeo(src)
#back_project_demo()
cv.waitKey(0)  # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口

cv.destroyAllWindows()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值