【问题标题】:'Stretching' histograms (levels) in Numpy, PythonNumpy,Python中的“拉伸”直方图(级别)
【发布时间】:2019-08-28 22:13:34
【问题描述】:

我有灰度图像,其背景是 0-255 色阶的中白颜色,平均像素颜色值为 246;前景为中灰色,平均像素颜色值为 186。

我想将高于 246 的每个像素“移动”到 255,低于 186 的每个像素都“移动”到零,并“拉伸”介于两者之间的所有像素。是否有任何现成的算法/过程可以在 numpy 或 python 中执行此操作,或者必须“手动”计算新的级别/直方图(就像我到目前为止所做的那样)?

这相当于在 Gimp 或 Photoshop 中打开关卡窗口并分别使用白色和黑色吸管选择我们想要制作为白色的较亮区域和我们想要制作为黑色的较暗区域:应用程序修改相应的级别/直方图(“拉伸”所选点之间的值)。

我正在尝试的一些图片:

【问题讨论】:

  • 请展示您尝试过的内容,可能带有图片。
  • 发生了很多事情,但我试图将其总结为几张截图。
  • 注:我这样做的原因是因为现有算法会生成文本,虽然是黑色的,但缺少补丁和间隙。不过,OpenCv 设法很好地找到计数,我使用它们来创建定义哪些区域应该被平均的掩码,正是它给出了要上下敲击的两个值..
  • 您可以按照您的描述进行操作:(1) 将高于 246 的所有像素阈值设置为 255 (2) 将低于 186 的所有像素阈值为零 (3) 将介于两者之间的所有像素标准化为最大值 244。我认为没有任何现成的算法可以解决这个问题,因为实现所需结果的所有 3 个步骤都是微不足道的。

标签: python numpy image-processing


【解决方案1】:

这是一种方法-

def stretch(a, lower_thresh, upper_thresh):
    r = 255.0/(upper_thresh-lower_thresh+2) # unit of stretching
    out = np.round(r*(a-lower_thresh+1)).astype(a.dtype) # stretched values
    out[a<lower_thresh] = 0
    out[a>upper_thresh] = 255
    return out

根据 OP,标准集是:

  • 246 上方的每个像素“移位”到255,因此247 及以上应变为255

  • 186zero 下方的每个像素,因此185 及以下应变为0

  • 因此,基于上述两个要求,186 应该大于0,依此类推,直到246 小于255

或者,我们也可以使用np.where 使其更紧凑-

def stretch(a, lower_thresh, upper_thresh):
    r = 255.0/(upper_thresh-lower_thresh+2) # unit of stretching
    out = np.round(r*np.where(a>=lower_thresh,a-lower_thresh+1,0)).clip(max=255)
    return out.astype(a.dtype)

示例运行 -

# check out first row input, output for variations
In [216]: a
Out[216]: 
array([[186, 187, 188, 246, 247],
       [251, 195, 103,   9, 211],
       [ 21, 242,  36,  87,  70]], dtype=uint8)

In [217]: stretch(a, lower_thresh=186, upper_thresh=246)
Out[217]: 
array([[  4,   8,  12, 251, 255], 
       [255,  41,   0,   0, 107],
       [  0, 234,   0,   0,   0]], dtype=uint8)

【讨论】:

  • 这两个答案都很好,但选择这个答案是因为它的解释性品质(对于那些学习 Python 的人)。
【解决方案2】:

如果你的图片是 uint8 和典型图片大小,一种有效的方法是设置查找表:

L, H = 186, 246
lut = np.r_[0:0:(L-1)*1j, 0.5:255.5:(H-L+3)*1j, 255:255:(255-H-1)*1j].astype('u1')

# example
from scipy.misc import face
f = face()

rescaled = lut[f]

对于较小的图像,直接转换的速度更快(在我的设置中,它跨越了大约 100,000 个灰度像素):

fsmall = (f[::16, ::16].sum(2)//3).astype('u1')

slope = 255/(H-L+2)
rescaled = ((1-L+0.5/slope+fsmall)*slope).clip(0, 255).astype('u1')

【讨论】:

    猜你喜欢
    • 2016-05-07
    • 1970-01-01
    • 2017-04-28
    • 1970-01-01
    • 1970-01-01
    • 2014-06-26
    • 1970-01-01
    • 2019-01-24
    • 1970-01-01
    相关资源
    最近更新 更多