MATLAB Plot contrast enhancement? - matlab

I have a plot that needs to be contrast enhanced before another plot is superimposed over it.
figure
plot(something);
** contrast enhancement **
hold on
plot(something_else);
hold off
Is there a way to do this in the ** contrast enhancement ** line above? I have looked into imadjust function but it takes direct image input (tif/jpeg etc.).
Thank you.
Edit: Example code -
figure
plot(ebsd,ebsd.prop.bc);
mtexColorMap black2white
** contrast enhancement **
hold on
plot(ebsd('Forsterite'),ebsd('Forsterite').orientations.angle./degree);
hold off

Grab the image from the axes (if it is an image!)
im=getimage(rgb2gary(gca)); %it should already be gray, but matlab returns RGB anyway
and automatically adjust the contrast
im2=imadjust(im);
Set it again
imshow(im2,'Parent',gca); % or whatever other method you are using for display.

Of what I see in the example, you want area with saturated colors on a background of "faint", milky colors. Try this solution of highlight by increased saturation.
rgb = imread('peppers.png');
% make under-saturated image
hsv = rgb2hsv(rgb);
hsv(:, :, 2) = hsv(:, :, 2)*0.2;
hsv(hsv > 1) = 1; % Limit values
rgbFaint = uint8(255*hsv2rgb(hsv));
% make a mask of area to highlight
mask = false(size(rgb,1),size(rgb,2));
h = fspecial('disk',60) > 0;
mask(200:200+size(h,1)-1,200:200+size(h,2)-1) = h;
mask = repmat(mask,1,1,3);
% create image with highlight area
rgbHighlight = rgbFaint;
rgbHighlight(mask) = rgb(mask);
figure;
imshow(rgbHighlight)

Related

How to prevent inaccurate segmentation of enclosed background regions in Watershed Algorithm?

I'm using the watershed algorithm to segment bright spots on a dark background. The code is provided below, along with some images it generates.
In the second image, I've marked with red crosses the areas of enclosed background which are segmented as 'cells' (they're not biological cells, just using the word) - this is incorrect, they're part of the background, just enclosed by 'cells'. I see that this creates a false minimum, any help on how to prevent this?
% Improve contrast, binarize
RFP_adjust = imadjust(RFP_blur, stretchlim(RFP_blur, 0.001));
figure, imshow(RFP_adjust), title('Contrast adjust');
RFP_binarized = imbinarize(RFP_adjust);
RFP_perimeters = bwperim(RFP_binarized);
% figure, imshow(RFP_binarized), title('Otsu thresholding');
%2B - SEGMENTATION BY WATERSHED METHOD
% Discover putative cell centroids and process
RFP_maxs = imextendedmax(RFP_adjust, 3000);
RFP_maxs = imclose(RFP_maxs, strel('disk',5));
RFP_maxs = imfill(RFP_maxs, 'holes');
RFP_maxs = bwareaopen(RFP_maxs, 5);
RFP_max_overlay = imoverlay(RFP_adjust, RFP_perimeters | RFP_maxs, [1 .3 .3]);
figure, imshow(RFP_max_overlay), title('Maxima');
% Obtain complement - maxima become low-points (required for watershed)
RFP_comp = imcomplement(RFP_adjust);
RFP_imposemin = imimposemin(RFP_comp, ~RFP_binarized | RFP_maxs);
figure, imshow(RFP_imposemin), title('Inverted Maxima');
% Apply watershed
RFP_watershed = watershed(RFP_imposemin);
mask = im2bw(RFP_watershed, 1);
overlay3 = imoverlay(RFP_adjust, mask, [1 .3 .3]);
figure, imshow(overlay3), title('Segmented cells');
% Segment
RFP_cc = bwconncomp(RFP_watershed);
RFP_label_matrix = labelmatrix(RFP_cc);
whos labeled;
RFP_label = label2rgb(RFP_label_matrix, #spring, 'c', 'shuffle');
figure, imshow(RFP_label), title('Cells segmented');
Image 0 - result for image titled 'Maxima' (i.e. adjusted original image with maxima and outlines overlaid).
Image 1 - the result for image titled 'inverted maxima'
Image 2 - the result for image titled 'Cells segmented'
I would suggest something like what is done in the example included for the watershed function: use the background mask to set those pixels to Inf, perform the watershed operation, then set the background pixels in the result to 0. I believe you could change the watershed section of your code like so to achieve this:
% Apply watershed
RFP_watershed = RFP_imposemin; % Added
RFP_watershed(~RFP_binarized) = Inf; % Added
RFP_watershed = watershed(RFP_watershed); % Modified
RFP_watershed(~RFP_binarized) = 0; % Added
mask = im2bw(RFP_watershed, 1);
overlay3 = imoverlay(RFP_adjust, mask, [1 .3 .3]);
figure, imshow(overlay3), title('Segmented cells');
There no magic bullet, but a few things you can try.
One is to filter the image with a very large circular disc, creating a blurry image that looks like the background. Then subtract it from the original image. That will tend to force the actual background to zero.
Another is to Otsu threshold to separate foreground from background. That creates a binary image. Then do a morphological open operation using a mask designed to look like the actual cells.

Extracting Feature from an Image - suggestions for best approach?

I am currently learning computer vision and I would like to extract the onion from the image. What would be the best approach to do this?
I attempted a thresholding approach to detect white colour by breaking down the image into its R,G,B channels, but that also detects light reflections on other parts of the image. How could I clean up this image to obtain a mask that approximately represents the onion?
onionRGB = imread('onion.png');
onionGRAY = rgb2gray(onionRGB);
figure, imshow(onionRGB);
% split channels
rOnion = onionRGB(:, :, 1); % red channel
gOnion = onionRGB(:, :, 2); % green channel
bOnion = onionRGB(:, :, 3); % blue channel
whiteThresh = 160*3;
% detect white onion
onionDetection = double(rOnion) + double(gOnion) + double(bOnion);
% apply thresholding to segment the foreground
maskOnion = onionDetection > whiteThresh;
figure, imshow(maskOnion);
The following code, placed after splitting into channels, works well.
onionHSV = rgb2hsv(onionRGB);
saturationOnion = onionHSV(:,:,2);
figure;
imagesc(saturationOnion);
title('Saturation');
figure;
imagesc(rOnion+bOnion); title('purple');
%apply threshold to saturation and purple brightness levels
maskOnion = and((saturationOnion < 0.645), (rOnion+bOnion >=155));
%filter out all but the largest object
maskOnion = bwareafilt(maskOnion,1);
figure, imshow(maskOnion);
The first trick is using saturation from the HSV representation of the colors for filtering purposes.
The second trick is thresholding on more than one channel.
The third trick is filtering out all but the largest object.

Removing background and measuring features of an image in MATLAB

I'm trying to measure the areas of each particle shown in this image:
I managed to get the general shape of each particle using MSER shown here:
but I'm having trouble removing the background. I tried using MATLAB's imfill, but it doesn't fill all the particles because some are cut off at the edges. Any tips on how to get rid of the background or find the areas of the particles some other way?
Cheers.
Edit: This is what imfill looks like:
Edit 2: Here is the code used to get the outline. I used this for the MSER.
%Compute region seeds and elliptial frames.
%MinDiversity = how similar to its parent MSER the region is
%MaxVariation = stability of the region
%BrightOnDark is used as the void is primarily dark. It also prevents dark
%patches in the void being detected.
[r,f] = vl_mser(I,'MinDiversity',0.7,...
'MaxVariation',0.2,...
'Delta',10,...
'BrightOnDark',1,'DarkOnBright',0) ;
%Plot region frames, but not used right now
%f = vl_ertr(f) ;
%vl_plotframe(f) ;
%Plot MSERs
M = zeros(size(I)) ; %M = no of overlapping extremal regions
for x=r'
s = vl_erfill(I,x) ;
M(s) = M(s) + 1;
end
%Display region boundaries
figure(1) ;
clf ; imagesc(I) ; hold on ; axis equal off; colormap gray ;
%Create contour plot using the values
%0:max(M(:))+.5 is the no of contour levels. Only level 0 is needed so
%[0 0] is used.
[c,h]=contour(M,[0 0]) ;;
set(h,'color','r','linewidth',1) ;
%Retrieve the image data from the contour image
f = getframe;
I2 = f.cdata;
%Convert the image into binary; the red outlines are while while the rest
%is black.
I2 = all(bsxfun(#eq,I2,reshape([255 0 0],[1 1 3])),3);
I2 = imcrop(I2,[20 1 395 343]);
imshow(~I2);
Proposed solution / trick and code
It seems you can work with M here. One trick that you can employ here would be to pad zeros all across the boundaries of the image M and then fill its holes. This would take care of filling the blobs that were touching the boundaries before, as now there won't be any blob touching the boundaries because of the zeros padding.
Thus, after you have M, you can add this code -
%// Get a binary version of M
M_bw = im2bw(M);
%// Pad zeros all across the grayscale image
padlen = 2; %// length of zeros padding
M_pad = padarray(M_bw,[padlen padlen],0);
%// Fill the holes
M_pad_filled = imfill(M_pad,'holes');
%// Get the background mask after the holes are gone
background_mask = ~M_pad_filled(padlen+1:end-padlen,padlen+1:end-padlen);
%// Overlay the background mask on the original image to show that you have
%// a working background mask for use
I(background_mask) = 0;
figure,imshow(I)
Results
Input image -
Foreground mask (this would be ~background_mask) -
Output image -

Plot imellipse over image in MATLAB

I am trying to make a binary region of interest mask over an image stack (GUI). Here is what I have thus far:
% Initalize lesion mask
LesionMask = zeros(size(handles.ImageOne));
% Create an ellipse for roi analysis
Lesion = imellipse(handles.axes1);
% Save roi to 3D binary mask
LesionMask(:,:,handles.CurrentSlice) = Lesion.createMask();
boundary = bwboundaries(LesionMask(:,:,handles.CurrentSlice))
Now I would like to overlay the boundary over my image, in particular, I would like it to stay even when I go through my image stack.
In short, I would like to plot the edge of the ellipse over my image.
Thanks!
This might work for you when added to your code at the end -
hold on
for k = 1:numel(boundary)
plot(boundary{k}(:,2), boundary{k}(:,1), 'r', 'Linewidth', 3) %// Red border
end
Inspired from this blog
If you would like to keep the edge on the image saved for later usage, try this -
[M,N,C] = size(handles.ImageOne)
t1 = cell2mat(boundary);
ind1 = sub2ind([M N],t1(:,1),t1(:,2));
ind2 = bsxfun(#plus,ind1,[0:C-1].*(M*N));
handles.ImageOne(ind2)=0; %// Creates a black border

how to remove noise from a special area in Matlab

I have a an image of size 180x220 containing some noise in the region for example (145:180,1:65).
My question is how to remove the noise in this region without affecting the other parts of the image using Matlab.
Thank you very much.
Edit: I want to remove the noise in the regions (1:146,1:25) and (1:15,25,174) from the following image:
In general, this would go something like
% filter image in-place
img(145:180, 1:65) = medfilt2(img(145:180, 1:65));
Note that most filters require some context of the region of interest to do a proper interpolation/averaging/etc., so you might want to take this approach:
% Note: increase ROI by 10 on each side
offset = 10;
img_tmp = img(145-offset : 180+offset, 1 : 65+offset);
% apply filter
img_tmp = medfilt2(img_tmp, [additional parameters]);
% put filtered image back in its proper place
img(145:180, 1:65) = img_tmp(offset:end-offset+1, 1:end-offset+1);
img = double(imread('img.jpg'));
h = fspecial('gaussian', hsize, sigma); % decide how to filter the image
img_filt = imfilter(img, h, 'replicate');
now, use the filtered image only in the noise region
img(145:180,1:65,:) = img_filt(145:180,1:65,:);
Edit: After you posted the image I guess you want simply replace the noised region by the vanilla color?
If so, then do the following (assuming gray image):
med_pixel = median(img(:)); % detect the dominant color
img(1:146,1:25) = med_pixel;
img(1:15,25,174) = med_pixel;
... and so on