一、直方图:查找、绘制和分析


直方图可以反映一张图片中,每个范围内像素值的多少。比如上图中中间调的像素比较集中,也就是说,(我们不看图片都知道)这张图片的像素,多数集中在这个值左右。在PS,LR等等修图软件里面,提供直方图,可以让创作者清楚地知道过曝面积和死黑面积大概有多少。同样在相机里,也有直方图,优秀的摄影师,可以根据直方图来调节相机参数,使得照片曝光处于最佳状态哈哈哈。(广告位留给自己:有兴趣的朋友,欢迎到我的pott:Mr_Zhou,ID:2100190切磋交流,嘻嘻)

寻找直方图

OpenCV:cv.calcHist(images,channels,mask,histSize,ranges [,hist [,accumulate]])

img=cv.imread("gh.jpg")
hist=cv.calcHist([img],[0],None,[256],[0,256])

numpy:

hist,bins = np.histogram(img.ravel(),256,[0,256])
hist = np.bincount(img.ravel(),minlength = 256)#比上面一条快10倍左右

注意: OpenCV函数比np.histogram()快大约40倍。因此,尽可能使用OpenCV函数

绘制直方图

**matplotlab:**使用matplotlib.pyplot.hist()

img=cv.imread("gh.jpg",0)
plt.subplot(122),plt.hist(img.ravel(),256,[0,256]),plt.title("hist")
plt.subplot(121),plt.imshow(img),plt.title("Original img")
plt.gray()
plt.show()


彩色图片,可以使用matplotlib的法线图,比较容易区分。(实际上用的是OpenCV的方法找到的直方图。)

img=cv.imread("gh.jpg")
color=("b","g","r")
plt.subplot(121)
for i,col in enumerate(color):histr=cv.calcHist([img],[i],None,[256],[0,256])plt.plot(histr,color=col)plt.xlim([0,256])
plt.title("color_hist")
plt.subplot(122),plt.imshow(img),plt.title("Original")
plt.show()


OpenCV:

img=cv.imread("gh.jpg",0)
hist=cv.calcHist([img],[0],None,[256],[0,256])
plt.subplot(121),plt.imshow(img),plt.title("Original")
plt.subplot(122),plt.plot(hist),plt.xlim([0,256]),plt.title("Hist")
plt.gray()
plt.show()

使用掩码

掩码可以使我们快速观察图片指定区域的直方图,而不需要裁切。

#创建掩码矩阵,要求和目标图片一致
mask=np.zeros(img.shape[:2],np.uint8)
#将不需要遮掩的区域,取值为255,即白色
mask[200:800,600:1500]=255
#掩码与图片加和,得到不需要掩码的区域
masked_img=cv.bitwise_and(img,img,mask=mask)
#用OpenCV方法获得直方图
hist_full=cv.calcHist([img],[0],None,[256],[0,256])
hist_mask=cv.calcHist([img],[0],mask,[256],[0,256])plt.subplot(231),plt.imshow(img,"gray"),plt.title("Original")
plt.subplot(232),plt.imshow(mask,"gray"),plt.title("Mask")
plt.subplot(233),plt.imshow(masked_img,"gray"),plt.title("Masked image")
plt.subplot(234),plt.plot(hist_full),plt.xlim([0,256]),plt.title("Hist full")
plt.subplot(236),plt.plot(hist_mask),plt.xlim([0,256]),plt.title("Hist masked")
plt.show()

(果然,大部分好的图片在主视觉区域内都有优秀的直方图哈哈)

二、直方图均衡

理论

有时候,我们得到的照片,总会因为某些原因,比如说曝光过度,光源太强或者太弱,或者太过于集中在某个值范围内,那么我们可以重新布局每个像素值中像素的多少,来平衡这种情况,直方图均衡就是做这么一件事。在手机或者电脑上修过图片的人都知道,我们改变图片白平衡的时候,图片的直方图会跟着改变,这就是在做直方图的均衡操作。

要调整直方图,我们需要先知道像素分布的范围比例。

img=cv.imread("gh.jpg",0)
#直方图设置
hist,bins=np.histogram(img,256,[0,256])
#cdf作为像素的累计和
cdf=hist.cumsum()
#归一化cdf
cdf_normalized=cdf*float(hist.max())/cdf.max()plt.subplot(121)
plt.plot(cdf_normalized,color="b")
plt.hist(img.flatten(),256,[0,256],color="r")
plt.xlim([0,256])
plt.legend(("cdf","histogram"),loc="best")
plt.subplot(122),plt.imshow(img),plt.title("Original")
plt.gray()
plt.show()

大概有一半的像素,在黑线左边。我们可以看到,曲线向上拱起。做均衡,也可以理解为,把这条曲线拉直(当然实际上大部分时候我们不会真的把它拉成直线,这样看起来照片会没有什么特色哈哈)。

使用掩码数组,对图像进行操作,所有操作都是在非掩码元素下执行的,所以掩码元素不会发生变化。比如说,某个地方特别亮,掩码就不覆盖那片区域的元素,我们在接下来均衡化的时候,就对这部分区域进行修改均衡。和前面 使用掩码 这个逻辑是一样的,只操作,非掩码区像素。

#创建掩码,分布和cdf相同
cdf_m=np.ma.masked_equal(cdf,0)
cdf_m=(cdf_m-cdf_m.min())*255/(cdf_m.max()-cdf_m.min())
cdf=np.ma.filled(cdf_m,0).astype("uint8")
img2=cdf[img]
hist1,bins1=np.histogram(img2,256,[0,256])
cdf_normalized1=cdf*float(hist1.max())/cdf.max()plt.subplot(223),plt.plot(cdf_normalized1,color="y"),plt.hist(img2.flatten(),256,[0,256],color="b"),plt.xlim([0,256]),plt.legend(("cdf","histogram"),loc="best")
plt.subplot(224),plt.imshow(img2),plt.title("Original"),plt.gray()
plt.show()

和原图对比:相对于原图,均衡化之后的图片明暗更统一。

放大后,曲线明显被“拉直”,图片黑暗的地方被提亮。

OpenCV中的均衡

OpenCV中使用cv.equalizeHist()语句进行直方图均衡。

img=cv.imread("gh.jpg",0)
equ=cv.equalizeHist(img)
#并排两个图像
res=np.hstack((img,equ))
plt.subplot(),plt.imshow(res,"gray"),plt.title("Res")
plt.show()

左边使原图,右边是均衡化以后的图像,明显看见,暗部被提亮,但是在明暗对比较强的地方,变化不大。甚至在某些亮部,某些细节被抹去,导致重要的信息丢失。

自适应直方图均衡 CLAHE

为了解决亮部再次被提亮,导致很多的细节信息丢失,我们需要在均衡图片直方图的时候,希望它能自适应地去操作。

我们使用一个滤波器,对图片进行过滤,在次滤波器包含的元素中绘制直方图。但是图片中总会出现噪声,所以我们设定一个对比度阈值,超过这个阈值,就裁剪掉这个地方的像素并向其它地方均匀分配。

在OpenCV中,默认使用的titleSize是8X8的过滤器,阈值为40。

img=cv.imread("gh.jpg",0)
#自适应均衡,(对比度,过滤器)
clache=cv.createCLAHE(clipLimit=2.0,tileGridSize=(8,8))
#用到图片中
cll=clache.apply(img)equ=cv.equalizeHist(img)
res=np.hstack((img,equ,cll))
plt.subplot(),plt.imshow(res,"gray"),plt.title("Original-Normal-CLACHE")
plt.show()

从左往右,分别是原图-普通均衡-自适应均衡,可以看出,自适应均衡不会再将亮部细节抹去,反而加强了效果,同时暗部细节也突出,明暗对比强烈的同时,保证整体的亮度均衡。

三、二维直方图

一维直方图,检测的是图片像素的灰度值,所以它的图片输出只能是黑白色。
二维直方图,检测的是图像每个像素的饱和度和色相,通常,它是用于检测有颜色的图片。

OpenCV中的二维直方图

二维直方图,也是采用cv.equalizeHist()这个函数。在开始之前,我们在前面已经知道,OpenCV采用的颜色是BRG,我们需要将其转换为HSV颜色通道。其中,H的取值范围是0-180,S和V的取值范围是0-256。

在这里,色相和饱和度,就是H和S,所以,
channel=[0,1]两个通道
bins=[180,256]对应两个通道最大值
range=[0,180,0,156]对应两个通道的取值范围

img=cv.imread("gh.jpg")
#颜色转换
hsv=cv.cvtColor(img,cv.COLOR_BGR2HSV)
#获得二维直方图
hist=cv.calcHist([hsv],[0,1],None,[180,256],[0,180,0,256])
#matplotlab显示方式,插值法使用邻近值可以获得更好的效果
plt.subplot(),plt.imshow(hist,interpolation="nearest")
plt.show()
#OpenCV的显示方式
cv.imshow("hist",hist)
cv.waitKey(0)

matplotlab的显示方式,横轴表示饱和度S,纵轴表示色相H。蓝色的像素点表示图片中有蓝色。

OpenCV显示方式,主要存在三种颜色,黑色占多,然后是蓝色,最后是白色。如果不是对色相值有所了解的话,这张图上并不能获取任何信息,因为它是黑白的。

Numpy中的二维直方图

img=cv.imread("gh.jpg")
hsv=cv.cvtColor(img,cv.COLOR_BGR2HSV)
h=hsv[0:1]
s=hsv[1:2]
hist,xbins,ybins=np.histogram2d(h.ravel(),s.ravel(),[180,256],[[0,180],[0,256]])
plt.subplot(),plt.imshow(hist,interpolation="nearest")
plt.show()
cv.imshow("hist",hist)
cv.waitKey(0)

效果和上面的不太相同,它的分布让我比较困惑。存疑。

四、直方图反投影

反投影可以获得我们感兴趣的区域(像素),类似于前面的颜色查找,但是我们在这里输入的不再是颜色,而是一张图片,在另一张图片里查找这张图片相关的像素区域,然后进行掩码操作。

roi=cv.imread("gh1.jpg")
hsv=cv.cvtColor(roi,cv.COLOR_BGR2HSV)
target=cv.imread("gh.jpg")
hsvt=cv.cvtColor(target,cv.COLOR_BGR2HSV)
#获取直方图
roihist=cv.calcHist([hsv],[0,1],None,[180,256],[0,180,0,256])
#直方图的归一化
cv.normalize(roihist,roihist,0,255,cv.NORM_MINMAX)
#使用反传算法
dst=cv.calcBackProject([hsvt],[0,1],roihist,[0,180,0,256],1)
#卷积操作
disc=cv.getStructuringElement(cv.MORPH_ELLIPSE,(5,5))
cv.filter2D(dst,-1,disc,dst)
#用阈值加和
ret,thresh=cv.threshold(dst,50,255,0)
thresh=cv.merge((thresh,thresh,thresh))
res=cv.bitwise_and(target,thresh)
res=np.vstack((target,thresh,res))
plt.subplot(121),plt.imshow(roi),plt.title("Select area")
plt.subplot(122),plt.imshow(res),plt.title("Result")
plt.show()

可以和前面颜色寻找作比较。

OpenCV-Python 笔记(五)直方图相关推荐

  1. python opencv 直方图均衡_详解python OpenCV学习笔记之直方图均衡化

    本文介绍了python OpenCV学习笔记之直方图均衡化,分享给大家,具体如下: 官方文档 – https://docs.opencv.org/3.4.0/d5/daf/tutorial_py_hi ...

  2. opencv学习笔记五--文件扫描+OCR文字识别

    opencv学习笔记五--文件扫描+OCR文字识别 文件扫描 定义函数 边缘检测 获取轮廓 变换 OCR文字识别 环境配置 代码 文件扫描 # 导入工具包 import numpy as np imp ...

  3. OpenCV学习笔记五:直方图

    图像由不同颜色值的像素组成,像素值在图像中的分布情况是图像的一个重要特征. 一.计算图像的直方图 直方图是一个简单的表,它给出了图像中各个像素值的数目(归一化后则为相应的比例),在OpenCV中可以使 ...

  4. OpenCV—python 颜色直方图与直方图均衡化

    文章目录 一.颜色直方图 1.1 使用opencv展示直方图 1.2 使用matplotlib绘制 二.直方图均衡化 2.1 全局直方图均衡化与自适应均衡化 2.2 使用查找表来拉伸直方图 2.3 直 ...

  5. OpenCV学习笔记五-图像混合

    将两张图片混合 P6 图像混合 #include<iostream> #include<opencv2/opencv.hpp>using namespace std; usin ...

  6. opencv 学习笔记五 二维离散卷积

    卷积的用途: 卷积主要用于降噪处理,是降噪处理的一种方式: 二维离散卷积包含高斯滤波,平滑滤波,中值滤波,以及能保证图像边缘的双边滤波和导向滤波算法等: 一.了解噪声的来源以及噪声的分类: 图像中难免 ...

  7. python笔记图片_图像 opencv - python笔记

    默认 基础变换 模糊 锐化 色彩分层 傅里叶变换 高通低通 图像序列转换为视频 人脸识别 import opencv as cv2 img = cv2.imread('test.jpg') # imw ...

  8. opencv学习笔记五十三:训练自己的级联分类器

    训练工作主要分为如下几步: 加载训练环境 制作训练数据集 获取样本路径列表 生成正样本描述文件(.vec) 训练人脸分类器 使用分类器进行人脸检测 加载训练环境  训练过程主要依靠OpenCV自带的两 ...

  9. opencv学习笔记五十八:grabCut抠图

    基本步骤: 基于交互式界面由用户选择前景区域: 定义一个单通道的输出掩码,0为背景,1为前景,2为可能的背景,3为可能的前景: grabCut抠图:将输出结果与可能的前景作比较得到可能的前景: 定义三 ...

  10. python笔记(五) - 获取对象的引用

    1,使用 getattr 函数,可以得到一个直到运行时才知道名称的函数的引用. >>> li = ["Larry", "Curly"] > ...

最新文章

  1. C# 启动外部程序的几种方法
  2. Android学习笔记之Intent
  3. 用法 the_【课堂】a、an、the的用法
  4. CS中常用转义符与@符号的作用
  5. 利用正则表达式截取特定字符中间字符
  6. 洛谷入门题P1046、P1047、P1427、P1428、P2141、P1567题解(Java语言描述)
  7. Gainlo 面试指南 翻译完成
  8. 水冒泡了几度_冒泡和选择排序详解
  9. 强化学习:7基于直接策略搜索的强化学习⽅法 之 策略梯度
  10. git删除分支_程序员必须要掌握的 Git 使用技巧
  11. 【毕业设计】JAVA网络通信系统的研究与开发(论文+源代码+开题报告)
  12. xpath获取标签的属性值_[Selenium]12.加餐: 如何手写xpath
  13. 三星i9158刷机教程
  14. 惠普打印机换硒鼓图解_hp硒鼓怎么安装 hp硒鼓安装方法这图文教程】
  15. [Excel函数]--intercept函数
  16. 利用Xposed秒抢微信红包
  17. c++缺省值 缺省参数
  18. 随机身份证号码计算年龄
  19. masked_fill_() - masked_fill() - v1.5.0
  20. 基于FlashWavRecorder实现IE11浏览器录音后用科大讯飞转文字

热门文章

  1. 02英语学习笔记01电影《遇见你之前》句子摘抄
  2. CSS如何使用字体图标
  3. 018历史记录画笔工具与历史记录艺术画笔工具
  4. DSP与FPGA之EMIF接口的调试说明
  5. 【还魂之迷失曼谷】下载
  6. 微信小程序监听屏幕上滑下滑事件
  7. 集成多路模拟开关的应用技巧
  8. android beam开关,打开灯泡开关,竟然放出了电影
  9. HTML <b>加粗与<strong>加粗标签区别
  10. Git | 面试官问你 Git 原理,你能回答得出来吗?