I have an image. I want to resize it to double the original size, filling in the new pixels by interpolation. I need to specify which type of interpolation I want to use.
I see the imresize function, which has an option for 'method'. The problem is, there are only 3 options: nearest, bilinear, bicubic. Bilinear and bicubic are averaging/mean methods, but is there any way to set the neighborhood size / weighting?
The main problem is, I need to do it with a 'median' interpolation method, instead of mean. How can I tell it to use this method?
The way that IMRESIZE implements interpolation is by calculating for each pixel in the output image (inverse mapping), the indices of the pixels in the input image that are going to be involved in the interpolation, along with the contributing weights.
The neighborhood and the weights are determined by the type of the interpolation kernel used, which as #Albert points out, can be passed along to the IMRESIZE function (the 'Method' property can accept {f,w} a cell array with the kernel function and the kernel width)
These two components will be used to compute linear combination of the input pixels involved to fill each value of the output pixels. This process is performed along each dimension separately one-at-a-time (vertically then horizontally).
Now the problem for you is that you can never obtain the median value by using a linear combination, that's because median is a non-linear ordering filter. So your only option is to write your own implementation...
Amro is right that the median filter cannot be computed as a weighted response. But MATLAB has a specific function for the median filter: medfilt2.
imresize has a third way of passing the interpolation method: "Two-element Cell Array Specifying Interpolation Kernel". You can read more about it in Matlab's documentation.
Related
I have a 3d matrix A=[mXnXl], which I want to inpaint, using a mask of mask=[mXn].
So each slice along the "l" is a 2D image (0-255 RGB range). I care about continuity along that axis as also along the 3rd dimenbtison.
I use the inpainting with the two following forms
im1=inpaint.inpaint_biharmonic(np.uint8(A), np.uint8(mask), multichannel=True)
for i in range(0,l):
im2[:,:,i]=inpaint.inpaint_biharmonic(np.uint8(A[:,:,i]), np.uint8(mask), multichannel=False)
How is the 3rd dimension handled in the algorithm? Will they produce the same results?
You can look at the source code of the function here:
https://github.com/scikit-image/scikit-image/blob/c221d982e493a1e39881feb5510bd26659a89a3f/skimage/restoration/inpaint.py#L76
As you can see in the for-loop in that function, the function is just doing the same thing as your for-loop, so the results should be identical.
I am now working on the interpolation of gray value for an image. I wanna use the matlab function griddedInterpolant. For the interpolation method it has 'cubic' and 'spline'. Both of them are C2 continues. I have found the algorithm about 'cubic' (actually 'bicubic' since my data are 2D) as listed in WiKipedia:
https://en.wikipedia.org/wiki/Bicubic_interpolation.
I wanna ask if some one know the algorithm behind 'spline' (actually 'bicubic spline' for 2D). Because I don't quite understand the difference between them.
And for my calculation I need the gradient of the gray value too. Since in function griddedInterpolant it is not possible to get the coefficients of the interpolation, there's no way to calculate the gradients directly.
Can someone help me with that?
I am currently doing some seismic modelling and processing in MATLAB, and would like to come up with an easy way of muting parts of various datasets. If I plot the frequency-wavenumber spectrum of some of my data, for instance, I obtain the following result:
Now, say that I want to mute some of the data present here. I could of course attempt to run through the entire matrix represented here and specify a threshold value where everything above said value should be set equal to zero, but this will be very difficult and time-consuming when I later will work with more complicated fk-spectra. I recently learned that MATLAB has an inbuilt function called impoly which allows me to interactively draw a polygon in plots. So say I, for instance, draw the following polygon in my plot with the impoly-function:
Is there anything I can do now to set all points within this polygon equal to zero? After defining the polygon as illustrated above I haven't found out how to proceed in order to mute the information contained in the polygon, so if anybody can give me some help here, then i would greatly appreciate it!
Yes, you can use the createMask function that's part of the impoly interface once you delineate the polygon in your figure. Once you use create this mask, you can use the mask to index into your data and set the right regions to zero.
Here's a quick example using the pout.tif image in MATLAB:
im = imread('pout.tif');
figure; imshow(im);
h = impoly;
I get this figure and I draw a polygon inside this image:
Now, use the createMask function with the handle to the impoly call to create a binary mask that encapsulates this polygon:
mask = createMask(h);
I get this mask:
imshow(mask);
You can then use this mask to index into your data and set the right regions to 0. First make a copy of the original data then set the data accordingly.
im_zero = im;
im_zero(mask) = 0;
I now get this:
imshow(im_zero);
Note that this only applies to single channel (2D) data. If you want to apply this to multi-channel (3D) data, then perhaps a multiplication channel-wise with the opposite of the mask may be prudent.
Something like this:
im_zero = bsxfun(#times, im, cast(~mask, class(im)));
The above code takes the opposite of the polygon mask, converts it into the same class as the original input im, then performs an element-wise multiplication of this mask with each channel of the input separately. The result will zero each spatial location that's defined in the mask over all channels.
I have some data set where each object has a Value and Price. I want to apply Gaussian Blur to their Price using their Value. Since my data has only 1 component to use in blurring, I am trying to apply 1D Gaussian blur.
My code does this:
totalPrice = 0;
totalValue = 0;
for each object.OtherObjectsWithinPriceRange()
totalPrice += price;
totalValue += Math.Exp(-value*value);
price = totalPrice/totalValue;
I see good results, but the 1D Gaussian blur algorithms I see online seems to use deviations, sigma, PI, etc. Do I need them, or are they strictly for 2D Gaussian blurs? They combine these 1D blur passes as vertical and horizontal so they are still accounting for 2D.
Also I display the results as colors but the white areas are a little over 1 (white). How can I normalize this? Should I just clamp the values to 1? That's why I am wondering if I am using the correct formula.
Your code applies some sort of a blur, though definitely not Gaussian. The Gaussian blur would look something like
kindaSigma = 1;
priceBlurred = object.price;
for each object.OtherObjectsWithinPriceRange()
priceBlurred += price*Math.Exp(-value*value/kindaSigma/kindaSigma);
and that only assuming that value is proportional to a "distance" between the object and other objects within price range, whatever this "distance" in your application means.
To your questions.
2D Gaussian blur is completely equivalent to a combination of vertical and horizontal 1D Gaussian blurs done one ofter another. That's how thee 2D Gaussian blur is usually implemented in practice.
You don't need any PI or sigmas as a multiplicative factor for the Gaussian - those have an effect of merely scaling an image and can be safely ignored.
The sigma (standard deviation) under the exponent has a major impact on the result, but it is not possible for me to tell you if you need it or not. It depends on your application.
Want more blur: use larger kindaSigma in the snippet above.
Want less blur: use smaller kindaSigma.
When kindaSigma is too small, you won't notice any blur at all. When kindaSigma is too large, the Gaussian blur effectively transforms itself into a moving average filter.
Play with it and choose what you need.
I am not sure I understand your normalization question. In image processing it is common to store each color component (R,G,B) as unsigned char. So black color is represented by (0,0,0) and white color by (255,255,255). Of course, you are free to decided to choose a different presentation form and take white color as 1. But keep in mind that for the visualization packages that are using standard 8-bit presentation, the value of 1 means almost black color. So you will likely need to manipulate and renormalize your image before display.
I have an image and two points,
and I want to read the pixels between these two points,
and resample them into a small 1x40 array.
I'm using EMGU which is a C# wrapper for OpenCV.
thanks,
SW
What you are looking for is Bresenham's line algorithm. It will allow you to get the points in the pixel array that best approximate a straight line. The Wikipedia link also contains psuedo code to get you started.
Emgu CV includes method in the Image class for sampling color along a line called Sample.
Refer to the manual for the definition. Here's the link to Image.Sample in version 2.3.0.
You will still have to re-sample/interpolate the points in array returned from Sample to end up with a 40 element array. Since there are a number of ways to re-sample, I'll suggest you look to other questions for that.
Rotate and crop
I'd first try to do it like this:
calculate rotation matrix with (GetRotationMatrix2D)
warp the image so that this line is horisontal (WarpAffine)
calculate new positions of two of your points (you can use Transform)
get image rectangle of suitable width and 1 px high (GetRectSubPix)
Interpolation here and there may affect the results, but you have to interpolate anyway. You may consider cropping the image before rotation.
Iterate over the 8-connected pixels of the line
Otherwise you may use the line iterator to iterate over the pixels between two points. See documentation for InitLineIterator (Sorry, the link is to the Python version of OpenCV, I've never heard of EMGU). I suppose that in this case you iterate over pixels of a line which was not antialiased. But this should be much faster.
Interpolate manually
Finally, you may convert the image to an array, calculate which elements the line is passing through and subsample and interpolate manually.