Today, I'm continuing my recent theme of thinking about peak-finding in images. When I wrote the first one (19-Aug-2021), I didn't realize it was going to turn into a series. This might be the last... read more >>

]]>Today, I'm continuing my recent theme of thinking about peak-finding in images. When I wrote the first one (19-Aug-2021), I didn't realize it was going to turn into a series. This might be the last one—but no promises!My previous post (17-Sep-2021) was based on 1-D examples. Today's post focuses on an image example (in 2-D), and it connects to using regionprops to compute gray-weighted centroids of peaks. I'll also throw in some 3-D surface visualization, just for fun. Here is today's image:url = "https://blogs.mathworks.com/steve/files/snowflakes2.png";A = imread(url);imshow(A)I'd like to see if we can focus algorithmically on these white blobby things (that's a technical term that I learned in engineering school). First, let's try computing the

...read more >>

]]>Last time, I introduced the idea of a regional maximum. Today, I want to add a concept that makes the regional maximum more useful: suppressing very small local maxima, possibly present only because... read more >>

]]>Last time, I introduced the idea of a regional maximum. Today, I want to add a concept that makes the regional maximum more useful: suppressing very small local maxima, possibly present only because of noise, that are are unimportant, before identifying the regional maxima. This "small peak suppression" can be accomplished using something called the h-maxima transform. The functions of interest today: imregionalmax, imhmax, imextendedmax, imregionalmin, imhmin, and imextendedmin. Let's get there by starting once again with the definition of regional maximum: a connected component of pixels with a constant value h, where every pixel that is neighbor to that connected component has a value that is lower than h. I'd like to elaborate on that using a one-dimensional example.y = peaksAndPlateaus;x = 1:length(y);plot(x,y)axis([-5 105 0 120])grid onI'll use dilation and

...read more >>

]]>A recent algorithm discussion on the Image Processing Toolbox development team reminded me of something I originally wanted to do a long time ago: explain imregionalmax and some related operations.... read more >>

]]>A recent algorithm discussion on the Image Processing Toolbox development team reminded me of something I originally wanted to do a long time ago: explain imregionalmax and some related operations. (I guess I got sidetracked.)For this explanation, I'll use the following sample image:P = sampleImage;imshow(P)Note that this image has a number of constant-valued rings. One might call these regions "plateaus." Here is a cross-section of the pixel values:p256 = P(256,:);plot(p256)axis([1 500 0 300])text(250,255,"plateau",HorizontalAlignment = "center", ... VerticalAlignment = "bottom")text(345,204,"plateau",HorizontalAlignment = "center", ... VerticalAlignment = "bottom")text(415,153,"plateau",HorizontalAlignment = "center", ... VerticalAlignment = "bottom")text(471,102,"plateau",HorizontalAlignment = "center", ... VerticalAlignment = "bottom")Local maximaIn image processing, the usual definition of a local maximum is that a pixel is considered to be a local maximum if and only

...read more >>

]]>The functions meshgrid and repmat have a long and rich history in MATLAB. Today, I'll try to convince you to use them less.meshgridThe function meshgrid is typically used to take a vector of... read more >>

]]>The functions meshgrid and repmat have a long and rich history in MATLAB. Today, I'll try to convince you to use them less.meshgridThe function meshgrid is typically used to take a vector of x-coordinates and a vector of y-coordinates and turn them into two matrices, X and Y, that can be used to compute a function of two variables. Here is a small example.x = [0 1 2];y = [0 10 20 30];[X,Y] = meshgrid(x,y)X = 4×3 0 1 2 0 1 2 0 1 2 0 1 2 Y = 4×3 0 0 0 10 10 10 20 20 20 30 30 30 Here is another example that illustrates how meshgrid is typically used. The example, taken from the 2nd edition (2009) of Digital Image Processing Using MATLAB, constructs a surface plot of the function $ f(x,y) = xe^{-(x^2 + y^2)} $.x = -2:0.1:2;y = -2:0.1:2;[X,Y] = meshgrid(x,y);Z = X.*exp(-(X.^2 + Y.^2));surf(Z)The variables x and y are vectors, and the variables X and Y are matrices:whos x y X Y Name

...read more >>

]]>Today, I want to convince you to use imbinarize instead of im2bw.Background: I recently saw some data suggesting that many Image Processing Toolbox users are still using im2bw, an old function that... read more >>

]]>Today, I want to convince you to use imbinarize instead of im2bw.Background: I recently saw some data suggesting that many Image Processing Toolbox users are still using im2bw, an old function that dates back to the original toolbox release in 1993. We recommend using the newer function, imbinarize, because it saves a step in the most common scenario, and because it offers additional flexibility if you need it.I'll explain by updating an old blog post topic called "Tracing George," in which I try to extract the curve shown in the following image:url = 'https://blogs.mathworks.com/images/steve/36/george.jpg';I = imread(url);imshow(I)I call this "George." I created George originally for some examples and diagrams in the book Digital Image Processing Using MATLAB. I found at some point that I needed to reproduce the outline curve, but I

...read more >>

]]>Some of us at MathWorks like to share our "NaN sightings." Here is an example to show what I mean. This is a screenshot of the tuner/metronome app that I use when practicing music. One day, I was a... read more >>

]]>Some of us at MathWorks like to share our "NaN sightings." Here is an example to show what I mean. This is a screenshot of the tuner/metronome app that I use when practicing music. One day, I was a bit startled when the app suddenly decided that my metronome tempo was -NaN. (Am I playing too fast? No. Am I playing too slow? No. Am I playing at just the right speed? Also no.)

Here's another example spotted by a fellow MathWorker. In a town near my home, you can apparently buy a lawn tractor that has been driven NaN miles.

And a third MathWorker was helping a family member file their taxes and received this surprising summary of the results.

If you spot some amusing NaNs in the wild, let us

...read more >>

]]>Recently, I was talking with MathWorks writer Jessica Bernier about the reference page for the imresize function. Jessica pointed out that we don't have an example that shows how to use your own... read more >>

]]>Recently, I was talking with MathWorks writer Jessica Bernier about the reference page for the imresize function. Jessica pointed out that we don't have an example that shows how to use your own interpolation kernel. In today's post, I'll compare the supported interpolation kernels on a sample image, and then I'll show you how to use your own kernel.The different methods supported by imresize, including 'bilinear', 'bicubic', 'lanczos2', and 'lanczos3', correspond to using different interpolation kernels, also known as interpolants. The bilinear method uses a triangular interpolation kernel, which is defined as:f(x)={1-|x||x|≤10otherwisefplot(@triangle,[-3.5 3.5])(The function triangle, as well as the other interpolation kernel functions used in this post, are at the end.)The bicubic method uses this piecewise cubic interpolation

...read more >>

]]>I have published more than 560 blog posts here since 2006, and I estimate that about 98% of them started out as MATLAB scripts.Recently, I've started writing my blog posts as live scripts. Live... read more >>

]]>I have published more than 560 blog posts here since 2006, and I estimate that about 98% of them started out as MATLAB scripts.Recently, I've started writing my blog posts as live scripts. Live scripts contain not only MATLAB code, but also code output, graphics output, and formatted text, including equations. It's a really nice way to share a technical story.Now, thanks to my friends on the MATLAB Central development team, I can write a blog post as a live script -- and then you can run the code yourself in your web browser!Let me show you how it works. Here is my blog post on using a custom interpolation kernel with imresize:Now scroll all the down to the bottom of the post (above the comments):Click on the "Run in your browser" button, and you'll get your own MATLAB Online session

...read more >>

]]>Today's blog post comes from planning one topic, but then taking a sharp left turn and doing something else completely. I was thinking about writing something related to meshgrid, and so I was... read more >>

]]>Today's blog post comes from planning one topic, but then taking a sharp left turn and doing something else completely. I was thinking about writing something related to meshgrid, and so I was looking at some old blog posts in which meshgrid was used. For example, meshgrid was used in this 30-Dec-2010 post about the a* and b* component in the Lab color space.In reading over that old post, however, I realized that I made a rather egregious conceptual error in it. I plotted colors over the domain $ -100 \leq a^* \leq 100 $, $ -100 \leq b^* \leq 100 $, using $ L^* = 90 $, without realizing or explaining that most of those $ (L^*,a^*,b^*) $ combinations are far out of the sRGB gamut. In other words, they are not really displayable (even on a wide-gamut monitor). Also, the functions I used back then have since been superseded by new functions that are not only easier to use, but are also more helpful at looking at

...read more >>

]]>A MATLAB user recently contacted MathWorks tech support to ask why the output of fft did not meet their expectations, and tech support asked the MATLAB Math Team for assistance. Fellow Georgia Tech... read more >>

]]>A MATLAB user recently contacted MathWorks tech support to ask why the output of fft did not meet their expectations, and tech support asked the MATLAB Math Team for assistance. Fellow Georgia Tech graduate Chris Turnes wrote a detailed response that I enjoyed reading. I thought it would be worth adapting the case for a blog post. Although the case is about the 1-D FFT, the underlying issues show up in image processing, too, and I have written about them in the past. (See my Fourier transform category.)Let's set up the case by starting with a sine wave at 50 Hz, sampled at 1 kHz, with 4080 samples.Fs = 1000;N = 4080;t = (0:(N-1))/Fs;y = sin(2*pi*50*t);plot(t,y)axis([0 0.1 -1.2 1.2])xlabel('t (sec)')ylabel('y(t)')grid ontitle('The first 0.1 seconds of y(t)')Next, let's compute and display the FFT, scaling the frequency axis so that it is in Hz, and scaling the magnitude by the square root of the FFT length.Y

...read more >>

]]>