【问题标题】:Converting an image to grayscale using numpy使用 numpy 将图像转换为灰度
【发布时间】:2018-12-19 12:02:12
【问题描述】:

我有一个由三元组(r,g,b)numpy.array 矩阵nxm 表示的图像,我想使用我自己的函数将其转换为灰度。

我尝试将矩阵 nxmx3 转换为单个值矩阵 nxm 失败,这意味着从数组开始 [r,g,b] 我得到 [gray, gray, gray] 但我需要 @ 987654327@.

即初始颜色通道:[150 246 98]。 转换为灰色后:[134 134 134]。 我需要什么:134

我怎样才能做到这一点?

我的代码:

def grayConversion(image):
    height, width, channel = image.shape
    for i in range(0, height):
        for j in range(0, width):
            blueComponent = image[i][j][0]
            greenComponent = image[i][j][1]
            redComponent = image[i][j][2]
            grayValue = 0.07 * blueComponent + 0.72 * greenComponent + 0.21 * redComponent
            image[i][j] = grayValue
    cv2.imshow("GrayScale",image)
    return image

【问题讨论】:

  • 请使用矢量化而不是嵌套的 for 循环。
  • 您能详细说明一下吗? @Quickbeam2k1
  • 我不确定我是否理解您的问题。 opencv转换到底有什么问题?你想自己实现opencv转换吗?
  • opencv转换没有问题。是的,我想要一个二维图像数组来实现我自己的代码。
  • thesamiroli 如果我的回答不正确,您能否详细说明我错过了什么?谢谢!

标签: python arrays numpy opencv


【解决方案1】:

这是一个工作代码:

def grayConversion(image):
    grayValue = 0.07 * image[:,:,2] + 0.72 * image[:,:,1] + 0.21 * image[:,:,0]
    gray_img = grayValue.astype(np.uint8)
    return gray_img

orig = cv2.imread(r'C:\Users\Jackson\Desktop\drum.png', 1)
g = grayConversion(orig)

cv2.imshow("Original", orig)
cv2.imshow("GrayScale", g)
cv2.waitKey(0)
cv2.destroyAllWindows()

【讨论】:

    【解决方案2】:

    您可以使用点积:

    gray_image = image.dot([0.07, 0.72, 0.21])
    

    或者甚至只是手动完成整个操作:

    b = image[..., 0]
    g = image[..., 1]
    r = image[..., 2]
    gray_image = 0.21 * r + 0.72 * g + 0.07 * b
    

    别忘了转换回 0-255:

    gray_image = np.min(gray_image, 255).astype(np.uint8)
    

    【讨论】:

    • 图片还是3维数组。
    • 你的意思是gray_image.ndim == 3?在我的机器上是 2
    【解决方案3】:

    使用apply_along_axis的解决方案

    使用apply_along_axis可以实现解决方案:

    import numpy as np
    def grayscale(colors):
        """Return grayscale of given color."""
        r, g, b = colors
        return 0.07 * r + 0.72 * g + 0.21 * b
    
    image = np.random.uniform(255, size=(10,10,3))
    result = np.apply_along_axis(grayscale, 2, image)
    

    示例

    10x10 图片

    我们现在可以继续可视化结果:

    from matplotlib import pyplot as plt
    plt.subplot(1,2,1)
    plt.imshow(image)
    plt.subplot(1,2,2)
    plt.imshow(result, cmap='gray')
    

    文字示例(2x2 图片)

    为了在文本中可视化实际结果,我将使用一个较小的数组,只是一个 2x2 图像:

    image = np.random.uniform(250, size=(2,2,3))
    

    内容是:

    array([[[205.02229826, 109.56089703, 163.74868594],
        [ 11.13557763, 160.98463727, 195.0294515 ]],
    
       [[218.15273335,  84.94373737, 197.70228018],
        [ 75.8992683 , 224.49258788, 146.74468294]]])
    

    让我们使用我们的自定义函数将其转换为灰度:

    result = np.apply_along_axis(grayscale, 2, image)
    

    而转换的输出是:

    array([[127.62263079, 157.64461409],
       [117.94766108, 197.76399547]])
    

    我们也可以使用与上面相同的代码来可视化这个简单的示例:

    进一步的建议

    如果您想应用自己的自定义函数,那么apply_along_axis 是可行的方法,但您应该考虑使用更纯粹的numpy 方法,例如Eric 建议的方法,或者,如果可能,只需使用cv2 选项加载黑白图像:

    cv2.imread('smalltext.jpg',0)
    

    【讨论】:

    • 那么,结果变量应该是灰度图像吧?还是我错过了什么,因为当我尝试显示它时,它只在各处显示白色像素。
    • 是的,但他要求使用自己的自定义函数。
    • Your comment 给人一种误导性的印象,即这样做更好,因为它避免了 python 循环 - 但 python 循环正是 apply_along_axis 所做的。
    • Eric 评论已删除,您是对的。
    • @thesamiroli 我相信是的。使用cv2灰度加载cv2.imread('smalltext.jpg',0)时会出现什么情况?
    猜你喜欢
    • 2021-11-24
    • 2020-12-19
    • 1970-01-01
    • 2021-04-02
    • 1970-01-01
    • 2010-11-20
    相关资源
    最近更新 更多