-2

I am new to python (also to stackoverflow) and I need help with combining pixel color values into an image.

After searching through the web and playing around with the codes mentioned, I eventually used the following code to get the color values from a given image:

    from PIL import Image  

    filename = "INSERT_PATH_OF_IMAGE"  
    image = Image.open(filename)  

    t = list(image.getdata())  
    r = list(image.getdata(0))  
    g = list(image.getdata(1))  
    b = list(image.getdata(2))  

    print(r)  
    print(g)  
    print(b)  
    print(image)  

This outputs the numerical values of the given pixels of the given image like so:

    [r_value1, r_value2, ..]
    [g_value1, g_value2, ..]
    [b_ , b_..]

How from here would the pixel-coordinates of the colors be identified and how could they be put together into an image?

How can the print-command be structured such that

    [(r_value1, g_value1, b_value1), 
    (r_value2, g_value2, ..)]

would be the output shown?

Because (depending on image size) the amount of values shown can exceed the output terminal record (Using Pycharm), how could the printed result instead be saved in a text file? (Like: Editor on Windows OS)

The eventual goal is to create an algorithm to use with opencv (probably) with which to process images, I thought I should start with understanding how to process just standard images from pixeldata first and progress from there.

Thanks for reading!

P.S. I welcome any and every advice on what sources I should read up on, so feel free to share. =)

Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
Zerhat
  • 1
  • 3
  • 1
    Your question has already been answered at least twice, so I'm afraid it won't last long. In the meanwhile, here are 2 resources you can use : [first resource](https://stackoverflow.com/questions/12062920/how-do-i-create-an-image-in-pil-using-a-list-of-rgb-tuples) and [second resource](https://stackoverflow.com/questions/46923244/how-to-create-image-from-a-list-of-pixel-values-in-python3) – LiterallyGutsFromBerserk Jul 24 '23 at 09:58
  • Python lists of pixels are slow and inefficient. Consider converting your image to a Numpy array and processing it efficiently with vectorised OpenCV or Numpy routines. Make Numpy array from your PIL Image like this `import numpy as np`, `from PIL import Image`, `im = Image.open(...)` then `na = np.array(im)` Then you can do `print(na)` – Mark Setchell Jul 24 '23 at 10:19
  • Hi! I read through the resources mentioned, the first resource already has it structured such that [(r1, g1 , b1), (r2, g2, b2)..] is shown, which is what I am still to achieve (hence the question). The first aswell as the second do not mention how to order output values or how to save them in a text file, the second already had the colors and works from there, likewise, just as with the first, with the already desired output structure, [(r1, g1, b1), (r2, g2, b2)..]. Like written before, I need help with achieving that. Both don't mention how to save output in a text file or how to order it. – Zerhat Jul 24 '23 at 10:31
  • @MarkSetchell Thanks for your response, the output of the code suggested shows 3 lines (RGBA) followed by "..." followed by 3 lines (RGBA) line by line, which I appreciate (and will from now use). What does the "..." imply? How could that output be saved in a text file, what can be done so only the RGB values are output when run? – Zerhat Jul 24 '23 at 10:52
  • The ellipsis (...) is indicating that something has been omitted for compactness of output. I added a section to my answer so you can see how to write your CSV on `stdout`. – Mark Setchell Jul 24 '23 at 12:24

1 Answers1

2

As mentioned in the comments, try to avoid Python lists of image pixels - they are slow and inefficient. Prefer instead Numpy arrays and vectorised processing by Numpy or OpenCV.

from PIL import Image
import Numpy as np

# Make a linear gradient and resize to 8x8 so we can see it
gradient = Image.linear_gradient('L').resize((8,8))

enter image description here

# Rotate to make interesting
gradient90 = gradient.rotate(90)

enter image description here

# Make a solid black image same size
black = Image.new('L', (8,8))

# Merge the 3 channels into RGB
rgb = Image.merge('RGB',(gradient, gradient90, black))
rgb.show()

enter image description here

# Make into Numpy array
na = np.array(rgb)

# Reshape as 8x8x3 RGB array into 64x3 triplets
triplets = na.reshape((-1,3))
print(triplets)

[[ 16  16   0]
 [ 16  47   0]
 [ 16  80   0]
 [ 16 112   0]
 [ 16 144   0]
 [ 16 176   0]
 [ 16 208   0]
 [ 16 239   0]
 [ 47  16   0]
 [ 47  47   0]
 [ 47  80   0]
 [ 47 112   0]
 [ 47 144   0]
 [ 47 176   0]
 [ 47 208   0]
 [ 47 239   0]
 [ 80  16   0]
 [ 80  47   0]
 [ 80  80   0]
 [ 80 112   0]
 [ 80 144   0]
 [ 80 176   0]
 [ 80 208   0]
 [ 80 239   0]
 [112  16   0]
 [112  47   0]
 [112  80   0]
 [112 112   0]
 [112 144   0]
 [112 176   0]
 ...
 ...
 [239 208   0]
 [239 239   0]]

# Save as CSV
np.savetxt('image.csv', triplets, fmt='%i', delimiter=',')

16,16,0
16,47,0
16,80,0
16,112,0
16,144,0
16,176,0
16,208,0
16,239,0
47,16,0
47,47,0
47,80,0
...
...

If you want to output the CSV to your PyCharm terminal, i.e. stdout, you can use:

import sys

np.savetxt(sys.stdout, triplets, fmt='%i', delimiter=',')

If you want to load the image back from the CSV, you will need to know its original shape because that is not stored in the CSV. Note that it is generally a poor idea to store an image in a CSV because it is neither efficient, nor compressible, nor viewable.

It would go like this:

# Load pixels from CSV into Numpy array and reshape to original shape
pixels = np.loadtxt('image.csv', delimiter=',', dtype=np.uint8).reshape((8,8,3))

# Convert Numpy array into PIL Image
im = Image.fromarray(pixels)

# Display on screen
im.show()

# Save to disk
im.save('result.png')
Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • Thanks alot for your comprehensive response, would you also tell me how to turn the csv file back into an image (and show it)? I tried 'np.loadtxt' but I could not figure how to quite use that. (and wether that is the actual approach to it in the first place) – Zerhat Jul 24 '23 at 13:37
  • I have added a little extra at the end of my answer to explain loading back from CSV. Note that CSV is a poor format for images - it is very, very inefficient. – Mark Setchell Jul 24 '23 at 13:46
  • How did you get on with my suggestion? – Mark Setchell Jul 28 '23 at 20:09
  • 1
    I think it was a great learning experience, I have learned the neccessity of using numpy properly to code effectivly. After having applied the code you had suggested, I contemplated on what to code next - what you have posted here, including the suggestions, have been a great support pillar and reference point for what I currently aim for. Thanks alot for taking the time. – Zerhat Jul 28 '23 at 20:44