2

Preface:

I have an image of a coin. This is any generic image of a coin that I plug into python, and I want to make this coin a grayscale image. The variable P represents the array containing the RGB values for the picture of the coin, and I believe that I can turn RGB to grayscale by changing any RGB values under 128 to 0 while turning any RGB values above 128 to 255.

Error:

I am trying to use a for loop to turn the values in the array generated by P to 0, 128, and 255. When I do so this way, I encounter the error as:

TypeError: '<' not supported between instances of 'tuple' and 'int' ".

Code:

import numpy as np
import matplotlib.pyplot as plt
P = plt.imread('coin.jpg')
for item in enumerate(P):
    if item < 128:
        item = 0
    elif item > 128:
        item = 255
finefoot
  • 7,307
  • 6
  • 35
  • 69
  • 1
    Please note that enumerate returns a tuple : index and value. So `item` here is a tuple. You might have to compare it with `item[1]` – Sruthi V Sep 08 '18 at 05:01
  • Apart from the `enumerate` problem, that code won't loop correctly over your pixels. But even if you fix that, your algorithm won't convert an RGB image to greyscale, or black & white. – PM 2Ring Sep 08 '18 at 06:40
  • I don't know matplotlib, but it would be easy to use PIL to load & convert the image to greyscale or B & W. And Numpy can easily load PIL images. – PM 2Ring Sep 08 '18 at 06:43
  • Possible duplicate of [Read image grayscale opencv 3.0.0-dev](https://stackoverflow.com/questions/23339315/read-image-grayscale-opencv-3-0-0-dev) – KaiserKatze Sep 08 '18 at 08:23
  • 2
    You are talking about converting normal images to greyscale images, but what you really do is converting them into [binary images](https://en.wikipedia.org/wiki/Binary_image). What do you really want? – KaiserKatze Sep 08 '18 at 08:36

3 Answers3

4

Two issues. Firstly, you are not converting to greyscale. Secondly, the whole point of numpy is to vectorise and avoid for loops because they are slow.

So starting with this image:

enter image description here

You want something like this:

#!/usr/local/bin/python3
import numpy as np
from PIL import Image

# Load coins and convert to greyscale
grey = np.array(Image.open('coins.png').convert('L'))

# Threshold at 128
thresholded=((grey>128)*255).astype(np.uint8)

# Save
Image.fromarray(thresholded).save('result.png')

enter image description here

Mark Setchell
  • 146,975
  • 21
  • 182
  • 306
1

Sruthi V is right. enumerate() returns a tuple.

So instead of if item < 128 it should be if item[1] < 128

Or you could just remove enumerate() entirely if you aren't using it. It seems it will work fine without it.

SuperKooks
  • 113
  • 1
  • 1
  • 8
1

Hereby I quote from Wikipedia:

Converting color to grayscale

Conversion of an arbitrary color image to grayscale is not unique in general; different weighting of the color channels effectively represent the effect of shooting black-and-white film with different-colored photographic filters on the cameras.

So, you need to implement an algorithm to convert original images into greyscale images, that is, to convert the tuples of color in RGB space you get from enumerate() to a tuple of color in greyscale space.

Then if you want to convert greyscale images into binary images, you need thresholding.

Thresholding (image processing)

Thresholding is the simplest method of image segmentation. From a grayscale image, thresholding can be used to create binary images.

Read more about Greyscaling:

Community
  • 1
  • 1
KaiserKatze
  • 1,248
  • 1
  • 16
  • 29