Opencv笔记(二十)——直方图(二)

Stella981
• 阅读 689

直方图均衡化

原理:

   想象一下如果一副图像中的大多是像素点的像素值都集中在一个像素值范围之内会怎样呢?例如,如果一幅图片整体很亮,那所有的像素值应该都会很高。但是一副高质量的图像的像素值分布应该很广泛。所以你应该把它的直方图做一个横向拉伸(如下图),这就是直方图均衡化要做的事情。通常情况下这种操作会改善图像的对比度。直方图均衡化后面潜在的数学原理是一个分布(输入的亮度直方图)被映射到另一个分布(一个更宽,理想统一的亮度值分布),映射函数是一个累积分布函数。对于连续分布,结果将是准确的均衡化。在equalizeHist中,原始图像及目标图像必须是单通道,大小相同的8位图像,对于彩色图像,必须先将每个通道分开,再分别进行直方图均衡化处理,然后将通道合并形成新的图像。

Opencv笔记(二十)——直方图(二)

# coding=utf-8
import cv2
import numpy as np

img = cv2.imread("/home/wl/4.jpg",0)
equ = cv2.equalizeHist(img)#灰度图像直方图均衡化
while(1):
    cv2.imshow("2",equ)
    cv2.imshow("1", img)
    cv2.imwrite("/home/wl/baocun1.jpg", img)
    cv2.imwrite("/home/wl/baocun2.jpg", equ)
    k = cv2.waitKey(1) & 0XFF
    if k==ord('q'):
        break;
cv2.destroyAllWindows()

原图:

Opencv笔记(二十)——直方图(二)

均值化后的图:

Opencv笔记(二十)——直方图(二)

CLAHE 有限对比适应性直方图均衡化

的确在进行完直方图均衡化之后,图片背景的对比度被改变了。但可能会由于太亮而丢失了很多信息。造成这种结果的根本原因在于这幅图像的直方图并不是集中在某一个区域。为了解决这个问题,我们需要使用自适应的直方图均衡化。这种情况下,整幅图像会被分成很多块这些小块被称为“tiles”(在 OpenCV 中 tiles 的大小默认是 8x8),然后再对每一个小块分别进行直方图均衡化(跟前面类似)。所以在每一个的区域中,直方图会集中在某一个小的区域中(除非有噪声干扰)。如果有噪声的话,噪声会被放大。为了避免这种情况的出现要使用对比度限制。对于每个小块来说,如果直方图中的 bin 超过对比度的上限的话,就把其中的像素点均匀分散到其他 bins 中,然后在进行直方图均衡化。最后,为了去除每一个小块之间“人造的”(由于算法造成)边界,再使用双线性差值,对小块进行缝合。

import cv2

img = cv2.imread("/home/wl/4.jpg",0)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(img)

效果图:

Opencv笔记(二十)——直方图(二)

2D直方图

  在前面的部分我们介绍了如何绘制一维直方图,之所以称为一维,是因为我们只考虑了图像的一个特征:灰度值。但是在 2D 直方图中我们就要考虑两个图像特征。对于彩色图像的直方图通常情况下我们需要考虑每个的色调(Hue)和饱和度(Saturation)。根据这两个特征绘制 2D 直方图。

使用函数 cv2.calcHist(),函数的参数要做如下修改:

  • channels=[0,1] 因为我们需要同时处理 H 和 S 两个通道。

  • bins=[180,256]H 通道为 180,S 通道为 256。

  • range=[0,180,0,256]H 的取值范围在 0 到 180,S 的取值范围在 0 到 256。

    coding=utf-8

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

    img = cv2.imread("/home/wl/4.jpg") hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV) hist = cv2.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256]) plt.imshow(hist,interpolation = 'nearest')#nearest插值参数 plt.show()

Opencv笔记(二十)——直方图(二)

Numpy 中 2D 直方图

Numpy 同样提供了绘制 2D 直方图的函数:np.histogram2d()。

# coding=utf-8
import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread("/home/wl/4.jpg")
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
h=hsv[:,:,0]
s=hsv[:,:,1]
hist, xbins, ybins = np.histogram2d(h.ravel(),s.ravel(),[180,256],[[0,180],[0,256]])
plt.imshow(hist,interpolation = 'nearest')
plt.show()

Opencv笔记(二十)——直方图(二)

直方图反向投影

原理:

   反向投影可以用来做图像分割,寻找感兴趣区间。它会输出与输入图像大小相同的图像,每一个像素值代表了输入图像上对应点属于目标对象的概率,简言之,输出图像中像素值越高的点越可能代表想要查找的目标。直方图投影经常与camshift(追踪算法)算法一起使用。算法实现的方法,首先要为包含我们感兴趣区域的图像建立直方图(样例要找一片草坪,其他的不要)。被查找的对象最好是占据整个图像(图像里全是草坪)。最好使用颜色直方图,物体的颜色信息比灰度图像更容易被分割和识别。再将颜色直方图投影到输入图像查找目标,也就是找到输入图像中每一个像素点的像素值在直方图中对应的概率,这样就得到一个概率图像,最后设置适当的阈值对概率图像进行二值化。

OpenCV 提供的函数 cv2.calcBackProject() 可以用来做直方图反向投影。它的参数与函数 cv2.calcHist 的参数基本相同。其中的一个参数是我们要查找目标的直方图。同样再使用目标的直方图做反向投影之前我们应该先对其做归一化处理。返回的结果是一个概率图像,我们再使用一个圆盘形卷积核对其做卷操作,最后使用阈值进行二值化。下面就是代码和结果:

# coding=utf-8
import cv2
import numpy as np
#roi图片,就想要找的的图片
roi = cv2.imread('1.jpg')
hsv = cv2.cvtColor(roi,cv2.COLOR_BGR2HSV)

#目标搜索图片
target = cv2.imread('2.jpg')
hsvt = cv2.cvtColor(target,cv2.COLOR_BGR2HSV)

#计算目标直方图
roihist = cv2.calcHist([hsv],[0,1],None,[180,256],[0,180,0,256])
#归一化,参数为原图像和输出图像,归一化后值全部在2到255范围
cv2.normalize(roihist,roihist,0,255,cv2.NORM_MINMAX)
dst = cv2.calcBackProject([hsvt],[0,1],roihist,[0,180,0,256],1)


#卷积连接分散的点
disc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
dst = cv2.filter2D(dst,-1,disc)

ret,thresh = cv2.threshold(dst,50,255,0)
#使用merge变成通道图像
thresh = cv2.merge((thresh,thresh,thresh))

#蒙板
res = cv2.bitwise_and(target,thresh)
#矩阵按列合并,就是把target,thresh和res三个图片横着拼在一起
res = np.hstack((target,thresh,res))

cv2.imwrite('res.jpg',res)
#显示图像
cv2.imshow('1',res)
cv2.waitKey(0)

原图:

Opencv笔记(二十)——直方图(二) 1.jpg Opencv笔记(二十)——直方图(二) 2.jpg

结果:

Opencv笔记(二十)——直方图(二)

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
10、图像的几何变换——平移、镜像、缩放、旋转、仿射变换
1.几何变换的基本概念  图像几何变换又称为图像空间变换,它将一副图像中的坐标位置映射到另一幅图像中的新坐标位置。我们学习几何变换就是确定这种空间映射关系,以及映射过程中的变化参数。图像的几何变换改变了像素的空间位置,建立一种原图像像素与变换后图像像素之间的映射关系,通过这种映射关系能够实现下面两种计算:1.原图像任意像素
Stella981 Stella981
3年前
Android OpenCV(二十):高斯滤波
高斯滤波高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。高斯滤波的具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值
Stella981 Stella981
3年前
Python实现图像信息隐藏
Python实现图像信息隐藏之前学习密码学的时候老师有提到过『信息隐藏』,现在用图像的方法尝试一下。思想是:把信息藏到RGB通道中的B通道,然后利用奇偶性可以恢复过来原理从源图中提取文字图像信息,记录这个文字图像信息像素点在图像矩阵中的位置对载体图片进行预处理,将B通道的像素值全部设置
Stella981 Stella981
3年前
C++ OpenCV特征提取之积分图计算
前言什么是积分图像积分图像的定义:取图像左上侧的全部像素计算累加和,并用这个累加和替换图像中的每一个像素,使用这种方式得到的图像称为积分图像。为什么要用积分图像直方图的计算方法为遍历图像的全部像素并累计每个强度值在图像中出现的次数。有时仅需要计算图像中某个特定区域的直方图,而
Stella981 Stella981
3年前
Android OpenCV(十八):均值滤波
均值滤波均值滤波也称为线性滤波,其采用的主要方法为邻域平均法。线性滤波的基本原理是用均值代替原图像中的各个像素值,即对待处理的当前像素点(x,y),选择一个模板,该模板由其近邻的若干像素组成,求模板中所有像素的均值,再把该均值赋予当前像素点(x,y),作为处理后图像在该点上的灰度g(x,y),即g(x,y)∑f(x,y)/mm为该模板中
Stella981 Stella981
3年前
OpenCV阈值化处理
图像的阈值化就是利用图像像素点分布规律,设定阈值进行像素点分割,进而得到图像的二值图像。图像阈值化操作有多种方法,常用方法有经典的OTSU、固定阈值、自适应阈值、双阈值及半阈值化操作。这里对各种阈值化操作进行一个总结。OTSU阈值化在阈值化处理中,常用的算法就是OTSU。发明人是NobuyukiOstu。这种二值化操作阈值的选取非常重要,阈
Stella981 Stella981
3年前
Python OpenCV实例:图像直方图均衡化(数学公式简单实现)
coding:utf8'''直方图均衡化作用:通常用来增加图像局部对比度,尤其在图像的有用数据的对比度相当接近时,通过直方图均衡化,图像的亮度可以更好地在直方图上分布基本思想:把原始图像的直方图变换为均匀分布的形式,增加了像素灰度值的动态范围,从而增强图像的整