OpenCV 3d直方图3轴直方图?

时间:2017-09-29 23:19:54

标签: opencv

从OpenCV calcHist()返回的3d直方图究竟是什么?

对于1d直方图,我知道:
- x轴表示我想要的箱子(为简单起见,可以说0-255 - 灰度颜色值) - y轴表示具有该bin /颜色值的像素数。

对于3d直方图...我是否正确:
- 有3个x轴阵列?每个颜色通道一个(在我的情况下是b,g,r)?
- 有3个y轴阵列?上面的每个一个?

OR

  • 仍然只有1 x和y轴。但x轴表示b * g * r的串联(?),y轴告诉我有多少像素的颜色为b * g * r?

如果是第一个场景,OpenCV是否有办法: - 产生一个唯一的数字来表示颜色(十六进制?或组合b * g * r)?
- 生成3通道图像的直方图,其中x轴区域代表上面的唯一颜色编号,y轴告诉我有多少像素具有该颜色?
- 据推测,这比具有255个bin的3d直方图计算效率更高?

1 个答案:

答案 0 :(得分:0)

OpenCV' calcHist()可以计算任意**个图像/通道的直方图。返回的直方图具有与输入图像中的通道数一样多的轴,并且每个轴具有与为该通道指定的区间一样多的值。例如,假设你有一个RGBD图像;也就是说,四个通道:一个用于红色,蓝色,绿色,另一个用于深度。如果您想以任何理由计算这种图像的直方图,OpenCV可以让您:

import cv2
import numpy as np

img = cv2.imread('lane.jpg')
img = np.dstack([img, img[:, :, 0]])
print('Input image shape:', img.shape)
n_channels = img.shape[2]
channels = list(range(n_channels))
sizes = [8,]*n_channels
ranges = [0, 255]*n_channels
hist = cv2.calcHist(img, channels, None, sizes, ranges)
print('Output histogram shape: ', hist.shape)
  

输入图像形状:(540,960,4)

     

输出直方图形状:(8,8,8,8)

注意在np.dstack([img, img[:, :, 0]])行中我只是将第一个频道添加到图像的末尾作为第四个频道。您可以修改程序以在通道深度为9的图像上运行,并获得输出9D直方图:

img = cv2.imread('lane.jpg')
img = np.dstack([img, img, img])
print('Input image shape:', img.shape)
n_channels = img.shape[2]
channels = list(range(n_channels))
sizes = [8,]*n_channels
ranges = [0, 255]*n_channels
hist = cv2.calcHist(img, channels, None, sizes, ranges)
print('Output histogram shape: ', hist.shape)
  

输入图像形状:(540,960,9)

     

输出直方图形状:(8,8,8,8,8,8,8,8,8)

此处唯一的修改是dstack线,我只是将图像堆叠三次以创建一个包含9个通道的图像。

对于多声道阵列,您会错误地考虑轴。您不应该将它们称为xy等,而应将它们视为来自每个频道的bins,即ch1bins, ch2bins, ...等等。如果你拍摄单通道图像的直方图,那么肯定;当我绘制时,x - 轴有你的箱子而y - 轴有你的计数,但这只是一种绘制它们的方法。真的,你有一系列的箱子和一系列的计数。如果您绘制双通道图像的直方图并使用3D条形图将其可视化,则x - 轴具有分档,但y - 轴和{{1}也是如此。在这种情况下,轴有计数。 z轴将具有第一个通道的区间,x轴将具有第二个通道的区间。如果你有一个三通道图像,然后在一个图中可视化,所有三个轴都是与每个通道相对应的箱子,因此你必须用其他东西可视化每个箱子中的数量,比如一个该垃圾箱的标记,或者您必须根据标记的强度或其他颜色对标记着色。

OpenCV docs for calcHist()给出了一个2D直方图(即双通道)的示例,您可以在其中分析色调和饱和度值的直方图。这意味着对于给定范围的色调和饱和度值(例如0到32之间的色调,以及144到176之间的饱和度),您可以看到落在该范围内的像素数。

对于3D直方图的示例,您可以check out some I've plotted。我没有将OpenCV用于直方图,因为......在你提出这个问题之前,我实际上并不知道它可以做3D直方图。但y可以完全相同的D维直方图,如OpenCV。在这些图中,标记的颜色对应于bin表示的实际颜色,标记大小有点对应于每个bin中的值的数量。

如果我拍了一张3D直方图,我们只想说我们想知道每个频道的深色和亮度。所以我只需要一个直方图,每个频道有2个频段。那我的箱子就是:

  • 频道0:numpy
  • 第1频道:[0, 127], [128, 255]
  • 第2频道:[0, 127], [128, 255]

获取值为[0, 127], [128, 255]的像素。这将对应于在通道0的bin 0,通道1的bin 1和通道3的bin 0中。有多少总可能性?像素可以放在箱子中:

  • 0,0,0
  • 0,0,1
  • 0,1,0
  • 0,1,1
  • 1,0,0
  • 1,0,1
  • 1,1,0
  • 1,1,1

所以有8种可能性。如果我在3空间中绘制所有RGB值,则将这些轴中的每一个分成两个,得到8个不同的直方图箱。然后我只计算这8个箱子中的每个箱子中的数字,这就是直方图。所以看看上面的列表,这个简单的直方图会告诉我有多少暗像素(对应于二进制0,0,0),有多少个亮像素(对应1,1,1),多少是绿色像素有(0,1,0)等等。确实这就是OpenCV给出的:

[0, 255, 0]
  

输入图像形状:(540,960,3)

     

输出直方图形状:(2,2,2)

多通道直方图的重点是要确定每个通道独立在一定值范围内的像素数。希望这篇文章已经清除了一些内容!

**注意:请勿使用频道数较多的小型垃圾箱尺寸......您将很快耗尽内存。