【问题标题】:Convert RGB to black OR white将 RGB 转换为黑色或白色
【发布时间】:2013-09-17 15:26:00
【问题描述】:

如何在 Python 中获取 RGB 图像并将其转换为黑白?不是灰度,我希望每个像素都是全黑 (0, 0, 0) 或全白 (255, 255, 255)。

是否有任何内置功能可以在流行的 Python 图像处理库中完成它?如果不是,最好的方法是循环遍历每个像素,如果它更接近白色,则将其设置为白色,如果它更接近黑色,则将其设置为黑色?

【问题讨论】:

  • 我不懂 Python,但thresholdthis example 可能会有所帮助
  • @WangYudong OpenCV 对此感到疯狂的矫枉过正
  • @NickT 我实际上希望用 OpenCV 来解决这个问题,因为我的脚本的其余部分正在使用 OpenCV 进行霍夫线变换。仍然没有弄清楚如何在 PIL 中做到这一点......或者如何在 PIL 和 OpenCV 之间进行转换。
  • @Tom img = opencv.adaptors.PIL2Ipl(pilimg) 是否可以转换为您可以使用的 opencv 图像?

标签: python opencv numpy python-imaging-library


【解决方案1】:

缩放为黑白

转换为灰度,然后缩放为白色或黑色(以最接近的为准)。

原文:

结果:

Pure Pillow 实现

如果您还没有安装pillow

$ pip install pillow

Pillow(或 PIL)可以帮助您有效地处理图像。

from PIL import Image

col = Image.open("cat-tied-icon.png")
gray = col.convert('L')
bw = gray.point(lambda x: 0 if x<128 else 255, '1')
bw.save("result_bw.png")

或者,您可以将Pillownumpy 一起使用。

Pillow + Numpy 位掩码方法

你需要安装 numpy:

$ pip install numpy

Numpy 需要一个数组的副本来操作,但是结果是一样的。

from PIL import Image
import numpy as np

col = Image.open("cat-tied-icon.png")
gray = col.convert('L')

# Let numpy do the heavy lifting for converting pixels to pure black or white
bw = np.asarray(gray).copy()

# Pixel range is 0...255, 256/2 = 128
bw[bw < 128] = 0    # Black
bw[bw >= 128] = 255 # White

# Now we put it back in Pillow/PIL land
imfile = Image.fromarray(bw)
imfile.save("result_bw.png")

黑白使用枕头,抖动

使用pillow 可以直接将其转换为黑白。它看起来像有灰色阴影,但你的大脑在欺骗你! (黑白相近看起来像灰色)

from PIL import Image 
image_file = Image.open("cat-tied-icon.png") # open colour image
image_file = image_file.convert('1') # convert image to black and white
image_file.save('/tmp/result.png')

原文:

转换:

黑白使用 Pillow,无抖动

from PIL import Image 
image_file = Image.open("cat-tied-icon.png") # open color image
image_file = image_file.convert('1', dither=Image.NONE) # convert image to black and white
image_file.save('/tmp/result.png')

【讨论】:

  • 必须承认,猫没有抖动就更可爱了。
  • 你很幸运,关卡成功了,这可能真的很丑陋。而且我确信 PIL(和枕头?)有办法在不诉诸 Numpy 的情况下进行阈值处理。
  • 肯定有,天哪,我是重构代码的贪吃者。如果您找到它,请随意编辑。 :)
  • @MarkRansom - 很好的编辑!认为可以将更紧凑的代码移到顶部并仅提供 numpy 部分以提高灵活性?
  • @Jaime,不,它没有——point 函数缓存了函数的返回值,所以它最多只会被调用 256 次。
【解决方案2】:

我建议转换为灰度,然后简单地对其应用一个阈值(中间值,或者平均值或中位数,如果你愿意的话)。

from PIL import Image

col = Image.open('myimage.jpg')
gry = col.convert('L')
grarray = np.asarray(gry)
bw = (grarray > grarray.mean())*255
imshow(bw)

【讨论】:

  • @Tom 您是否更改了要比较的值?比如说,grarray &gt; 16 例如
【解决方案3】:
img_rgb = cv2.imread('image.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
(threshi, img_bw) = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

【讨论】:

    【解决方案4】:

    枕头,带抖动

    使用pillow 可以直接将其转换为黑白。它看起来像有灰色阴影,但你的大脑在欺骗你! (黑白相近看起来像灰色)

    from PIL import Image 
    image_file = Image.open("cat-tied-icon.png") # open colour image
    image_file = image_file.convert('1') # convert image to black and white
    image_file.save('/tmp/result.png')
    

    原文:

    转换:

    【讨论】:

    • 我不希望像素之间有这些间隙
    • 那些“间隙”是白色像素。
    • 好吧,不要看原始图像中的顶部栏。它是纯色,但转换后它会以某种方式拾取那些白色像素。
    • @Tom,“间隙”被称为抖动,如果没有它,您可能不会喜欢结果。我不知道 Pillow 默认会这样做!
    • 在这种情况下,我实际上需要禁用这种抖动。这可能吗?
    【解决方案5】:

    您可以使用colorsys(在标准库中)将rgb转换为hls并使用亮度值来确定黑/白:

    import colorsys
    # convert rgb values from 0-255 to %
    r = 120/255.0
    g = 29/255.0
    b = 200/255.0
    h, l, s = colorsys.rgb_to_hls(r, g, b)
    if l >= .5:
        # color is lighter
        result_rgb = (255, 255, 255)
    elif l < .5:
        # color is darker
        result_rgb = (0,0,0)
    

    【讨论】:

      【解决方案6】:

      使用opencv可以轻松将rgb转为二值图像

      import cv2
      %matplotlib inline 
      import matplotlib.pyplot as plt
      from skimage import io
      from PIL import Image
      import numpy as np
      
      img = io.imread('http://www.bogotobogo.com/Matlab/images/MATLAB_DEMO_IMAGES/football.jpg')
      img = cv2.cvtColor(img, cv2.IMREAD_COLOR)
      imR=img[:,:,0] #only taking gray channel
      print(img.shape)
      plt.imshow(imR, cmap=plt.get_cmap('gray'))
      
      #Gray Image
      plt.imshow(imR)
      plt.title('my picture')
      plt.show()
      
      #Histogram Analyze
      
      imgg=imR
      hist = cv2.calcHist([imgg],[0],None,[256],[0,256])
      plt.hist(imgg.ravel(),256,[0,256])
      
      # show the plotting graph of an image
      
      plt.show()
      
      #Black And White
      height,width=imgg.shape
      for i in range(0,height):
        for j in range(0,width):
           if(imgg[i][j]>60):
              imgg[i][j]=255
           else:
              imgg[i][j]=0
      
      plt.imshow(imgg)
      

      【讨论】:

      • 使用 NumPy 时,应避免循环。可以写成imgg[ imgg&lt; 60 ] = 0imgg[ imgg &gt;= 60 ] = 255
      【解决方案7】:

      这里是使用 opencv-python 创建二进制图像的代码:

      img = cv2.imread('in.jpg',2)
      
      ret, bw_img = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
      
      cv2.imshow("Output - Binary Image",bw_img)
      

      【讨论】:

        【解决方案8】:

        如果您不想使用 cv 方法进行分割并了解自己在做什么,请将 RGB 图像视为矩阵。

        image = mpimg.imread('image_example.png') # your image
        R,G,B = image[:,:,0], image[:,:,1], image[:,:,2] # the 3 RGB channels
        thresh = [100, 200, 50] # example of triple threshold
        
        # First, create an array of 0's as default value
        binary_output = np.zeros_like(R)
        # then screen all pixels and change the array based on RGB threshold.
        binary_output[(R < thresh[0]) & (G > thresh[1]) & (B < thresh[2])] = 255
        

        结果是基于三元组条件的 0 和 255 数组。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-10-04
          • 2015-06-30
          • 1970-01-01
          • 2019-12-13
          • 2015-04-07
          • 2013-08-29
          • 2018-12-23
          相关资源
          最近更新 更多