मैं पायथन में आरजीबी छवि को ग्रेस्केल में कैसे बदल सकता हूं?


205

मैं matplotlibएक RGB छवि में पढ़ने और इसे ग्रेस्केल में बदलने के लिए उपयोग करने का प्रयास कर रहा हूं ।

मतलाब में मैं इसका उपयोग करता हूं:

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

में matplotlib ट्यूटोरियल वे इसे कवर नहीं है। वे सिर्फ छवि में पढ़ते हैं

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

और फिर वे सरणी को स्लाइस करते हैं, लेकिन आरजीबी को ग्रेस्केल में परिवर्तित करने के समान नहीं है जो मैं समझता हूं।

lum_img = img[:,:,0]

मुझे यह विश्वास करना मुश्किल है कि आरजीबी से ग्रे में बदलने के लिए सुन्न या मेटप्लोटिब में एक अंतर्निहित फ़ंक्शन नहीं है। क्या यह इमेज प्रोसेसिंग में एक सामान्य ऑपरेशन नहीं है?

मैंने एक बहुत ही सरल फ़ंक्शन लिखा है imreadजो 5 मिनट में उपयोग करके आयातित छवि के साथ काम करता है । यह बहुत ही अयोग्य है, लेकिन यही कारण है कि मैं एक पेशेवर कार्यान्वयन के लिए उम्मीद कर रहा था।

सेबस्टियन ने मेरे कार्य में सुधार किया है, लेकिन मैं अभी भी अंतर्निहित एक को खोजने की उम्मीद कर रहा हूं।

matlab का NTSC (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]वहाँ अगर यह वास्तव में आरजीबीए है।
1

हम्म, gray = np.mean(rgb, -1)ठीक काम करता है। धन्यवाद। क्या इसका उपयोग नहीं करने का कोई कारण है? मैं नीचे दिए गए उत्तरों में समाधानों का उपयोग क्यों करूंगा?
इपिनेटर

6
ग्रेस्केल पेज विकिपीडिया कहते हैं ग्रेस्केल करने के लिए आरजीबी बदलने की विधि अद्वितीय नहीं है, लेकिन एक आमतौर पर इस्तेमाल किया चमक के आधार पर सूत्रों देता है। की तुलना में यह काफी अलग है np.mean(rgb, -1)
unutbu

2
इसलिए मुझे लगता है कि मुझे मतलूब का संस्करण चाहिए ? 0.2989 * R + 0.5870 * G + 0.1140 * B मैं मान रहा हूँ कि यह करने का मानक तरीका है।
थापिनटर

जवाबों:


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()का उपयोग करने में सक्षम होना चाहिए और साथ ही सिर्फ लामा चैनल प्राप्त करने के लिए एक स्लाइस बदलना चाहिए।
सिलास रे

34
क्यों .convert('LA')? क्यों नहीं .convert('gray')? अनावश्यक रूप से लगता है। जनहित याचिका प्रलेखन परिवर्तित समारोह के लिए 'ला' के बारे में कुछ भी उल्लेख नहीं है।
ऑपिनेटर

25
पीआईएल का उपयोग करना: cannot write mode LA as JPEGमुझे एल मोड का उपयोग करने की आवश्यकता नहीं है ला
जैस्की

6
इसके img = Image.open('image.png').convert('LA')लिए आवश्यक हैimg = Image.open('image.png').convert('L')
nviens

12
@ ब्लैक्यूथॉन: LAमोड में ल्युमिनोसिटी (चमक) और अल्फा है। यदि आप LAमोड का उपयोग करते हैं, तो संरक्षित greyscale.pngके अल्फा चैनल के साथ एक RGBA छवि होगी image.png। यदि आप Lमोड का उपयोग करते हैं, तो greyscale.pngएक RGB छवि होगी (बिना अल्फा के)।
दोपहर

69

आप scitit-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 <मान <1 मिल रहा है? क्या मुझे वास्तविक ग्रे स्केल प्राप्त करने के लिए उन्हें 255 से गुणा करना चाहिए?
सैम

यह जानते हुए कि मेरा उद्देश्य
सैम

Io.imread के लिए ध्यान दें: "as_grey" को "as_gray" के पक्ष में चित्रित किया गया है। समान उपयोग, बस अमेरिकीकृत वर्तनी। :)
हैलोजन

1
मेरा मानना ​​है कि यह हाथ में सवाल करने के लिए सबसे उपयोगी उत्तर है, इस का उत्पादन भी matplotlib और numpy के साथ संगत है।
मर्ट बेसिकटपे

मैं कलर ऑब्जेक्ट का उपयोग कर रहा हूं लेकिन मेरी छवि अब लाल रंग की है और ग्रे (ब्लैक एंड व्हाइट) नहीं है। मुझे pyplot.imshow () `के cmapरूप में उपयोग करने की आवश्यकता है gray' then only the image is shown as gray in ? कोई विचार ? मैं कहां गलत हूं?
गदाधरीगीक

63

उबंटू 16.04 LTS (XDon E5 2670 पर SSD के साथ) पर पायथन 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 : 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 / तकिया। इसलिए, SciPy का परीक्षण प्रभावी ढंग से SciPy के आवरण कार्यों द्वारा पेश किए गए नगण्य ओवरहेड के साथ PIL / तकिया को हटा रहा है। यह ओपनसीवी (जो पीआईएल / पिलो का लाभ नहीं उठाता) को साइपी (जो करता है) के विकल्प के लिए बहुत अधिक उपयोगी होता। बहरहाल, समर्पित बेंचमार्किंग के लिए धन्यवाद! SciKit द्वारा लगाया गया घटिया मंदी आकर्षक ... और भयावह है।
सेसिल करी

@CecilCurry OpenCV के साथ विचार के लिए धन्यवाद! कुछ खाली समय मिलने पर मैं इसे जोड़ूंगा।
मैक्सिमिलियन पीटर्स

Upvoted! ऐसा कोई उत्तर नहीं, जिसकी मुझे तलाश थी, लेकिन फिर भी बहुत दिलचस्प बात है :)
सिरिल एन।

29

आप हमेशा imreadOpenCV का उपयोग करके शुरुआत से ही चित्र फ़ाइल को ग्रेस्केल के रूप में पढ़ सकते हैं :

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

इसके अलावा, यदि आप छवि को RGB के रूप में पढ़ना चाहते हैं, तो कुछ प्रोसेसिंग करें और फिर ग्रे स्केल में बदलें जिसे आप cvtcolorOpenCV से उपयोग कर सकते हैं :

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

6
फीट: 0झंडा है cv2.CV_LOAD_IMAGE_GRAYSCALE
dtk

24

सबसे तेज और वर्तमान तरीका पिलो का उपयोग करना है , जिसके माध्यम से स्थापित किया गया है pip install Pillow

कोड तो है:

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

3
ध्यान दें कि, यदि आप ऊपर दिए गए उदाहरण की तरह अपने तरीकों का पीछा नहीं कर रहे हैं, तो convertछवि की एक परिवर्तित प्रति लौटाता है
मैट

32 बिट PNG के लिए काम करते हैं, मान लिया जाएगा नहीं है clamped 255
एंड्रयू Matuk

11

ट्यूटोरियल धोखा दे रहा है क्योंकि यह आरजीबी में एनकोडेड एक ग्रेस्केल इमेज के साथ शुरू हो रहा है, इसलिए वे सिर्फ एक ही कलर चैनल को स्लाइस कर रहे हैं और इसे ग्रीसेकेल मान रहे हैं। आपको जो मूल कदम उठाने की ज़रूरत है, वह RGB Colorpace से एक ऐसे Colorpace में बदलना है, जो Luma / क्रोमा मॉडल, जैसे YUV / YIQ या HSL / HSV, के साथ कुछ एनकोड करता है, फिर luma जैसे चैनल को स्लाइस करके उपयोग करें आपकी ग्रेसी छवि। matplotlibYUV / YIQ में कनवर्ट करने के लिए एक तंत्र प्रदान करने के लिए प्रकट नहीं होता है, लेकिन यह आपको HSV में परिवर्तित करने देता है।

matplotlib.colors.rgb_to_hsv(img)अपने ग्रेस्केल के लिए एरे से अंतिम मान (V) को घटाते हुए उपयोग करने का प्रयास करें । यह एक लूमा मान के समान नहीं है, लेकिन इसका मतलब है कि आप यह सब कर सकते हैं matplotlib

पृष्ठभूमि:

वैकल्पिक रूप से, आप पीआईएल या बिलिन 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'))

हालाँकि, GIMP रंग को ग्रेस्केल इमेज सॉफ्टवेयर में परिवर्तित करने के लिए कार्य करने के लिए तीन एल्गोरिदम हैं।


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, आप इमेजियो का उपयोग करके रंगीन छवि को ग्रे स्केल में कैसे परिवर्तित करते हैं?
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
क्या 5 वीं पंक्ति होनी चाहिए img = img.convert('L')?
एलन रुइन

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)
Ak25all 15:17 बजे

@Akavall जानकर अच्छा लगा, धन्यवाद! क्या आपको पता है कि आपका शॉर्टकट तेज़ है? यदि नहीं, तो मैं अपना रखूंगा क्योंकि यह समझना आसान है।
मार्टिन थोमा

मैंने इसे समय नहीं दिया, मेरी आंत की भावना numpy.averageथोड़ी तेज है, लेकिन व्यावहारिक रूप से अलग नहीं है। आपका समाधान स्पष्ट है और आर, जी, बी के बारे में प्रासंगिक जानकारी है, इसलिए मैं इसे रखूंगा। मेरी टिप्पणी एक अतिरिक्त विकल्प की अधिक थी, प्रतिस्थापन की नहीं।
अकवाल

दोनों scipy.ndimage.imread()और scipy.misc.imread()कर रहे हैं औपचारिक रूप से बहिष्कृत कर दिया गया SciPy 1.0.0 में किया जाएगा और स्थायी रूप से हटा SciPy 1.2.0 में। आप शायद इसके बजाय तकिया के बिलिन ग्रेस्केल रूपांतरण समर्थन (अला अनटुब का उत्तर ) का उपयोग करना चाहते हैं ।
सेसिल करी

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

आप greyscale()सीधे रूपांतरण के लिए उपयोग कर सकते हैं ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.