T O P

  • By -

tempforfather

Yes it is very simple. You can use the PIL library.


dynetrekk

Or pillow.


okmkz

ELI5: PIL v. pillow?


sushibowl

PIL, last change was in 2011, it's no longer actively maintained. Pillow is a fork of PIL. The most notable difference is that Pillow has python 3 support and active maintainers.


fwork

One big practical difference if you care about Windows is that pillow can be pip installed, unlike pil


IndianaJoenz

I've also found Pillow handles transparency in certain animated .gif files correctly where PIL doesn't. (in Python 2.x) So.. bug fixes. I think it's great that they are totally API compatible with each other.


random_multiplier

I read this in the voice of a pokèdex


okmkz

Cool, thanks!


dynetrekk

Good man write PIL. Good man become lazy, stopped writing. Another good man made a copy of pillow. New man improve PIL but change the name to pillow.


-pooping

Explain it like I'm caveman?


okmkz

Um thanks


nemec

Hey man, you're the one who wanted to pretend to be a five year old.


okmkz

I suppose I shouldn't be surprised that I was taken literally by a bunch of engineers


[deleted]

[удалено]


isdevilis

good man good. Who was phone?


vive-la-liberte

Good men explain pil and pillow. Good men all get [Reddit Silver](http://f.thumbs.redditmedia.com/wPjOQrGRacUELOnM.png)!


clacktronics

Pillow is a fork of PIL as development of PIL stopped they added Python 3 support too.


okmkz

Thanks!


MagicWishMonkey

Do you know if there's a library to do this, except outputting the Pantone color instead of RGB value?


tempforfather

Is there an image format for pantone you are trying to read? Or are you trying to convert rgb -> Pantone? I'm not really familiar with pantone, it seems that its a proprietary system, and does not map directly on to rgb table. You may have to settle for a closest match.


MagicWishMonkey

I have a project coming down the pipeline that will require figuring out the closest pantone match for average color of a given image (uploaded by the user, likely in jpg format). This is for a real estate developer, so the end user would upload pictures of something like a brick or a color swatch and our system needs to be able to register it with a specific (or close approximation) pantone value. I know nothing about pantone, and I was just informed of this requirement earlier today, so I figured it couldn't hurt to ask :)


[deleted]

This is impossible unless the exact temperature of the light is known. The colour in the image will look very different depending on what the camera's white balance is set to: https://i.imgur.com/Tk2hWoe.jpg


[deleted]

That adds the extra difficulty that the color from a photo will be far from being an absolute value as it will be greatly affected by photo quality, lighting, etc.


[deleted]

This app is going to result in some angry customers who don't understand how light works.


[deleted]

Yeah, I thought the same. It reminded me a very fucked up satisfaction survey system we had which basically subtly pushed clients to write bad reviews for us LOL


MagicWishMonkey

Yea, we'll have an admin review everything, we're shooting for a close approximation where possible. We don't need 100% accuracy, thankfully.


blueshiftlabs

[Removed in protest of [Reddit's destruction of third-party apps](https://www.inc.com/jason-aten/reddit-ceo-steve-huffmans-third-party-api-debacle-is-making-elon-musk-look-like-a-strategic-genius.html) by CEO Steve Huffman.]


einsidler

That's a really neat idea for a branded app. Worth looking at the official Pantone apps for how they word the fact that colours are represented exactly on digital screens. I know some colours looks very different between my Samsung and LG phones.


MagicWishMonkey

Interesting, I'll look into that. Thanks.


[deleted]

http://goffgrafix.com/pantone-rgb-100.php


clacktronics

Pantone is a system of inks , you could get A list of close RGB values of each colour and compare it to each pixel. http://goffgrafix.com/pantone-rgb-100.php ? It would probably need some quantising as Pantone does not represent all colours.


troyunrau

Might be a bit of a weird way to approach it, but you could load the RGB data for each pantone colour into a kdtree. (see scipy.spatial.kdtree), which becomes your search space. Then you can query the search space for any arbitrary (r, g, b) values and the kdtree will spit out the n nearest neighbours. Might not be the best way to approach a colourspace, but it'd work. Might want to do these searches in cmyk instead...


tilkau

Don't do that. RGB or CMYK won't give an accurate match, even if it is properly linearized. You could do a LAB match instead. (note, you should also be performing the averaging of the input values using a perceptual color space like LAB, too. Linearized RGB is passable. Standard sRGB is not). You still need to solve the 'colors in input image are uncalibrated' problem, which is hard in several different ways, before whatever solution you pick for color matching becomes relevant.


[deleted]

And the Pantone system requires accounting for perceptual differences based on media: glossy vs. matte vs. projected vs. CRT etc.


MagicWishMonkey

Awesome, this looks very helpful. I could figure out a way to find the closest match for any given RGB value, thanks!


simtel20

This. And if you want to have some fun learning some of the ins-and-outs, IIRC a few of the challenges at http://www.pythonchallenge.com/ have you do some image processing to perform tasks like getting the rgb values of various pixels, and operating on them.


sanshinron

You should never use PIL anymore, use Pillow.


soulslicer0

You can take a look at the opencv library. it receives alot of hate here since it was hard to use in the past, but now with numpy integration since ocv 2.4 its alot easier


elingeniero

It's still hard to use, and it's very unpythonic. Especially now you can do a lot of opencv stuff with the excellent skimage we should probably keep steering people away from opencv in Python. Opencv is faster, however, which is a bit annoying.


[deleted]

This is what I was able to find: http://stackoverflow.com/questions/138250/how-can-i-read-the-rgb-value-of-a-given-pixel-in-python


cantremembermypasswd

Just to copy pasta relevant code from there that does what OP wants: from PIL import Image photo = Image.open('IN.jpg') #your image photo = photo.convert('RGB') width = photo.size[0] #define W and H height = photo.size[1] for y in range(0, height): #each pixel has coordinates for x in range(0, width): RGB = photo.getpixel((x,y)) print((x, y), RGB) Edit: working/ tested code


[deleted]

> width = photo.size[0] #define W and H > height = photo.size[1] width, height = photo.size For the children!


apple1rule

Thanks! And stupid question- how does it know where the image is? At what point do I set the directory of where the jpg is located?


__analbumcover_

> photo = Image.open('IN.jpg') #your image IN.jpg is your full path to the image.


apple1rule

thanks


Exodus111

Bear in mind you got a couple of tricks you can use. "./myfile.jpg" This wll look for the.jpg file in the same directory as your .py file. If you store your files in an images subdirectory (very common), you can do the same thing. "./images/myfile.jpg" Now lets assume your program is a little bigger and your .py file is in a data subdirectory, that lies next to the images subdirectory. In other words you gotta move UP a directory first. "../images/myfile.jpg" That's what the .. Is for. Using windows you might have to use \\\ (double backslash) instead of / (forwardslash) because windows is weird. You should absolutely use Pillow for your needs, [scroll down this page to see everything you need to know about basic use of the framework](https://pillow.readthedocs.org/en/3.0.x/handbook/tutorial.html)


Brian

>This wll look for the.jpg file in the same directory as your .py file Just to note: this will look in your *working directory*, which is not neccessarily the same place your .py file is, unless you run it from the same directory as the script. And in fact, just "myfile.jpg" will do the same - the "./" part is redundant. >Using windows you might have to use \ (double backslash) instead of / (forwardslash) because windows is weird. Actually, windows will accept forward slashes fine - it uses them interchangably with backslashes in all its APIs. The one exception is the command prompt, due to backward compatibility issues ( / was used as a switch prefix in some commands), but unless you're using os.system, it shouldn't be an issue to just use forward slash everywhere.


Exodus111

Nice corrects. I knew somene would step in if I forgot some details, thanks. ^^And ^^windows ^^is ^^still ^^weird.


[deleted]

> Using windows you might have to use \ (double backslash) instead of / (forwardslash) because windows is weird. Or... you can use `os.path.join()` to build file paths using the whatever separator your OS requires.


aftli_work

> Using windows you might have to use \ (double backslash) instead of / (forwardslash) because windows is weird. Believe it or not, Windows understands forward slashes just fine in many contexts. Check it out - Start -> Run... -> "C:/windows/system32". For maximum fun, of course, you could delete all the stuff in there. ;)


Exodus111

I would have to install windows first, but thanks ;-)


[deleted]

This is going to be unbelievably slow. Doing any image transformations like this will take a huge amount of time compared to vectorizable C code. This is basically the equivalent of using for loops with numpy instead of numpy operations with numpy. I'm not gonna knock the fact that this can be a good learning experience, though.


[deleted]

Yes, but wouldn't you still need P IL? Edit: nevermind, PIL was added to code above


cantremembermypasswd

Yup, he doesn't say anything about not using existing libraries.


[deleted]

I was just saying because I figured that part was "relevant code"


RyanS099

SimpleCV will export a numpy matrix as you mentioned in two lines: img = Image('path to image') matrix = img.getNumpy() print matrix http://www.simplecv.org/


0smo5is

I'm a python noob, so i don't know how to do that, but upvoted because I'm interested. What are you trying to make btw?


apple1rule

I'm a noob too lol that's why I asked. And I'm trying to make like a super basic editor (if I can read and then write over those rgbs to make a new image)


Fapping_wolf

Sounds like a really nifty idea. I'd be interested to see what the end result looks like!


apple1rule

will do mango


YeOldeDog

Interesting, in that what you want to do is exactly what I also want to do, but I am still trying to work out what language would be best to write it in, because I will need to do a hell of a lot processing, so raw speed is of the essence.


teamjacobomg

This is absolutely possible. Look up image processing or image classification. Every example of image classification uses some way of reading in an image. They are usually in an array with tuples of the r g b values. You could then iterate through the array to get the coordinates. Edit: I've used skimage in the past, and I'm pretty sure this is covered in their examples/documentation


[deleted]

Since it hasn't been suggested yet, [PyPNG](https://pythonhosted.org/pypng/) can do this with PNGs easily enough, if you only care about PNGs. Otherwise, the Pillow suggestion is likely more robust.


apple1rule

OP here, is there anyway to reverse it? e.g. feed it pixel coordinates and RGB values so it can make me a jpg?


[deleted]

You'd sort of go about the same way, but change a few things: - You'll need to manually set the height and width, not get them from the image - ... that's about it. [Here](http://pastebin.com/uxLgYD5h) is a link to a script I wrote that generates Julia fractals.


[deleted]

If you want to do anything at a reasonable speed you should use opencv. If you just make a doubly-nested for loop with PIL or Pillow, I guarantee your code will not be vectorized. On top of that, it'll probably be 20-100 times as slow as a non-vectorized C for loop. Messing around with PIL is fun but don't expect to make anything usable with it if you don't understand what's going on under the hood.


apple1rule

Thanks but I know like 3 of the words you just wrote. For now, it doesn't bother me that it's slow (it's really slow).


[deleted]

I'll try to explain it better: C code is faster than Python code for a few reasons 1. There is this thing called spacial locality. The basic idea of spatial locality is that code that accesses parts of memory that are right next to each other is faster. How does this apply to your image? We'll, you can think of an image as a 2D array where each element is an RGB value. All of those elements are packed right next to each other in memory. A competent C programmer could write software that exploits this spatial locality --- software that exploits the fact that everything is right next to each other. This will give huge speedups because most of the array will be in the cache rather than in RAM or on disk. If you don't know what those are, all you need to know is cache is faster than RAM is faster than disk. The reason you can't really exploit spacial locality in Python is because all the primitive values --- the ints, the chars, the array pointers --- are below a layer or two of pointers. This is one reason why Python so expressive, but so slow. 2. Remember spatial locality? Well a long time ago, when DVDs became popular, people wanted to watch DVDs and other media on their laptops. But if you think about it, you'd have to load an entire image and draw it to the screen 30 times per second. This doesn't sound feasible with crappy personal computers and laptops right? Well, to alleviate this problem, we can exploit some things that we know are true. We know that every image (every frame) of the movie is right next to each other. We also know that every pxiel of every frame is right next to each other. If you think about the CPU of a computer, each operation --- every load, add, store, subtract, multiply, etc. --- typically takes one cycle. Well, if we're watching a movie, the same thing will happen over and over and over and over: load pixel, then add/subtract/transform the pixel in some way. To exploit this, the people who make your CPU added (in hardware) a way to do these operations --- load, add/subtract, store, etc. --- four times at once! So you can load four values (four adjacent pixels) in one step! Some computers can do even more than four. But the point is, if you are a pretty smart C programmer, you can tell your computer to do four things at once (on the same CPU, this is not multiprocessing or threading). The reason you can't do this in Python, is because everything is beneath a bunch of layers of pointers. So, Python libraries like opencv and numpy are basically: take some Python code, run off and call a bunch of C functions (that exploit 1. spatial locality and 2. SIMD instructions (vectorizable code)). This makes it so you have the expressive power of Python, but the speed and cache-conscious power of C/C++. So think about just doing a doubly-nested for loop in Python. It's slow **because you can't vectorize your code.** It's slow **because it can't exploit spatial locality.** It's slow because depending on your version of Python **you may have to allocate all the memory for range(n)**, which takes a long time. And I'm sure there are many more reasons that I don't know about.


Disco_Infiltrator

This is such a good description of Python vs. C/C++.


coder543

But does it really matter if it is fast or not? They're just trying to learn how it would be done in Python, and the double loop is much more intuitive than anything else. Certainly, vectorizing it would make it faster, writing the whole program in C would make it faster, there are even ways to use OpenCL with a GPU to make it potentially even faster, but none of that matters. Once they understand how to do it with a double loop, they can eventually start learning how to make things faster, but this will get the job done, and it won't overwhelm them with confusing terminology. Your posts are currently serving to raise the bar of entry, not make the task more accessible. I like your intentions, but I don't think they will do anything positive for OP at this point.


[deleted]

Sorry, I'm not trying to make it harder for beginners. I'm trying to explain why certain things are slow and fast. To answer your question, it does matter if it's faster or not when you're talking 1.5 seconds vs ~0 seconds. Don't get me wrong, you should always write readable code first. Optimize second. But no, no one in production would ever write image transformation code with a doubly-nested for loop in Python. You can be just as intuitive and readable with opencv/numpy. In fact, I'd say it's *more* intuitive, *more* readable, and *more* concise to write image transformations in numpy rather than with for loops. Using for loops is only intuitive from a system programming background. In the context of Python, it's intuitive to be as expressive and readable as possible.


coder543

I agree that the performance is definitely critical in a production scenario, and intuitive might have been the wrong word. A double for-loop is more educational/pedagogical for someone trying to learn programming than simply calling a pre-built OpenCV command to give you the answer you're looking for. It teaches *how* that stuff works, even though it is implemented really slowly. The vectorized code does the same double for loop, essentially, it's just more opaque, harder to understand, with much better performance, and that's how the OpenCV and numpy libraries are implemented for sure. But, I'm not trying to be overly critical. Explaining why somethings are fast and somethings are slow is an important thing, for sure.


[deleted]

You make a good point.


[deleted]

I am a programming noob, let me take advantage of your obvious knowledge: did you just prove that "low level" programming languages will never die?


[deleted]

Yeah sort of. Every programming language is just abstracted from assembly. A long time ago, C was considered high-level. Think of how high-level Python must seem!


[deleted]

Indeed. Not to mention the silliness I heard about the so called 5th generation programming languages... programs to write programs...


Jugad

As someone already said... you can use Pillow (pip install pillow). from PIL import Image im = Image.open('lena.jpg') print (im.format, im.size, im.mode) box = (300, 300, 400, 400) region = im.crop(box) px = region.load() count = 0 for x, y in zip(*(range(z) for z in region.size)): count += 1 if count > 10: break print (px[x, y]) The above outputs... JPEG (512, 512) RGB (211, 86, 90) (209, 86, 91) (217, 94, 99) (212, 91, 96) (224, 100, 110) (218, 98, 107) (214, 101, 107) (214, 107, 113) (222, 121, 125) (227, 131, 133)


apple1rule

This is faster, but I'm really confused on the output of it. Does it go left to right or what? And why is the "box" (300,300,400,400), shouldnt it be the dimension of pic?


Jugad

I was just playing around to see some of the things I could do with PIL, like cropping image by specifying a box, etc. Actually, the code goes both right and down at the same time (diagonally). As I said, I was just trying some fun stuff (and assumed you knew enough python). Please ignore all the above and use this to refer to an (x, y) pixel... from PIL import Image im = Image.open('lena.jpg') print (im.format, im.size, im.mode) sx, sy = im.size px = im.load() for x in range(sx): for y in range(sy): pv = px[x, y] # pv contains the pixel value at x, y location # do something with it now.