10.5: Image Processing with Pixels - Processing Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Okay, we're ready for the next stage. So now that we've kind of looked at the... the pixel array and understand how the pixel array mapped to the actual pixels in a window the next thing I want to do is think about this particular scenario. So here is our Processing... our Processing window. Now what if we have an image, and the image I have in the example that I'll work with is of a frog. So what if I have an image frog.jpeg, which I am not gonna attempt to draw a frog, has a frog in that image. Let's say I want to look at every single pixel of that frog and copy that pixel into the window. Why might I do that? Well for the one thing we know the image function frog is a function that takes an image and draws it to a given x y. So essentially what we're doing here is learning how to write the guts of this function. How we have an image, we can look at every single pixel, take every single pixel value and put those pixel values into our Processing window. The reason why we might do this without the image function is we want something else to happen right here. In the moment of taking this pixel and transfering it to the screen. Maybe we want to make that pixel, brighter or darker or turning to black and white or... insert you're much more creative and interesting idea for image processing right there. So... this is... this... if we can understand this algorithm of looking at the pixels, putting them into the window and doing something to manipulate the colors of those pixels in between... then we can start building a Photoshop and you know from scratch. I don't know what I'm saying exactly. But, you know what I'm saying. Okay, so this is the idea. Let's look at how we might do this. Ah! But before we do I want to mention something. So this is the way that I'm going to build our first example of looking at image processing however I'm going to suggest that there might be a slightly... a way that's... it might actually be a little bit better in the end for a variety of reasons. So let's just say our Processing window is here. This is our Processing window, and we have our image of our frog. What if I had another image? A blank image... another PImage object and here I actually process all the pixels from the frog into this image object through our algorithm pixel by pixel by pixel and then here I just use the image function to draw this new blank image into the window. The reason why this is useful to do is this is going to work really nicely for demonstration purposes, but as soon as the window is a slightly different size than our source image, we're going to have some problems. So this way if I am creating an empty PImage I'm manipulating the pixels of this frog. Putting it into this empty PImage and then putting that PImage onto the screen. Then my window it kind of retains its purity it could be any size I could be drawing stuff on it and I don't have to worry so much about having some type of conflict between setting the pixels and drawing stuff. So this is a nice way of working as well in terms of image Processing. I should mention that we also could just to give a third option here.... If this is my frog and this is my Processing window I could just like manipulate the pixels of the frog itself onto itself, and then draw it to the window. The reason why this is not the best strategy in all cases is once I've manipulated the pixels of the frog image to draw it the window I've lost my original frog image. So this scenario saves this frog image. It never changes it. If I'm manipulating the pixels, the new pixels are going to a separate image and that separate image is going to the window but again let's start with this simpler case of just reading the pixels of the frog and putting those pixels in the window and let's take a look at how that might work. Ok, so I'm back over here, and if I run this particular sketch... here's my frog that I just grabbed from the internet. And I'm loading the image and drawing the image and there it is in the screen. Now notice here the size. Why is my size of this window 858 by 536? That's because this image of the frog I downloaded those are the dimensions of that image and to make this example work really nicely without by accident running into a problem... you know with all this math of multiplying by width... If the width of the image and the width of the window are different.... our math has to be a little bit more sophisticated to account for that. Which is an important thing to learn in practice I would say maybe try that as an exercise. First get this idea of image processing to work with an image and window of the same dimensions, then see what happens when you change the dimensions. Although, this again is going to be a good scenario for that. Doesn't matter what size the window is because these will always be the same exact image. Okay, so let's come back over here, and think about how to do this. Now... I have from our previous example in the previous video that code commented out, so if I... Comment this back out, in and run this. I now have, oh, I have that weird... dark center white.... white edges, result. Right? Because I'm setting every, the pic, every pixel according to some arbitrary algorithm that's coloring the pixels according their distance from the center. But I don't need that here. I can get rid of this line of code and what do I actually want here? I want image dot pixels loc. Look at this single, ok it's not image, I'm sorry it's frog. Look at this line of code. What I'm saying is: "Go to that frog image, give me the pixel from that location, take that pixel and put it into the screen at the same location. For every single pixel go and get the pixel for the frog put it on the screen." Now one thing I missed is... you see how I'm loading the pixels for the window because I'm going to mess with those pixels? I probably should also alert Processing to the fact that I want to look at the frogs pixels as well. So I'm going to say frog.loadPixels(). The truth of the matter is I've a feeling if I didn't add that in this would still work. Loading and updating pixels is sort of a funny thing like, sometimes you need to, sometimes you don't. I would say: "Why not just do it all the time?" Then you don't have to worry about whether you needed to or not. Okay. Look at this. There's our frog. I just... Just to prove that this is really doing that I'm going to comment out this line of code which was drawing the entire frog image to the window. There it is. There's our frog. We have now written the guts of that image function. We have now written the code that says look at every pixel from an image and put it all, everyone of those pixels in the window. We haven't really done anything yet interesting cuz we're just verbatim taking that exact color and putting it exactly in the window. Let's look at what we might do to kind of mess with that. So one problem here is that, you know, I could start to do something weird like... Well, what if I just said like divide by 2? That's kind of a strange result right? The thing about, that's kind of cool actually, a sort of surprising result. The.. The reason why this is giving us such a strange, unintentional, confusing, difficult to predict result is remember the actual color is just this conglomerate of the RGB values into one big integer. So the actual number is somewhat irrelevant. What we need to do is actually look at the red, green and blue components individually. So what I think might be a good strategy here would be to say give me... the red part of the pixel, the green part, the blue part, and then... make a new color RGB. Okay, so I added one little bit here. What did I do? I've got my frog again it's exactly what it was before. But instead of saying that exact pixel put it there I said: "Hey, give me the red, give me the green, give me the blue, make a new color, RGB and put it there. Now I at least understand what's really going on. I now have access to the red, green, blue components of every single color. What am I choosing to do with that information? Absolutely nothing. I'm just gonna get verbatim on the screen, but I could it could be really mischievious here, and I could say: "Aha, let me swap the green and the red values." And now I've kind of done something strange to the color of this frog. So you can start to see that once I've done this I now have the ability to start doing anything I want to those pixels. I could say like you know, the blue value times 2. Which is making it much bluer. So this is really... now... now we're here in the world of image processing. We are looking at every single pixel.... For every single pixel we were grabbing the RGB components, and we are manipulating those values and drawing a new image. This is essentially what an image filter does, you know... Sell your Instagram now for 2 billion dollars or whatever and send me a thank you note in the mail or whatever. Um, so... This appetizer is in many ways a good place to stop because here you now could kind of recreate this algorithm and your assignment, your exercise would be like come up with something a little bit more interesting to do, but let's... let's... before we get Before, before I leave you with that kind of exercise, Let's think about some creative possibilities that or that go beyond just kind of changing the colors around. One thing is, the pixels are spatially oriented. We know they're x y values so we can do something different to each pixel. Right now we're doing the same operation to every single pixel. We could say like for example. What if I... You know if x is greater than 200 do this... otherwise if X otherwise do, you know, put the pixels back to normal and we can see, you know, I am only have only doing this weird algorithm to these pixels and not to these pixels. So you can start to do whatever you can kind of imagine in here, based on the X&Y values. Another idea that I might have for you is to go back to that distance idea What if I said... okay, give me the distance between the... oh sorry, the center of the window... and the xy of that pixel and now whoops, pixels loc equals a color. Why don't I say... use that distance to and... to add it, to each one of these colors. Now I can start to see well everything just got really really bright. So one thing we can notice here. Is that how do we affect the brightness of a pixel? The brightness of a pixel is affected by the magnitude of its color value. So we're using distance here but perhaps an easier demonstration would be let me just add mouseX to every single pixel color you can see that over here I'm brightening, brightening, brightening, brightening the image, of course once all those values get to 255 I have a completely white image. Another way of doing this would be to multiply each color. So what if I multiply each color times you know 1.1 I'm making each color 10% brighter. So, you know, if you're not familiar with the map function of Processing, the map function says given a value of certain range and map it to another range. So what if I have a factor? And I map the distance, the distances, you know somewhere between like 0 and 200 or something like that.... And why don't I map that to between 0 and 2? And why don't I multiply each... each component of the color by that factor? So what I've done here now when I run this... oops sorry the distance.... I'm saying, has a range between 0 and 200 map that range to a range between 0 and 2. And if you notice as I... the pixels are now darker in the center and brighter to the, towards the edge and really I think it might be more interesting if they're brighter towards the center and darker towards the edge. Look I kind of highlighted the center of this image. And why am I hard coding in the center when I could actually just move the mouse around? Now I have this kind of like flashlight effect. So I'm manipulating the brightness of every single pixel according to its distance from the mouse. Again I kind of quickly just like mocked up this demonstration the point is, it doesn't matter... What you do here. The point... What matters is I'm getting the RGB and I'm making a new color. So for you.... Come up with your own idea of how you might manipulate the image. Look, just, just, I should probably finish this video... But just to do one more demonstration. An interesting... I'm going to comment this out, so I have access to it later if I'm saving these and putting them somewhere. Something we might know about an image is the brightness of a pixel, so let's say I just get the brightness... of the frog's pixel at a given location. A threshold filter... Something we could do is we can say let's redraw this image... But I'm only going to only draw a white or black. It doesn't matter. I'm not going to draw any kind of interesting color. I'm not even going to draw a grayscale color. I'm only ever going to say... Make every pixel black. Not every... Make a pixel black or make a pixel white. Now, what if.... I make all the pixels white if the brightness of the frog pixel is greater than 100 but black if it's less than 100. Let's run this... and you can see... I sort of see the frog in there. Pixels are white or black and you can see what's the threshold? The threshold is 100. If a pixel is brighter than 100, it's white and, you know, maybe what I should do here is kind of use the mouse to control this threshold and we can start to see like I can now kind of recreate this frog image and my threshold with the mouse over here seems kind of like a nice one. For I'm seeing the frog as white and the background is black. So... the reason why I point this out to you is, this is starting to kind of walk into this area of computer vision, that we're going to look at later. If I wanted to find the frog in this image... Applying a threshold would allow me to sort of separate out the image into only white or black pixels... And maybe I could then get the average location of all the white pixels And that's about where the frog is. So you could see how like visually it's kind of almost easier to recognize it's actually not easy to recognize visually for us because we're a human being and all the colors are very meaningful to us but to a computer algorithm now it's very easy to recognize a white pixel versus a black pixel. So perhaps this idea of different types of image processing filters might be useful later as we begin to try to recognize or analyze or get, gain some sort of aspect of the... knowledge about the image according to its pixels. So these are some sample ideas of things you can do. I could just set every pixel to black or white, I could set every pixel according to the distance. I would say here is now an opportunity for you to do a couple things. One... try to invent your own image processing algorithm or recreate one that you know about. Another thing that you might consider... I don't know if I'm going to have time to put this in the videos right now or I'll come back and do it later is.... If you could make your own image by saying createImage... this is the function you could look this up in the Processing reference that makes an empty image. See if you could redo this example from drawing... and I have this, I'll try to link to it below that... from instead of drawing your pixels from the image to the window draw your pixels from an image to a blank image and then draw that blank image to the window, and then you could have that blank image rotate, grow, shrink... There's lots of possibilities for what you could do from there, but I'll try to fill in a video that covers that at some point. So maybe by the time you're watching it'll actually just be the next video. Okay. Thanks very much, and this one is finished now.
Info
Channel: The Coding Train
Views: 209,643
Rating: undefined out of 5
Keywords: icm, processing.org, PImage, pixels, array, image processing, threshold
Id: j-ZLDEnhT3Q
Channel Id: undefined
Length: 16min 9sec (969 seconds)
Published: Fri Jul 24 2015
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.