I want to remove noise from an image. The image i've been given is a .mat file but it's very complicated because when i load the mat file no image can be seen, then i use imwrite to make it jpg
imwrite(destroyedImg, 'fr.jpg');
But when i use imshow I get only colorful dots in white background!
Is there a way to find out how to clear the noise from this picture?!
I'm not allowed to use the internal functions but to build one myself! But i cannot figure out the kind of noise and then remove it! i also have to return the "clear image" in RGB format and not grayscale!
here is some of my code
clear all; close all;
load('image_destroyed.mat');
imwrite(image_destroyed, 'fraou.jpg');
img = imread('fraou.jpg');
subplot(2,2,1), imshow(img)
title('Fraou');
H = fspecial('average',[3 3]);
average = imfilter(img, H, 'replicate');
subplot(2,2,2), imshow(average);
title('average');H = fspecial('gaussian',[5 5]);
average = imfilter(img, H, 'replicate');
subplot(2,2,3); imshow(average);title('gaussian');
H = wiener2(img,[5 5]);
subplot(2,2,4); imshow(H)
title('wiener 5x5');
DO NOT USE imwrite to 'jpg' to get your image - this only introduces artifacts.
Your input image is of type double with values exceeding the range [0..1] and thus all the confusion.
load('image_destroyed.mat');
image_destroyed = image_destroyed / 255.0; % back to [0..1] range
imshow( image_destroyed ); % should be meaningful now.
The following code, presuming that image_destroyed is a variable contained in image_destroyed.mat, is probably what is causing the issue:
load('image_destroyed.mat');
imwrite(image_destroyed, 'fraou.jpg');
img = imread('fraou.jpg');
At best this is equivalent to img = image_destroyed;, and therefore is unnecessary. It is possible (and given your strange results, quite likely) that this write/read process is actually introducing further degradation into your image, through inappropriate scaling or clipping, compression, etc.
For MATLAB image processing functions, when using doubles, you should make sure your data is scaled between 0 and 1.
Related
I am expecting the following output,
But, getting the following output
I.e. the displayed images' have incorrect aspect ratio.
What is the reason and How can I fix this?
Source Code
main.m
clear_all();
image_name = 'woman.png';
I = gray_imread(image_name);
K = {I, I, I, I, ...
I, I, I, I, ...
I, I, I, I};
draw_cell(K);
draw_cell.m
function draw_cell(image_list)
if(iscell(image_list))
figure;
hold all
colormap(gray(256));
N = length(image_list);
[m, n] = factor_out(N);
display('cell');
for k=1:N
h = subplot(m,n,k);
image(image_list{k},'parent',h);
set(gca,'xtick',[],'ytick',[])
end
hold off
else
error('''image_list'' is not a cell array');
end
function [m, n] = factor_out(input_number)
sqrtt = ceil(sqrt(input_number));
m = sqrtt;
n = sqrtt;
Two possible options for maintaining aspect ratio of images
axis equal or axis image
For most plotting functions, you can use the axis equal command to set the same scale on the x and y axes. While plotting images, this is equivalent to maintaining the aspect ratio. You need to call this command for every subplot, so I would suggest using it immediately after the subplot command.
For plotting images specifically, the axis equal command will leave white space around the image. axis image will maintain aspect ratio and remove white space.
imshow instead of image
If you have the Image Processing Toolbox, you can substitute the imshow function for the image function. imshow makes the assumption that you want to display an image and restricts both the colormap and the aspect ratios accordingly. Despite its name image is designed to visualize any matrix data, not just images. Therefore, it scales pixels to fully utilize screen real estate. You'll run into the same problem if you use imagesc along with the additional problem of color scaling. To be on the safe side, always use imshow when displaying RGB and grayscale images unless you have an explicit reason not to.
Introduction
Background: I am segmenting images using the watershed algorithm in MATLAB. For memory and time constraints, I prefer to perform this segmentation on subsampled images, let's say with a resize factor of 0.45.
The problem: I can't properly re-scale the output of the segmentation to the original image scale, both for visualization purposes and other post processing steps.
Minimal Working Example
For example, I have this image:
I run this minimal script and I get a watershed segmentation output L that consists in a label image, where each connected component is addressed with a natural number and the borders between the connected components are zero-valued:
im_orig = imread('kitty.jpg'); % Load image [530x530]
im_res = imresize(im_orig, 0.45); % Resize image [239x239]
im_res = rgb2gray(im_res); % Convert to grayscale
im_blur = imgaussfilt(im_res, 5); % Gaussian filtering
L = watershed(im_blur); % Watershed aglorithm
Now I have L that has the same dimension of im_res. How can I use the result stored in L to actually segment the original im_orig image?
Wrong solution
The first approach I tried was to resize L to the original scale by using imresize.
L_big = imresize(L, [size(im_orig,1), size(im_orig,2)]); % Upsample L
Unfortunately the upsampling of L produces a series of unwanted artifacts. It especially loses some of the fundamental zeros that represent the boundaries between the image segments. Here is what I mean:
figure; imagesc(imfuse(im_res, L == 0)); axis auto equal;
figure; imagesc(imfuse(im_orig, L_big == 0)); axis auto equal;
I know that this is due to the blurring caused by the upscaling process, but for now I couldn't think about anything else that could succeed.
The only other approach I thought about involve the use of Mathematical Morphology to "enlarge" the boundaries of the resized image and then upsample, but this would still lead to some unwanted artifacts.
TL;DR (or recap)
Is there a way to perform watershed on a downscaled image in MATLAB and then upscale the result to the original image, keeping the crisp region boundaries outputted by the algorithm? Is what I am looking for a completely absurd thing to ask?
If you only need the watershed segment borders after upsizing the image, then just make these little changes:
L_big = ~imresize(L==0, [size(im_orig,1), size(im_orig,2)]); % Upsample L
and here the results:
you can use nearest neighbor interpolation when resizing:
L_big = imresize(L, [size(im_orig,1), size(im_orig,2)],'nearest'); % Upsample L
Normally when we resize images we star fro the destination, iterate over x, y, and find the best matching pixel in the source. Here you want to do the reverse. Iterate over the source in x, y and write to the destination buffer, with 0 taking priority (so initialise to 0xFF, then don't overwrite any zeroes with other values),
There's unlikely to be a function that does this on the toolkit, you;ll hav e to roll your own.
I am trying to save a figure in Matlab R2014a in which I want to plot data over an Image. This is the code:
[Singapore, R] = geotiffread(file);
s = size(Singapore);
matrix = rand(s(1),s(2));
geoshow(Singapore(:,:,1:3), R)
hold on
geoshow(matrix, R, 'DisplayType', 'texturemap','facealpha',.2);
xlim([103.605,104.04])
ylim([1.2,1.475])
This one is the plot that works perfectly:
While when I am printing the figure
print(gcf, '-dpng', fullfile(FileF, 'test.png'))
the image is completely white
Many thanks for the image link!
I have tried your code (adapted for the `Singapore.tif' file you provided and an appropriate output file) and it works as expected on my system (Matlab 2013b, Linux 64-bit). This is the output file:
So I'm sorry to say that there's nothing wrong with your code, and it's probably something to do with the 'png' driver on windows or your particular installation. Have you tried printing to a different driver? (e.g. jpg or pdf?). Does it actually work if you do this from the figure's graphical menu, i.e. File->Save As; or via File->Export Setup->Export with appropriate properties?
The only other thing I can think of which may be confusing your system is the attempt to print a uint8 rgb image (your Singapore image) and an overlayed double grayscale image. You can see if converting your Singapore image to double solves this by changing:
geoshow(Singapore(:,:,1:3), R)
to
geoshow(mat2gray(Singapore(:,:,1:3)), R)
Might also be worth trying to plot the data manually and see if printing that works, e.g.:
[Singapore, R] = geotiffread('Singapore.tif');
SingaporeXYImage = cat(3, flipud(Singapore(:,:,1)), ...
flipud(Singapore(:,:,2)), ...
flipud(Singapore(:,:,3)));
s = size(Singapore);
matrix3D = repmat( rand(s(1),s(2)), [1,1,3]);
imagesc(R.LongitudeLimits, R.LatitudeLimits, mat2gray(SingaporeXYImage));
hold on;
imagesc(R.LongitudeLimits, R.LatitudeLimits, matrix3D, 'alphadata', .2);
hold off;
axis xy equal tight;
xlim([103.605,104.04])
ylim([1.2,1.475])
print(gcf, '-dpng', 'test.png');
As a bonus, here's how you might perform the same thing in Octave, in case you're interested (I find printed plots from Octave look much nicer, especially in terms of fonts!):
pkg load mapping;
pkg load image;
[SingaporeStruct, R] = rasterread('Singapore.tif');
SingaporeImage = cat(3, SingaporeStruct(1:3).data); % note this is a matrix of
% "doubles" in range [0,255]
SingaporeImage = mat2gray(SingaporeImage); % Convert to appropriate [0,1] range
% for "doubles" rgb images!
s = size (SingaporeImage);
matrix3D = repmat (rand (s(1), s(2)), [1, 1, 3]);
imagesc (R.bbox(:,1), R.bbox(:,2), ...
SingaporeImage .* 0.8 + matrix3D .* 0.2); % manually create
% transparency effect
axis xy equal tight
xlim([103.605,104.04])
ylim([1.2,1.475])
print (gcf, '-dpng', 'test.png');
Also, no disrespect to my colleague and the effort he / she put into his / her answer, but I will note that the other answer you received is essentially completely wrong and you should retract your marked accepted regardless of his / her claim and warnings about how rude it is to retract a marked answer. mapshow is specifically used for images using a MapCellsReference format: the boston.tif image is one such image. Your image however uses a GeographicCellsReference format. mapshow is used for the former, geoshow is used for the latter; geoshow would have failed for boston.tif, in the same way mapshow fails for Singapore.tif. It should have been obvious your image is a "Geo" variant because your line geoshow(Singapore(:,:,1:3), R) worked without throwing an error. Therefore the suggestion to use mapshow is not the correct answer to your question, and is misleading. Not to mention it is completely irrelevant to your actual question about why the print command does not produce the expected result from its figure handle, which should in theory have nothing to do with how the figure was produced in the first place. I would have no qualms about retracting your "accepted" mark from it. Not least because this site functions as a reference for many other viewers; it does not make sense to direct users to the wrong answer just because you got bullied into accepting it.
As suggested by mathworks, using mapshow should solve your problem. The following works for me:
[boston, R] = geotiffread('boston.tif');
figure
mapshow(boston, R);
axis image off
S = size(boston);
matrix=rand(S(1),S(2));
hold on
mapshow(matrix, R,'DisplayType','texturemap','facealpha',0.2);
print(gcf, '-dpng','test.png') ;
Here is the original image with better vision: we can see a lot of noise around the main skeleton, the circle thing, which I want to remove them, and do not affect the main skeleton. I'm not sure if it called noise
I'm doing it to deblurring a image, and this image is the motion blur kernel which identify the camera motion when the camera capture a image.
ps: this image is the kernel for one case, and what I need is a general method in here. thank you for your help
there is a paper in CVPR2014 named "Separable Kernel for Image Deblurring" which talk about this, I want to extract main skeleton of the image to make the kernel more robust, sorry for the explaination here as my English is not good
and here is the ture grayscale image:
I want it to be like this:
How can I do it using Matlab?
here are some other kernel images:
As #rayryeng well explained, median filtering is the best option to clean noise in the image, which I realized when I had studied about image restoration. However, in your case, what you need to do seems to me not cleaning noise in the image. You want to more likely eliminate the sparks in the image.
Simply I applied single thresholding to your noisy image to eliminate sparks.
Try this:
desIm = imread('http://i.stack.imgur.com/jyYUx.png'); % // Your expected (desired) image
nIm = imread('http://i.stack.imgur.com/pXO0p.png'); % // Your original image
nImgray = rgb2gray(nIm);
T = graythresh(nImgray)*255; % // Thereshold value
S = size(nImgray);
R = zeros(S) + 5; % // Your expected image bluish so I try to close it
G = zeros(S) + 3; % // Your expected image bluish so I try to close it
B = zeros(S) + 20; % // Your expected image bluish so I try to close it
logInd = nImgray > T; % // Logical index of pixel exclude spark component
R(logInd) = nImgray(logInd); % // Get original pixels without sparks
G(logInd) = nImgray(logInd); % // Get original pixels without sparks
B(logInd) = nImgray(logInd); % // Get original pixels without sparks
rgbImage = cat(3, R, G, B); % // Concatenating Red Green Blue channels
figure,
subplot(1, 3, 1)
imshow(nIm); title('Original Image');
subplot(1, 3, 2)
imshow(desIm); title('Desired Image');
subplot(1, 3, 3)
imshow(uint8(rgbImage)); title('Restoration Result');
What I got is:
The only thing I can see that is different between the two images is that there is some quantization noise / error around the perimeter of the object. This resembles salt and pepper noise and the best way to remove that noise is to use median filtering. The median filter basically analyzes local overlapping pixel neighbourhoods in your image, sorts the intensities and chooses the median value as the output for each pixel neighbourhood. Salt and pepper noise corrupts image pixels by randomly selecting pixels and setting their intensities to either black (pepper) or white (salt). By employing the median filter, sorting the intensities puts these noisy pixels at the lower and higher ends and by choosing the median, you would get the best intensity that could have possibly been there.
To do median filtering in MATLAB, use the medfilt2 function. This is assuming you have the Image Processing Toolbox installed. If you don't, then what I am proposing won't work. Assuming that you do have it, you would call it in the following way:
out = medfilt2(im, [M N]);
im would be the image loaded in imread and M and N are the rows and columns of the size of the pixel neighbourhood you want to analyze. By choosing a 7 x 7 pixel neighbourhood (i.e. M = N = 7), and reading your image directly from StackOverflow, this is the result I get:
Compare this image with your original one:
If you also look at your desired output, this more or less mimics what you want.
Also, the code I used was the following... only three lines!
im = rgb2gray(imread('http://i.stack.imgur.com/pXO0p.png'));
out = medfilt2(im, [7 7]);
imshow(out);
The first line I had to convert your image into grayscale because the original image was in fact RGB. I had to use rgb2gray to do that. The second line performs median filtering on your image with a 7 x 7 neighbourhood and the final line shows the image in a separate window with imshow.
Want to implement median filtering yourself?
If you want to get an idea of how to actually write a median filtering algorithm yourself, check out my recent post here. A question poser asked to implement the filtering mechanism without using medfilt2, and I provided an answer.
Matlab Median Filter Code
Hope this helps.
Good luck!
How do I avoid a jagged image in MATLAB?
I have a 600 x 600 pixels image opened in MATLAB and do some processing on the image. However, when I save it, it looks so blurred and jagged. What should I do?
(This question is related to my previous question, MATLAB - How to plot x,y on an image and save?)
fid = fopen(datafile.txt);
A = textscan(fid,'%f%f%f'); %read data from the file
code = A{1};
xfix = A{2};
yfix = A{3};
for k=1:length(code)
imagefile=code(k);
rgb = imread([num2str(imagefile) '.jpg']);
imshow(rgb);
hold on;
x = xfix2(k);
y = yfix2(k);
plot(x,y,'-+ b'); % plot x,y on the
saveas(([num2str(imagefile) '.jpg'])) % Save the image with the same name as it open.
end
hold off
If it is just a resolution issue, perhaps using the print command (as listed below) with an explicit resolution option may fix it.
print(gcf,'-djpeg','-r600',[num2str(imagefile)])
My guess would be JPEG compression artifacts. JPEG isn't a great format for data with a lot of high frequency components. Have you tried turning the compression down? Like so:
imwrite(f.cdata,([num2str(imagefile) '.jpg']),'Quality',100);
The default for the quality parameter is only 75. That's plenty for a lot of cases, but you might need more.