【问题标题】:NumPy - Faster way to implement threshold value ceilingNumPy - 实现阈值上限的更快方法
【发布时间】:2014-01-30 14:53:43
【问题描述】:

我正在编写一个脚本来使用 NumPy 和 CV2 修改 RGB 图像的亮度,方法是从 RGB 转换为 YCrCb 并再次转换回来。但是,我使用的循环需要一段时间才能执行,我想知道是否有更快的方法。

import cv2 as cv, numpy as np

threshold = 64
image = cv.imread("motorist.jpg", -1)
image.shape # Evaluates to (1000, 1500, 3)

im = cv.cvtColor(image, cv.COLOR_RGB2YCR_CB)

for row in image:
    for col in row:
        if col[0] > threshold:
            col[0] = threshold

image = cv.cvtColor(im, cv.COLOR_YCR_CB2RGB)
cv.imwrite("motorist_filtered.jpg", image)

实现阈值比较的嵌套循环至少需要 5-7 秒才能执行。有没有更快的方法来实现这个功能?

【问题讨论】:

    标签: python image-processing numpy


    【解决方案1】:

    这个想法是创建一个mask,让您可以使用 numpy 的矢量化。由于形状为(n,m,3),循环遍历前两个维度并使用[:,:,0]获取最后一个维度的第一个索引

    idx = image[:,:,0] > threshold
    image[idx,0] = threshold
    

    【讨论】:

    • @Jason 值得运行这个并打印出idx 的样子。这是一个大小为(n,m) 的巨大数组,其中填充了真/假。使用掩码 only 对 numpy 数组进行索引会获取掩码中为 True 的那些值。广播和屏蔽是让你的 numpy 代码快速运行的方法。
    • 当我运行您的示例时,它确实执行得更快。但是,图像中的主要效果更加绿色,好像亮度通道是绿色的。
    • 别在意我的最后评论。这是由于转换回 RGB 并保存到文件。如果我将 YCrCb 图像写入文件,效果看起来应该是这样。
    • @Jason 你确定你在上面的代码中正确使用了变量imimage 吗?在查看您的示例时,我注意到一些奇怪的事情,循环修改了image,但您在应用cv.cvtColor 时使用了im。由于问题是关于向量化 numpy 循环,我忽略了其他部分。
    • 这段代码似乎修改了所有频道,而不仅仅是频道 0。
    【解决方案2】:

    你可以使用clip:

    用法:

    result = im.copy()
    result[..., 0] = np.clip(im[..., 0], 0, threshold)
    

    或者就地修改:

    np.clip(im[..., 0], 0, threshold, out=im[..., 0])
    

    【讨论】:

    • 剪切所有像素值,而不仅仅是我所针对的单个亮度通道
    【解决方案3】:
    import numpy as np
    
    image[..., 0] = np.minimum(image[..., 0], threshold)
    

    编辑:抱歉,我还不能添加 cmets。昨天我感到很懒惰。关于就地修改是正确的,但它相当明显,或者你不需要它。懒惰是对一个懒惰问题的回应 - numpy 中有一个“一切”功能 - 只需查看文档即可。

    【讨论】:

    • 您能对此添加一些解释吗?没有解释的答案是不受欢迎的。
    • @Keith Pinson,同意,甚至可以认为它是懒惰的 ;)
    猜你喜欢
    • 1970-01-01
    • 2014-02-17
    • 2021-09-15
    • 2014-02-24
    • 2020-09-01
    • 2013-01-30
    • 1970-01-01
    • 1970-01-01
    • 2014-01-12
    相关资源
    最近更新 更多