Placeholder Image

Subtitles section Play video

  • Hello.

  • It's been a while since I've done one of these videos, but this video is eight bits of image processing.

  • You should know, and you might be thinking, Well, why do I need to know anything about image processing?

  • Well, images are just too dear rays of data on the algorithms that we apply to this data can shape.

  • It's in useful ways.

  • Obviously, some of the applications involved images and cameras and video footage.

  • But there's also other ways of manipulating two D data to your advantage, for example, in things like procedural generation.

  • On the whole, I think most programs should have an awareness of image processing.

  • It is a very useful tool to have in your toolbox.

  • So let's get started.

  • Before I start, I'm going to show you the video that I've created to demonstrate the eight bits, and it's quite nice because it allows us to quickly compare the algorithms.

  • So here it's going to show the first bit, which will be fresh holding, and we can choose different numbers to look at the different algorithms and see what their effects are because it's working with video, you see, here's a live feed of my arm waving around.

  • I think it makes quite a nice interactive tool, which is great for learning.

  • But this video is going to be a bit different to some of my others are not going to go through it line by line from scratch.

  • I've already created the code, and what I really want to emphasize is what is the image processing that is going on?

  • And how does it work?

  • Bit one.

  • This is the process of beina rising an image.

  • Here I have an image.

  • I'm going to assume it's a grayscale image, so the pixels go from black to white.

  • Fish holding involves taking an individual pixel on, classifying it as being above or below.

  • Official.

  • If it's above the threshold, you are the one.

  • If it's below the special, you output zero.

  • This green line represents a single row in our image.

  • If I take this row on plot its exposition against the brightness of that pixel, I might get something that looks like this.

  • Fresh holding involves specifying an appropriate value to access a cut off so any pixels above that value will get classified as one on any below.

  • It will get classified to zero.

  • The red dash line represents my threshold value.

  • So now with my blue pen, I can indicate what the binary equivalent of this might be.

  • So it starts down here in zero.

  • But that goes above the threshold toe one below.

  • Officials above the session old, and we've finalized our image to demonstrate these programs.

  • I'm using a pixel game engine application that I've already created on.

  • I feel it's necessary to give you a brief overview of what this application is before we get stuck into the algorithm code, just so it makes some sort of sense.

  • Fundamentally, it's based on the idea of a frame, which is a fixed to de array of pixels, in this case 3 20 by 2 40 the pixels of floating point type.

  • So instead of working with RGB values, I'm taking the RGB from the camera and converting it to a floating point value between zero and one by converting to the floating point domain from the interview, domain allows me to avoid complex cities such as interview division.

  • This simple frame class has some accesses get and set, which will do boundary checks for me, so I could quite happily set, the pixels value beyond the edges of the image.

  • And if I get something from beyond, the image just returns a black pixel.

  • So zero is black on white is one.

  • My frame class also overrides the assignment operator, so I can have multiple frames in my application, and I can transfer the contents of one frame to the other.

  • With these for this video, I'm not going to dwell on the image capture side of things.

  • I've already done that in other videos, and it's enough to say that we simply use the escapee library to capture a frame from a webcam.

  • So in on user create, the webcam is initialized and in on user update, I capture the image from the webcam per frame and convert the pixels to floating point and store it in a frame called input.

  • This program shows eight different algorithms, and so the bulk of the code shown here handles the selection of which algorithm is currently being demonstrated on.

  • The algorithms also have a degree of user input, which allows the user to change the values to play with the algorithm and see how they respond under different circumstances.

  • For example, when the user presses the one key on the keyboard, it changes the current algorithm being demonstrated to threshold.

  • So let's continue looking at that algorithm.

  • Here it is on dhe.

  • You'll see this on most of the albums.

  • We do a little bit of user input if their values to change and then we actually perform the algorithm under demonstration on fish.

  • Holding is very simple.

  • For all of the pixels in the frame, we read the input value of a pixel for that location.

  • Compare it with a threshold value, which will give us a one or a zero in response.

  • And then we write that to an output frame at the end of the program.

  • I then draw the input and output frames.

  • Hopefully, you can see fresh holding is very simple indeed.

  • So let's take a look at it.

  • This is Dash holding now.

  • My webcam has some automatic gain correction, which is what you saw then, as the image sort of changed and faded, I can't override those settings using the AP I for the camera, but for this video, it doesn't really matter.

  • I'm in fresh hold mode now on.

  • We can see The input image here on the left is in gray scale, but the outputs image here on the right is in black and white.

  • It's been buying arised on, it says here, I can use the said an excuse to change the value of the fresh holds A.

  • Currently it's 0.5.

  • It's halfway between the minimum and maximum intensity is for the gray scale.

  • As I increase the threshold value, we see less pixels being attributed to a binary one.

  • As I decrease it, we see the opposite.

  • Fresh holding is essentially the coarsest of filters, and this is usually the first step in removing as much rubbish from an image as you can.

  • For example, here you can see on the notebook the text.

  • One lone coder comes through quite clearly, but the lines on this, like grayness off it doesn't so if we were then to go on and extract this text, for example, it's much easier now.

  • We're not contaminated with this spatial background noise with fresh hold.

  • It is out bit to motion on for this video.

  • I'm assuming the simplest kind of motion.

  • We won't be able to get any direction.

  • Information from this.

  • The word motion implies that something has moved on for something to move takes time.

  • So to detect motion in an image we need to allow time to have elapsed.

  • Fortunately with video, this is quite simple because a video camera returns successive frames in time, which means we have a built in Delta time between each frame alongside movement in time.

  • Motion also implies movement in space.

  • The object was in one location, and now it's in another.

  • But for this bit, let's not think of objects as being the things we're looking at.

  • Instead, we're looking at pixel grayscale values.

  • So over time, if something is moving in the image, a particular pixel value is also changing.

  • So we can identify that motion has occurred by looking at the difference off pixel values between successive frames of video input on DSO.

  • On this graph, we can see that the difference between A and B is related to the change in that grayscale value.

  • The end result of this could be signed and in some applications.

  • That's a useful thing.

  • It gives you additional information, but for our application, I'm just going to take the absolute value of this to tell us that motion for that pixel is likely to have occurred.

  • The code for motion detection is equally a simple us thresh holding.

  • I'm going to go through every single pixel in my frames with these nested four loops, and I'm going to look at the difference between the current frame onto the previous frame by subtracting them on them, taking the absolute value of that result on dhe, setting that in the corresponding location to the output frame and then draw the input and output frames.

  • I update the previous input frame before I acquire a new image in the input frame.

  • Here's the algorithm running on its looking at a reasonably static scene, but as soon as things start to move, I'll bring my hand into the scene.

  • We're looking at the difference between one frame and the previous frame, but we only see illumination in the output where there has been changed.

  • So that signifies that motion has occurred in those locations because the frame rate of my camera is reasonably quick.

  • It's about 20 face per second.

  • I get what looks like an edge around the object that's moving, but don't be fooled by this, it's not strictly an edge, although you can use it as an edge.

  • It is just the difference between the two frames.

  • Motion detection like this is usually a foundation algorithm.

  • It is used to guide your decisions in subsequent algorithms that you apply to the image.

  • For example, I might want a system to shut down if nothing in this scene is moving, I mean, why bother taking more images if nothing has changed?

  • So I could detect that by accumulating the sum of all of the pixels in the output image and then checking that against a threshold value to tell me, has there been enough motion in the image for the system to switch on bit three Low past temporal filtering, as we've just seen in bit to the value of a pixel changes over time.

  • And if we look over a longer period of time, we might see that the pixels change values quite rapidly between frames.

  • This is called noise because sensors aren't perfect.

  • Lighting conditions, electronics and all sorts of things could influence the value of a pixel.

  • This noise can cause problems because what we actually want to see is the real value of the pixel change over time, she's indicated by this green line, we can approximate that.

  • That's somewhere in between all of these noise values.

  • A noise could become a problem if you do things such a stash holding because the noise might just tip you above or below the fish hold inappropriately.

  • We effectively want to run the grayscale value of the pixel through a low pass temporal filter, so the low frequency component of the pixel is allowed.

  • Food on the high frequency components are removed.

  • We can approximate this with a very simple equation for a given pixel value.

  • P.

  • We're going to update that pixel value by looking at the difference between the input pixel value on the current pixel value and multiplying that by a constant.

  • Fundamentally.

  • If this distance is small, then the change in our output pixel is small, and if it's large than the change in our output, pixel is large, but we can regulate that change with this constant in engineering.

  • This is also known as an R C.

  • Filter on its implementation is very simple.

  • In the low passed section of the program, I'm doing some user inputs so I can change the value of this temple constant.

  • And then I iterated through all of the pixels in a frame.

  • I look at the difference between the input on the output.

  • I scale the difference with our temporal coefficient, and then I accumulate that difference back into the output frame with this plus symbol for this algorithm.

  • The output frame is persistent between updates of the video camera feed, meaning that output pixels our only changed by a small amount, depending on how large the change waas off the input.

  • So here in the program are now running bit through the low pass temporal filter on the two images look very similar.

  • It might not even be that possible to see on the YouTube video, but the input image on the left actually has quite a lot of per pixel noise.

  • But the output image on the right has no temple noise visible to the naked eye.

  • If I move my hand into the scene, this is a particularly slow filter, so I could make rapid changes by wiggling my fingers around here.

  • But we can see that the output image doesn't change very much.

  • It's ignoring those fast changes, only allowing the really slow changes.

  • If I leave my hand in a fixed position.

  • Eventually it feeds into the image, so this is exaggerated in a way I can use the SET index keys to change the value of this constant, but I can make it very slow indeed, which might not immediately seem a useful thing to do.

  • But if you wanted to do some background subtraction algorithms over moving images, this is quite a nice way to do it.

  • You can accumulate the background of an image over time and then use that as a way to isolate things in the foreground.

  • If I increase the value of the constant, it becomes far more life.

  • Let's keep going a bit until the two images look very similar indeed.

  • But if you get it too high this concert, you'll start seeing the per pixel camera noise coming back into the output image so low pass Temple filtering is a great way to filter noise, and it also looks all ghostly and cool bit for convolution.

  • Where's the previous two bits have looked at filtering things in the time domain.

  • Convolution looks at filtering things in this spatial domain.

  • Fundamentally, we're going to decide what to do with the pixel by looking at its neighborhood for this example, I'm going to look at the immediate three by three neighborhood of our target pixel on this neighborhood is called a colonel.

  • And you can think of a colonel as a template of coefficients.

  • That's a used in a dot product of the neighboring pixels in that region on values of the Colonel to give us a result for the central pixel.

  • So my colonel might be defined here as a three by three matrix of values.

  • These values are over laid over the corresponding pixel in that location, and we also include the central value, which is the target pixel.

  • I can give these colonel values location, information, toe, identify the relationship to the target pixel.

  • I work out my final pixel value by performing the dot product between a colonel coefficient onto the grayscale value of the pixel at that location.

  • So this component, for example, is this component of the colonel well supplied by this pixel value.

  • And we go on to go through all of the colonel locations.

  • And so what effect do you think this colonel might have, then Well, we can see it is being regions of influence were strongly influenced by the target pixel, the one in the middle.

  • But we're also a little bit influenced by our immediate north, south, east and west neighbors.

  • Conveniently in this Colonel, all of these values ad upto one.

  • This is quite deliberate.

  • So we take the bulk of our pixels value from what it already is.

  • But then we take a little bit from its neighbors.

  • But we still land within the approximate range for that pixel.

  • This will give us the effect of blurring the image because we go on to apply this colonel, every single pixel in the image.

  • I've implemented convolution in a really naive way.

  • Here.

  • I'm going through every pixel in the frame and for each location I'm accumulating into an F some variable.

  • My colonels are three by three, but I want to get the corresponding offset location for a colonel coefficient in my image.

  • So I've got an additional two nested four loops which iterated through the values in my colonel.

  • The colonel we've just created is a blurring colonel on I'm representing.

  • That is just a array of nine floating point values.

  • I index into the appropriate location of that colonel using some simple two D 21 day arithmetic.

  • Once I've got the right coefficient, I multiplied by the input grayscale value and accumulated into my F some variable.

  • I then set my output pixel for that location to the F some variable.

  • In this demonstration, I've included two colonels blurring and sharpening.

  • But the coefficients of the kernels are quite different.

  • There's a little bit of user input at the top to choose which Colonel we're going to apply to the image in the demonstration program.

  • I've chosen bit forth the convolution, and it's currently running theblaze going Colonel, and we could see that the input image on the left is sharper than the output image on the right.

  • This blowing only occurs once over a three by three neighborhood, so it's a very delicate blur.

  • However, if I press the X key, I can change to the sharpening Colonel and we can see that this colonel has the effect of enhancing any areas of high contrast in the image.

  • You may have seen these filters in popular art programs.

  • The downside to sharpening of course, is it also sharpens all of the noise.

  • So we may want to combine convolution with some of the previous filtering algorithms we've already seen.

  • In this convolution example.

  • I've used a very small colonel three by three, so it can only look at its immediate neighbors for blurry.

  • For example, if we wanted to have Maura blurry image, there's two ways to go about it.

  • The first is we could repeatedly blur the image.

  • So once we've blurred it once, we then use that as the input on Blow it again and again and again and again until we've got the desired level of blood.

  • A second approaches to use a much larger colonel, so we could go five by 57 by 7 11 by 11 Whatever you want.

  • But the colonel's and the convolution I've shown here are four levels of nested for lives.

  • They will explode a computation and become very slow and difficult to get any kind of real time performance.

  • If you're serious about doing convolutions on most image processing techniques and programmers are, then you'll want to do your convolutions in the Fauria domain, the frequency domain instead, where you take the fast Fourier.

  • Transform off your input image on your fast Fourier.

  • Transform off your colonel, combine them and then take the inverse for your transform of the result.

  • And this will allow me to get very large colonels with a fixed computational overhead, a far more suitable approach for real time image processing.

  • Bet five Cybele edge detection edges in images indicate worthy information.

  • Oven image is simplistically because edges indicate were spatial.

  • Change has occurred in this example image we have background on.

  • We have a box the background doesn't change locally on the box doesn't change locally, so there's no relevant information in either of those zones.

  • So one could argue that the box is really only defined by how it is different to the background on this difference lies along the edge of the box, so detecting edges is quite an important step on.

  • Perhaps the most classical way to detect edges is using some bells edge detection, which is a perv.

  • Colonels used in a convolution.

  • The two colonels detect edges in the two main directions.

  • We've got horizontal.

  • The colonel looks something like this, and we've got physical.

  • If we can Volvo the image with the horizontal colonel, we will see the horizontal edges, and then we'll convey all the image with the vertical colonel, and we'll see the vertical edges will then combine the horizontal edges and the vertical edges into a single output image to show us all edges as before with the motion detection.

  • The sign bit of the result of these convolutions can contain useful and interesting information, but I'm going to throw it away by taking the absolute value of the results of these convolutions.

  • The sub l part of the code is exactly the same as the convolution part of the code before, except I'm doing the two things at once.

  • I'm maintaining to summation variables instead of the one on.

  • When I'm writing the output summation, I'm taking the average of the sum for the vertical and some for horizontal components.

  • I've defined the colonel's for Cybele in exactly the same way as I did before.

  • They're just a raise of floating point values.

  • Here is the demonstration program running the sub L edge detection algorithm.

  • On As we can see, edges are illuminated on boring surfaces.

  • I those that have low frequency spatial information that remain black.

  • The nice thing about Sibyl is it works on this gray scale input, and you could see it starts to highlight all of the areas of high frequency information.

  • So look at my really hurry arm that it's quite a visible thing.

  • So that's that's really indicated texture Bit six morphological operations, even though that sounds like a mouthful at morphological operations, are really a study of how things look specially in the image.

  • We want to do things regarding the shape of objects in the image, and we do this by working in the binary domain, so we must threshold the image.

  • First to bind.

  • Arise are pixels to 01 values on.

  • For this bit.

  • It's really split into three different bits.

  • The first I'm going to look at is called erosion.

  • In this simple demonstration image, I'm assuming that the background is zero on my object is one.

  • Erosion is the effect of eroding a single pixel off all edges of our object, effectively shrinking it.

  • And it's useful to remove airiness spurious pixels from other stages of image processing.

  • Because if I had a single pixel like this, or a cluster of single pixels in a line and I rode it.

  • Then if we're removing a one pixel from all edges, it's going to disappear entirely.

  • Where is larger objects?

  • The morphology remains intact.

  • The opposite to erosion is dilation, and it is quite literally the opposite.

  • This time we grow a one pixel boundary around our shape, so just going back to the previous example.

  • If we have some spurious small information on, we first erode it to remove it, and then we dilate the image again.

  • There's nothing here to actually die late, but our original shape will go back to something very similar to how it waas originally.

  • So this is a nice way of removing spatial noise from an image.

  • In many ways, implementing morphological operations is very similar to convolutions, but this time we use logic instead of dot products.

  • Looking at erosion, we use a very similar three by three colonel toe how we used in the convolutions.

  • But this time my colonel is just going to be a three by three matrix of logic ones for every pixel in my source image.

  • I overlay my morphological operation Colonel for that pixel.

  • So let's, for example, say I put it here centered around this pixel.

  • I then do a logic.

  • And with all of the elements in the colonel on all of the elements in the image, in this case, we can see that one on zero here is well, zero.

  • And this one's going to be zero.

  • This one's going to be zero on once we've handed all of those together, the end result is going to be zero because we've got some zeros in there.

  • So I will write to my image.

  • Zero.

  • However, when I get round to operating on this section of the image, the result is a logic one.

  • Because all of the colonel coefficients on all of the surrounding neighborhood pixels are going toe and together to give me a warm.

  • This pixel that was on its own has been eroded.

  • But this pixel that is robustly supported by its neighborhood stays intact.

  • Instead of just doing logic.

  • And we could also do some simple arithmetic.

  • We could count how many of our neighbors are equal to one and come to the same conclusion.

  • So in this case, I've got eight neighbors all equal toe one.

  • So my current value pixels of one But in the original scenario, only three of my neighbors were one, so I could then look for less than eight neighbors on in that condition.

  • I set myself to zero.

  • Now the interesting thing with erosion is that one man's erosion is another man's dilation.

  • If I inverted all of these bits and applied the same Colonel, I would have the effect of dilating the image.

  • But I can also dilate in a second way without requiring this inversion on that this one is quite simple.

  • If given pixel exists, then set its neighbors to exist as well.

  • On this would have the effect of growing object by one pixel along all edges.

  • Before I get stuck into the code on this, I just want to show visually another useful thing for dilation.

  • That if I can identify a particular point on an image, let's say here and I repeatedly dilate, I can effectively flood fill in the image.

  • Now there's an important condition here is that after every dilation, if we logically and that with the original image, will never go beyond the boundaries of the original image.

  • So this allows me to fill a secondary image with just the space occupied by single shape in binary space of the input image on this is a great way for doing image segmentation, the extraction of objects or labeling image parts.

  • In fact, I find this to be really interesting, and I think it's worthy of a video in its own right.

  • Got some interesting examples of how we can demonstrate that So expect in the near future of follow up video to this just showing morphological operations in the code.

  • The morphological section is the largest of them all.

  • It's got a great degree of user input, one to select which particular dilation or erosion operation we're going to do.

  • There's also 1/3 1 called Edge, which I'll talk about when we get to the code.

  • But I can also control the number of times that I perform the dilation over or erosion, and so we'll be able to see those effects visually.

  • But the first thing on the most important thing is we need to take our image from the grayscale domain into the binary domain, so I'm just fresh holding it on.

  • I'm going to fetch hold it, using the value that we've specified in the fish hold algorithm, so this will allow you to tweak the threshold first.

  • Then we go on to choose dilation erosion.

  • Or this 3rd 1 which I'm calling EJ is going to be an edge detect using morphological operations for dilation.

  • It was simply a case of seeing, if given pixel value is equal to one.

  • Then set all of your neighbors toe one too easy enough.

  • But I use this third register activity because I don't want to alter the frame as I'm going through the pixels.

  • It's important that the frames are treated homogeneous, Lee for erosion rather than doing set of logical operations.

  • I decided to go with the summation route.

  • So I'm looking at all of the values of my neighbors on all of the ones that have one.

  • I'm swimming together Now.

  • I know that in my activity frame, they're going to be ones or zeroes.

  • Anyway, we've finalized the image, so I'm just going to add them.

  • I'm going to check to see if my activity is one and if it is, but not all of my neighbors are set to one, then I'm going to set myself to zero, put myself out this 3rd 1 which I have not drawn up.

  • In one note, I've called EJ, and it's exactly the same as erosion.

  • But instead of looking for a less than eight neighbors, I'm looking for precisely eight neighbors in the situation that I am an illuminated pixel on.

  • I have all of my neighbors.

  • I'm going to extinguish myself.

  • So let's take a look.

  • The program has started up with fresh hold image, and this is just so I can tune the threshold value appropriately.

  • I can still tune it later on, but it's just a bit easier to do whilst looking at the grayscale image.

  • Then I'm going to choose bit six more binary morphological operations.

  • Now the current operation is dilation on dhe.

  • It looks like there's just a single interational being applied.

  • So on the left, where these individual pixels occurring, you can see they're expanding into a three by three region.

  • This has had the effect of removing the one loan coded text entirely from the book object, so this might be a precursor restage in being able to extract Where is the book this time?

  • If that's useful, I can increase the number of violations with the A and S keys.

  • And as you might expect, the region's just grow.

  • So dilation is a way of grouping things together.

  • Erosion is a little different here on the left.

  • Those spurious single pixels have all but disappeared, as has a lot of the noisy background.

  • So erosion has really just allowed us to focus on the core parts of the image.

  • If, for example, I rode this image and then dilated it well, I can't bring any of that background noise back in.

  • We're looking at the eroded image.

  • Now.

  • If I dilated this, there's no source pixels to cede anything for dilation.

  • So combining these two operations is a nice way to remove noise that's at multiple erosions, and eventually we can erode the image away entirely.

  • Erosions and violations, as I demonstrated very briefly, can be used for detecting and labeling objects individually on in a primitive way.

  • They can also be used for sizing objects.

  • If you continuously eroded the scene on looked for the finally illuminated pixel.

  • You could then dilate that pixel on dhe logically, and it back into the scene toe highlight the largest object so you could use the erosion and dilation for sizing, too.

  • Now, finally, there's one more mysterious one.

  • If I press the sea key on that is using morphological operations to detect edges on.

  • This gives you a really nice edge.

  • Detect where all of the edges are a single pixel.

  • If I bring my hand into the scene, it's a bit messy.

  • Let's find a nice high contrast scene.

  • There we go.

  • That's quite nice for it.

  • Isolating all of the buttons.

  • Now you see the cameras adjusted in gain there.

  • Not much I can do about that.

  • But this is different to see Belle and that it gives you a really crisp outline edge for an object bit.

  • Seven.

  • Median filtering When working with real world sensors, things don't always go to plan.

  • Sometimes your image will have little tiny artifact in it.

  • He's a bad pixels, or snow, depending on might be in a radioactive environment for all I know, but you end up with something which doesn't look quite right on.

  • These are usually quite tricky to filter out unless you use a median filter.

  • Median filters are conceptually very simple.

  • In a similar way to convolution forgiven pixel, we look it's it's immediate neighborhood.

  • In this example, I'm using a five by five neighborhood on dhe.

  • We're going to make an assumption in our image that we're not really expecting special change toe happen over a single column of pixels or a single row of pixels.

  • That's quite unusual in natural images.

  • So it tends to be that, in general, information and images is rather blurred out across the image.

  • So up here, where I've got this single Aaron, it's pixel.

  • I can make an assumption that most of my image in that region is behaving one particular way and that this black pixel is some form of outlier on.

  • We could statistically remove the outline by looking what the median pixel value is across all 25 pixels in this five by five.

  • Colonel.

  • If you don't remember what the median is, you take all of your values and you sought them in order, and you take the one that lies directly in the middle of that sorted set.

  • It's one of those quirky mathematical phenomena where it sounds really complicated mathematically, but there's actually no maths involved.

  • It all it's just sorting on an extraction for the median filter code as usual, I'm iterating through all of the pixels in the image on.

  • I'm not trying to optimize this att.

  • All.

  • I want the code to be readable s.

  • So I'm going to do something really horrendous and creative vector of the floating point values, which represents all of the pixels surrounding the pixel on currently investigating over this five by five area on.

  • All I'm doing is extracting those pixels in my neighborhood on pushing them into the vector.

  • Once I've got 25 pixels in my factor, I then sorts them using Standard Sort.

  • Since I've got 25 pixels, the one in the middle, it will be at the 12th location off my vector.

  • And that's what I'm choosing as my output value.

  • It's pretty simple, huh?

  • And so here in the demonstration program, I'm now running the median filter on.

  • You might be at first thinking it's just blowing the image, but it's not.

  • It kinda looks like it's painted it a little bit, so I'm sure median filtering is used in some of these arty effects programs.

  • But I do have a test image that I've created here.

  • We got the words median filter written on my page, and you can see the media filters filtered out the lines because it sees those is anomalous, and it's also filtered out to the dots.

  • But the sufficient information left in the text to then go on extracted using fresh holding or morphological operations or something else.

  • So it's just a precursor re phase to help you with later stages of image processing once the dots get large enough that they occupy a region.

  • In fact, even so, Zoom didn't like that.

  • You really would struggle thio identify the dots, but the text is just fine.

  • So when you get to this sporadic salt and pepper noise in your image median filter is the thing to choose and finally bit ate locally adaptive threshold.

  • I started this video with bit one, looking at fresh holes that were applied globally across the image.

  • More often or not, this is sufficient.

  • But there are situations where you want to threshold on image based on local information.

  • Working under the same principle as the median filter, we make an assumption that, overall, for a small region of image, there's not going to be a great deal of spatial variance.

  • So it's better to choose a fresh hold value based on the information in your locality, or at least bias towards a threshold value found from the information of your neighbors.

  • So I know, for example, in this region of the image, if I take the average value of my neighborhood, then things that are statistically interesting, maybe a certain level above that average, and that average might be different for different parts of the image.

  • Which means if I used a global fresh hold, that special value may not be appropriate for different regions of the image.

  • It might not be immediately obvious what locally adapted fresh holding buys you compared to a global fresh hold, but I find it really useful when you got change in lieu eminence across your scene.

  • Changing luminous is just a fancy word for shadows.

  • We're now getting quite familiar with the code for these algorithms.

  • We're going to reiterate through all of the pixels on in this case, I'm going to take the average value of my immediate neighbors five by five, but I'm then going to use that average as part of my fresh holding calculation region.

  • Some contains the average.

  • But I'm going to buy us that value with some user defined constant.

  • And that constant is user configurable over the user interface before we go on to threshold the image.

  • So let's take a look here.

  • I've got the input and output showing just the regular fish hold.

  • This was the one we started with bit one, and I can try and find a value which sensibly thresholds the image.

  • But you can see it's a global effect.

  • And one of the things I wanted to show here is that the shadow cast by my hand is influencing that fresh whole decision.

  • I'm going to press that the eight key now to choose the adaptive threshold and we could see straight away.

  • The difference is that my shadow has basically become irrelevant to the scene.

  • The local area around each pixel is used to guide what value were using to fresh hold it against, and so the areas in shadow have overall but lowered the threshold value in the areas of brightness and overall have raised the threshold value.

  • And so we're choosing a value which is varying across the screen in order to make our fresh holding decision.

  • So if you wanted to make things that are shadow and luminous in variant, then you probably do need to use some sort of locally adapted fresh holding algorithm.

  • It's also quite a cool visual effect, too.

  • And so that's that.

  • Image processing is a huge field for May I find it to be a very interesting one, too.

  • In this video, we've had a very quick look, very cursory introduction to some of the most fundamental techniques you need.

  • If you wanted to start doing image processing, as I mentioned in the introduction, you don't always have to work with images.

  • Procedural generation may also employ a lot of these techniques to particularly the morphological operations.

  • Anyway, that's it for now.

  • If you've enjoyed this video, you're a big thumbs up.

  • Please have a think about subscribing coming up a chat on the discord server.

  • I'll see you next time.

Hello.

Subtitles and vocabulary

Click the word to look it up Click the word to find further inforamtion about it