파이썬에서 RGB 이미지를 그레이 스케일로 어떻게 변환 할 수 있습니까?


205

matplotlibRGB 이미지를 읽고 그레이 스케일로 변환 하는 데 사용하려고합니다 .

matlab에서 나는 이것을 사용한다 :

img = rgb2gray(imread('image.png'));

에서 하기 matplotlib 튜토리얼 그들은 그것을 적용되지 않습니다. 그들은 단지 이미지를 읽었습니다.

import matplotlib.image as mpimg
img = mpimg.imread('image.png')

그런 다음 배열을 슬라이스하지만 RGB를 그레이 스케일로 변환하는 것과 같은 것은 아닙니다.

lum_img = img[:,:,0]

numpy 또는 matplotlib에 RGB에서 회색으로 변환하는 내장 함수가 없다고 생각하기가 어렵습니다. 이것은 이미지 처리에서 일반적인 작업이 아닙니까?

imread5 분 안에 가져온 이미지로 작동하는 매우 간단한 기능을 작성했습니다 . 끔찍하게 비효율적이지만 전문 구현이 내장되어 있기를 바랐습니다.

Sebastian은 내 기능을 개선했지만 여전히 내장 기능을 찾고 있습니다.

MATLAB (NTSC / PAL) 구현 :

import numpy as np

def rgb2gray(rgb):

    r, g, b = rgb[:,:,0], rgb[:,:,1], rgb[:,:,2]
    gray = 0.2989 * r + 0.5870 * g + 0.1140 * b

    return gray

2
rgb2gray 함수와 같은 것을 다음과 같이 간단하게 작성할 수 있습니다 gray = np.mean(rgb, -1). 어쩌면 rgb[...,:3]실제로 RGBA가있는 경우.
seberg

흠, gray = np.mean(rgb, -1)잘 작동합니다. 감사. 이것을 사용하지 않는 이유가 있습니까? 대신 아래 답변에서 솔루션을 사용하는 이유는 무엇입니까?
waspinator

6
페이지 위키 계조는 계조 RGB로 변환하는 방법은 유일한 것은 아니지만, 휘도에 기초하여 일반적으로 사용되는 수식을 제공했다. 와는 상당히 다릅니다 np.mean(rgb, -1).
unutbu

2
그래서 나는 내가 원하는 생각 matlab에의 버전을 ? 0.2989 * R + 0.5870 * G + 0.1140 * B 나는 그것이 표준 방법이라고 가정하고 있습니다.
waspinator

답변:


303

방법으로 그 일에 대해 베개 :

from PIL import Image
img = Image.open('image.png').convert('LA')
img.save('greyscale.png')

matplotlib 및 공식 사용

Y' = 0.2989 R + 0.5870 G + 0.1140 B 

당신은 할 수 있습니다 :

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

def rgb2gray(rgb):
    return np.dot(rgb[...,:3], [0.2989, 0.5870, 0.1140])

img = mpimg.imread('image.png')     
gray = rgb2gray(img)    
plt.imshow(gray, cmap=plt.get_cmap('gray'), vmin=0, vmax=1)
plt.show()

3
만약 그가 matplotlib다른 이유로 사용해야한다면 colorsys.rgb_to_yiq(), 루마 채널을 얻기 위해 내장 을 사용하여 슬라이스를 변환 할 수 있어야합니다 .
Silas Ray

34
.convert('LA')? 왜 안돼 .convert('gray')? 불필요하게 비밀스러운 것 같습니다. PIL 문서는 변환 기능 'LA'에 대해 아무것도 언급하지 않습니다.
waspinator

25
PIL : 사용 cannot write mode LA as JPEG, 나는 LA가 아닌 L 모드를 사용해야했다
jsky

6
이렇게 img = Image.open('image.png').convert('LA')할 필요가img = Image.open('image.png').convert('L')
nviens

12
@BluePython : LA모드에는 광도 (밝기)와 알파가 있습니다. LA모드 를 사용 greyscale.png하면 알파 채널이 image.png보존 된 RGBA 이미지가 됩니다. Lmode 를 사용 greyscale.png하면 RGB 이미지 (알파 없음)가됩니다.
unutbu

69

scikit-image를 사용 하여 ndarray와 같은 이미지를 변환하는 기능을 제공합니다 rgb2gray.

from skimage import color
from skimage import io

img = color.rgb2gray(io.imread('image.png'))

참고 :이 변환에 사용 된 중량은 최신 CRT 형광체에 대해 보정됩니다 : Y = 0.2125 R + 0.7154 G + 0.0721 B

또는 다음을 통해 이미지를 회색조로 읽을 수 있습니다.

from skimage import io
img = io.imread('image.png', as_gray=True)

0 <values ​​<1을 얻는 것이 정상입니까? 실제 그레이 스케일을 얻기 위해 255를 곱해야합니까?
Sam

내 목표는 GLCM 기능 (greycoprops)을 사용하는 것입니다.
Sam

io.imread에 대한 참고 사항 : "as_grey"는 "as_grey"를 위해 더 이상 사용되지 않습니다. 동일한 사용법, 미국식 철자법. :)
할로겐

1
나는 이것이 질문에 대한 가장 유용한 대답이라고 생각하며, 이것의 출력은 matplotlib 및 numpy 와도 호환됩니다.
Mert Beşiktepe

색상 개체를 사용하고 있지만 이미지가 회색 (흑백)이 아닌 붉은 색입니다. 내가 사용할 필요 cmapgray' then only the image is shown as gray in pyplot.imshow ()`? 이견있는 사람 ? 내가 어디 틀렸어?
GadaaDhaariGeek

63

제안 된 방법 중 3 가지가 Ubuntu 16.04 LTS (SSD의 Xeon E5 2670)에서 Python 3.5로 실행되는 1000 RGBA PNG 이미지 (224 x 256 픽셀)의 속도에 대해 테스트되었습니다.

평균 실행 시간

pil : 1.037 초

scipy: 1.040 초

sk : 2.120 초

PIL과 SciPy는 동일한 numpy배열 (0에서 255까지)을 제공했습니다. SkImage는 0에서 1까지의 배열을 제공합니다. 또한 색상이 약간 다르게 변환됩니다. CUB-200 데이터 세트 의 예를 참조하십시오 .

SkImage: SkImage

PIL : 필

SciPy : 사이 파이

Original: 실물

Diff : 여기에 이미지 설명을 입력하십시오

암호

  1. 공연

    run_times = dict(sk=list(), pil=list(), scipy=list())
    for t in range(100):
        start_time = time.time()
        for i in range(1000):
            z = random.choice(filenames_png)
            img = skimage.color.rgb2gray(skimage.io.imread(z))
        run_times['sk'].append(time.time() - start_time)

    start_time = time.time()
    for i in range(1000):
        z = random.choice(filenames_png)
        img = np.array(Image.open(z).convert('L'))
    run_times['pil'].append(time.time() - start_time)
    
    start_time = time.time()
    for i in range(1000):
        z = random.choice(filenames_png)
        img = scipy.ndimage.imread(z, mode='L')
    run_times['scipy'].append(time.time() - start_time)
    

    for k, v in run_times.items(): print('{:5}: {:0.3f} seconds'.format(k, sum(v) / len(v)))

  2. 산출
    z = 'Cardinal_0007_3025810472.jpg'
    img1 = skimage.color.rgb2gray(skimage.io.imread(z)) * 255
    IPython.display.display(PIL.Image.fromarray(img1).convert('RGB'))
    img2 = np.array(Image.open(z).convert('L'))
    IPython.display.display(PIL.Image.fromarray(img2))
    img3 = scipy.ndimage.imread(z, mode='L')
    IPython.display.display(PIL.Image.fromarray(img3))
  3. 비교
    img_diff = np.ndarray(shape=img1.shape, dtype='float32')
    img_diff.fill(128)
    img_diff += (img1 - img3)
    img_diff -= img_diff.min()
    img_diff *= (255/img_diff.max())
    IPython.display.display(PIL.Image.fromarray(img_diff).convert('RGB'))
  4. 수입
    import skimage.color
    import skimage.io
    import random
    import time
    from PIL import Image
    import numpy as np
    import scipy.ndimage
    import IPython.display
  5. 버전
    skimage.version
    0.13.0
    scipy.version
    0.19.1
    np.version
    1.13.1

6
SciPy의 이미지 I / O는 말 그대로 PIL / Pillow입니다. 따라서 SciPy 테스트는 SciPy의 래퍼 기능으로 인해 무시할 수있는 오버 헤드로 PIL / Pillow를 효과적으로 다시 테스트하고 있습니다. SciPy 대신 OpenCV ( PIL / Pillow 를 사용하지 않는) 를 대체하는 것이 훨씬 유용 했을 것 입니다. 그럼에도 불구하고 전용 벤치마킹에 감사드립니다! SciKit이 부과 한 식별 가능한 둔화는 매혹적 이며 끔찍 합니다.
세실 카레

@CecilCurry OpenCV의 아이디어에 감사드립니다! 여가 시간을 찾으면 추가하겠습니다.
Maximilian Peters

공감! 내가 찾던 대답은 아니지만 매우 흥미 롭습니다 :)
Cyril N.

29

imreadOpenCV 에서 처음부터 항상 이미지 파일을 그레이 스케일로 읽을 수 있습니다 .

img = cv2.imread('messi5.jpg', 0)

또한 이미지를 RGB로 읽으려면 처리를 한 다음 cvtcolorOpenCV에서 사용할 수있는 그레이 스케일로 변환하십시오 .

gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

6
Ftr : 0플래그는 cv2.CV_LOAD_IMAGE_GRAYSCALE입니다.
dtk

24

가장 빠르고 현재의 방법은 통해 설치된 Pillow 를 사용하는 것입니다 pip install Pillow.

코드는 다음과 같습니다.

from PIL import Image
img = Image.open('input_file.jpg').convert('L')
img.save('output_file.jpg')

3
위의 예와 같이 메소드를 연결하지 않으면 convert이미지의 변환 된 사본을 반환합니다.
Matt

32 비트 PNG에서는 작동하지 않습니다. 값은 255 로 고정 됩니다.
Andrew Matuk

11

이 자습서는 RGB로 인코딩 된 그레이 스케일 이미지로 시작하기 때문에 속이는 것이므로 단일 컬러 채널을 슬라이스하고 그레이 스케일로 처리합니다. 기본 단계는 RGB 색상 공간에서 YUV / YIQ 또는 HSL / HSV와 같은 루마 / 크로마 모델에 근사한 것으로 인코딩 한 색상 공간으로 변환 한 다음 루마와 유사한 채널을 분리하여 다음과 같이 사용하는 것입니다. 그레이 스케일 이미지. matplotlibYUV / YIQ로 변환하는 메커니즘을 제공하지는 않지만 HSV로 변환 할 수는 있습니다.

matplotlib.colors.rgb_to_hsv(img)회색조에 대한 배열에서 마지막 값 (V)을 사용한 다음 슬라이싱하십시오. 루마 값과 동일하지는 않지만에서 모든 것을 할 수 있음을 의미합니다 matplotlib.

배경:

또는 PIL 또는 내장 colorsys.rgb_to_yiq()을 사용하여 진정한 루마 값을 가진 색상 공간으로 변환 할 수 있습니다 . 당신은 또한 모두 들어가서 자신의 루마 전용 변환기를 굴릴 수는 있지만 아마도 과잉 일 것입니다.


9

이 공식을 사용하여

Y' = 0.299 R + 0.587 G + 0.114 B 

우린 할 수있어

import imageio
import numpy as np
import matplotlib.pyplot as plt

pic = imageio.imread('(image)')
gray = lambda rgb : np.dot(rgb[... , :3] , [0.299 , 0.587, 0.114]) 
gray = gray(pic)  
plt.imshow(gray, cmap = plt.get_cmap(name = 'gray'))

그러나 김프에서 컬러를 그레이 스케일 이미지 소프트웨어로 변환하는 작업에는 3 가지 알고리즘이 있습니다.


8

NumPy / SciPy를 이미 사용중인 경우 다음을 사용할 수도 있습니다 .

scipy.ndimage.imread(file_name, mode='L')


5
모두 scipy.ndimage.imread()하고 scipy.misc.imread()있습니다 공식적으로 사용되지 SciPy 1.0.0과됩니다 영구적으로 제거 SciPy 1.2.0에서. SciPy의 문서가 권장하는 동안imageio.imread() 는 적절한 대체물로 ,이 기능의 API는 부조리의 핵심입니다. 그레이 스케일 변환에 대한 지원을 제공 하지 않으므로 그레이 스케일 변환을 포함하여 많은 응용 프로그램에 부적합합니다. </sigh>
세실 커리

5
@CecilCurry, imageio를 사용하여 컬러 이미지를 그레이 스케일로 어떻게 변환합니까?
0x90

5

당신은 할 수 있습니다 :

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

def rgb_to_gray(img):
        grayImage = np.zeros(img.shape)
        R = np.array(img[:, :, 0])
        G = np.array(img[:, :, 1])
        B = np.array(img[:, :, 2])

        R = (R *.299)
        G = (G *.587)
        B = (B *.114)

        Avg = (R+G+B)
        grayImage = img

        for i in range(3):
           grayImage[:,:,i] = Avg

        return grayImage       

image = mpimg.imread("your_image.png")   
grayImage = rgb_to_gray(image)  
plt.imshow(grayImage)
plt.show()

5

img.Convert ()를 사용하고“L”,“RGB”및“CMYK”를 지원합니다. 양식

import numpy as np
from PIL import Image

img = Image.open("IMG/center_2018_02_03_00_34_32_784.jpg")
img.convert('L')

print np.array(img)

산출:

[[135 123 134 ...,  30   3  14]
 [137 130 137 ...,   9  20  13]
 [170 177 183 ...,  14  10 250]
 ..., 
 [112  99  91 ...,  90  88  80]
 [ 95 103 111 ..., 102  85 103]
 [112  96  86 ..., 182 148 114]]

1
다섯 번째 줄은 img = img.convert('L')?
Allan Ruin

3

이미로드 된 이미지를 그레이 스케일로 변환하는 방법을 찾고 Google을 통해이 질문에 왔습니다.

SciPy로 수행하는 방법은 다음과 같습니다.

import scipy.misc
import scipy.ndimage

# Load an example image
# Use scipy.ndimage.imread(file_name, mode='L') if you have your own
img = scipy.misc.face()

# Convert the image
R = img[:, :, 0]
G = img[:, :, 1]
B = img[:, :, 2]
img_gray = R * 299. / 1000 + G * 587. / 1000 + B * 114. / 1000

# Show the image
scipy.misc.imshow(img_gray)

1
좋은. 난 그냥이 될 것입니다 짧은 솔루션을주의 할img_gray = numpy.average(img, weights=[0.299, 0.587, 0.114], axis=2)
Akavall

@Akavall 감사합니다. 감사합니다! 바로 가기가 더 빠른지 아십니까? 그렇지 않다면 이해하기 쉽기 때문에 내 것을 지키겠다.
Martin Thoma

나는 그것을 시간이 지체하지 않았다, 나의 직감 numpy.average은 조금 더 빠르지 만 실질적으로 다르지 않다. 귀하의 솔루션은 명확하고 R, G, B에 대한 관련 정보가 있으므로 계속 유지하겠습니다. 내 의견은 추가 옵션이 아니라 대체 옵션이었습니다.
Akavall

모두 scipy.ndimage.imread()하고 scipy.misc.imread()있습니다 공식적으로 사용되지 SciPy 1.0.0과됩니다 영구적으로 제거 SciPy 1.2.0에서. 대신 필로우의 내장 된 회색조 변환 지원 (ala unutbu 's answer ) 을 사용하고 싶을 수도 있습니다 .
세실 카레

-3
image=myCamera.getImage().crop(xx,xx,xx,xx).scale(xx,xx).greyscale()

greyscale()변환에 직접 사용할 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.