【问题标题】:Create Image Histogram Manually and Efficiently in Python在 Python 中手动高效地创建图像直方图
【发布时间】:2017-02-25 15:32:03
【问题描述】:

我想编写无需使用内置 Matplotlib hist 函数即可显示图像直方图的代码。

这是我的代码:

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

def manHist(img):
   row, col = img.shape # img is a grayscale image
   y = np.zeros((256), np.uint64)
   for i in range(0,row):
      for j in range(0,col):
         y[img[i,j]] += 1
   x = np.arange(0,256)
   plt.bar(x,y,color="gray",align="center")
   plt.show()

def main():
   img = cv.imread("C:/Users/Kadek/Documents/MATLAB/2GS.jpg")
   manHist(img)

main()

我的问题是,有没有更有效的方法来制作像素值频率数组而不使用 for 循环?

【问题讨论】:

  • 除了遍历图像中的每个值之外别无他法,尽管矢量化的 numpy 解决方案会快几个数量级
  • 所以,您没有像以前那样使用通道的第三轴:y[img[i,j]]?
  • 您可以为此使用collections.Counter,尽管这对您来说可能不够“手动”。
  • @FranciscoCouzo 感谢您的建议,但我不明白如何使用矢量化 numpy。
  • @Divakar 是的,这是一张灰度图像。

标签: python opencv numpy image-processing matplotlib


【解决方案1】:

基于 NumPy 的矢量化解决方案将使用 np.bincount -

out = np.bincount(img.ravel(),minlength=256)

基于.sum()的另一种矢量化方法-

out = (img.ravel() == np.arange(256)[:,None]).sum(1)

运行示例以验证结果 -

In [155]: # Input image (512x512) as array
     ...: img = np.random.randint(0,255,(512,512))
     ...: 
     ...: # Original code
     ...: row, col = img.shape
     ...: y = np.zeros((256), np.uint64)
     ...: for i in range(0,row):
     ...:     for j in range(0,col):
     ...:         y[img[i,j]] += 1
     ...:         

In [156]: out1 = np.bincount(img.ravel(),minlength=256)

In [157]: out2 = (img.ravel() == np.arange(256)[:,None]).sum(1)

In [158]: np.allclose(y,out1)
Out[158]: True

In [159]: np.allclose(y,out2)
Out[159]: True

【讨论】:

  • 在我的代码中都返回 false。我写的和你的一模一样。
  • @KadekDwiBudiUtama 您还没有在 cmets 中回答问题,是否应该改为 row, col = img.shape
  • 哦,对不起。仅使用 1 个频道后即可使用!谢谢!
  • @KadekDwiBudiUtama 请使用该更正更新问题中的代码。
  • @KadekDwiBudiUtama 冒昧地自己进行编辑。如果不连贯,请随时进行其他编辑。
猜你喜欢
  • 2011-10-30
  • 2016-07-11
  • 2022-01-21
  • 1970-01-01
  • 1970-01-01
  • 2013-02-06
  • 2011-03-03
  • 1970-01-01
相关资源
最近更新 更多