PIL: 创建图像颜色亮度的一维直方图?

3 投票
2 回答
20203 浏览
提问于 2025-04-16 07:07

我正在写一个脚本,基本上需要做到以下几点:

  • 把图片变成灰度图(或者二值图,我会试试这两种,看哪种效果更好)。
  • 处理每一列,计算出每一列的净强度值。
  • 把结果输出成一个有序列表。

用ImageMagick可以很简单地做到这一点(不过你需要一些Linux工具来处理输出的文本),但我现在还不太清楚怎么用Python和PIL来实现。

这是我目前的进展:

from PIL import Image

image_file = 'test.tiff'

image = Image.open(image_file).convert('L')

histo = image.histogram()
histo_string = ''

for i in histo:
  histo_string += str(i) + "\n"

print(histo_string)

这个输出了一些东西(我想把结果画成图),但看起来和ImageMagick的输出完全不一样。我是用这个来检测扫描书籍的接缝和内容。

感谢任何帮助我的人!


我现在有一个(看起来不太好)的解决方案,可以用:

from PIL import Image
import numpy

def smoothListGaussian(list,degree=5):
  window=degree*2-1
  weight=numpy.array([1.0]*window)
  weightGauss=[]

  for i in range(window):
    i=i-degree+1
    frac=i/float(window)
    gauss=1/(numpy.exp((4*(frac))**2))
    weightGauss.append(gauss)

  weight=numpy.array(weightGauss)*weight
  smoothed=[0.0]*(len(list)-window)

  for i in range(len(smoothed)):
    smoothed[i]=sum(numpy.array(list[i:i+window])*weight)/sum(weight)

  return smoothed

image_file = 'verypurple.jpg'
out_file = 'out.tiff'

image = Image.open(image_file).convert('1')
image2 = image.load()
image.save(out_file)

intensities = []

for x in xrange(image.size[0]):
  intensities.append([])

  for y in xrange(image.size[1]):
    intensities[x].append(image2[x, y] )

plot = []

for x in xrange(image.size[0]):
  plot.append(0)

  for y in xrange(image.size[1]):
    plot[x] += intensities[x][y]

plot = smoothListGaussian(plot, 10)

plot_str = ''

for x in range(len(plot)):
  plot_str += str(plot[x]) + "\n"

print(plot_str)

2 个回答

7

根据PIL的文档histogram这个功能会给你一份列表,里面记录了图像中每种像素值的数量。如果你有一张灰度图像,那么它会有256种不同的像素值,这些值的范围是从0到255。而通过image.histogram得到的列表会有256个条目。

11

我看到你在使用numpy。首先,我会把灰度图像转换成一个numpy数组,然后用numpy沿着某个轴进行求和。额外提示:当你把平滑函数修改为接受一维数组作为输入时,你会发现它运行得快很多。

>>> from PIL import Image
>>> import numpy as np
>>> i = Image.open(r'C:\Pictures\pics\test.png')
>>> a = np.array(i.convert('L'))
>>> a.shape
(2000, 2000)
>>> b = a.sum(0) # or 1 depending on the axis you want to sum across
>>> b.shape
(2000,)

撰写回答