Decrease Target Contrast without losing image details - matlab

I have a original image (on the left) and I want to decrease object (horizontal shape thing) contrast to simulate the reference image (on the right). I have tried all smoothing methods but all of them will impact image contrast (say background contrast). Is there any way I can build a model then subtract it from the original image?
In another word, is there any way we can add opacity to the image on the left to simulate the image on the right? The object mask has been provided and it is the same size as original image.
Any suggestion will be appreciated.

You reduce the contrast by multiplying the masked area in the input image:
I = imread('https://i.stack.imgur.com/QML1p.png'); %I = imread('1.png'); %Read image
M = imbinarize(imread('https://i.stack.imgur.com/nBqeS.png')); %imbinarize(imread('2.png')); %Read mask, and convert to binary image.
J = I;
J(M) = J(M)*.5; %Multiply the "horizontal shape thing" by 0.5 - reducing contrast.
figure;imshow(J);
Result:
The above solution is kind of setting the opacity of the "shape thing".
I tried to make it a bit smoother, but result is still very different.
I = imread('https://i.stack.imgur.com/QML1p.png');
%I = imread('1.png'); %Read image
M = imbinarize(imread('https://i.stack.imgur.com/nBqeS.png'));
%M = imbinarize(imread('2.png')); %Read mask, and convert to binary image.
M = imdilate(M, strel('disk', 20)); %Make mask thicker.
%Crate blurred "shape thing"
T = zeros(size(I));
T(M) = double(I(M)); %"shape thing" with some margins, and black surrounding.
T = T/255; %Change pixels range from [0, 255] to [0, 1].
T = imgaussfilt(double(T), 5); %Blur (2-D Gaussian filtering).
%Create blurred mask:
M = imgaussfilt(double(M), 20); %Blur the mask (2-D Gaussian filtering).
M = max(M, 0.5);
J = T.*M + im2double(I).*(1-M); %Weighed average.
J = imgaussfilt(J, 1);
J = im2uint8(J);
figure;imshow(J);
Result:
Try to play with it a little...
Another try:
Reduce the relative contrast between "shape thing" and background by averaging J and 0.5
Add gaussian noise (so result be closer to reference).
Code:
I = imread('https://i.stack.imgur.com/QML1p.png');
M = imbinarize(imread('https://i.stack.imgur.com/nBqeS.png'));
M = imdilate(M, strel('disk', 20)); %Make mask thicker.
%Crate blurred "shape thing"
T = zeros(size(I));
T(M) = double(I(M)); %"shape thing" with some margins, and black surrounding.
T = T/255; %Change pixels range from [0, 255] to [0, 1].
T = imgaussfilt(double(T), 5); %Blur (2-D Gaussian filtering).
T = T*1.5; %Scale T for changing opaquely
%Create blurred mask:
M = imgaussfilt(double(M), 20); %Blur the mask (2-D Gaussian filtering).
M = max(M, 0.5);
J = T.*M + im2double(I).*(1-M); %Weighed average.
J = imgaussfilt(J, 1);
%Reduce the relative contrast between "shape thing" and background by averaging J and 0.5
J = (J + 0.5)/2;
J = min(J, 1);
%Add gaussian noise (so result be closer to reference).
J = imnoise(J, 'gaussian', 0, 0.005);
J = im2uint8(J);
figure;imshow(J);
Result:

Related

How can I detect the defect in this image of a semiconductor?

So I have this image of a semiconductor wafer and it has a defect in it which I need to detect using Matlab. I should detect only it and not its background. I need to also measure its perimeter and area.
So far I have this code where I convert the original image to a binary image and then use dilation on it and then try to get its contour. When getting the perimeter and the area, I receive the outcome not only for the defect but for the rest of the image which is not what I want. How can I extract the defect only so I can get only its area and parameter.
The image:
fig3 = imread('figure3.png');
imshow(fig3);
title('Original image', 'FontSize', 18);
%Gray image
fig3Gray = rgb2gray(fig3);
%Binary image
BW3 = imbinarize(fig3Gray,0.5);
imshow(BW3);
title('Binary image', 'FontSize', 18);
se3 = strel('square',5);
%Dilation image
dilated3 = imdilate(BW3,sr);
imshow(dilated3);
title('Dilated image', 'FontSize', 18);
minus3 = ~(BW3-dilated3);
imshow(minus3);
title('Contour image', 'FontSize', 18);
imshowpair(minus3,BW3,'montage');
%Perimeter and Area calculation
Coon3 = bwconncomp(~BW3)
ANS3 = length(Coon3.PixelIdxList{1});
OUTPUT3 = regionprops(Coon3,'Perimeter','Area');
P3 = OUTPUT3.Perimeter
Area3 = OUTPUT3.Area
Let's start by reading the image and converting it to binary. Note that I have lowered the threshold to eliminate unwanted details.
clear; close all; clc
fig3 = imread('XEQ59.png');
imshow(fig3);
title('Original image', 'FontSize', 18);
%Gray image
fig3Gray = rgb2gray(fig3);
%Binary image
BW3 = imbinarize(fig3Gray, 0.2); % lowered threshold
figure; imshow(BW3)
title('binary image')
Now we move on to find the coordinate of the defect. To do this, we define a structuring element that defines our desired shape se.
We are looking for the parts in the image that match with se. For a given coordinate to match, the surrounding area must exactly be se.
Note that gray values here are ignored, they can be either white or black.
se is manually defined where 1 represents white, -1 represents black, and 0 represents ignored pixels.
% hit-miss
se = [1, 1, -1*ones(1,5), ones(1, 3); ...
ones(6,1), -1*ones(6), zeros(6,2), ones(6,1); ...
ones(3,2), zeros(3,1), -1*ones(3,6), ones(3,1)];
figure; imshow(uint8(255/2*(se+1)), 'InitialMagnification', 3000)
title('structuring element')
Applying hit-miss operation to find the position of the defect:
pos = bwhitmiss(BW3, se);
figure; imshow(pos)
title('position of defect')
input('Press enter to continue...')
Now that we have the position, we grow that particular pixel position until it grows no more, in order to obtain defect.
% get the defect
close all; clc
def = pos;
last_def = zeros(size(def));
while ~isequal(def, last_def)
last_def = def;
def = ~BW3 & imdilate(def, ones(3));
imshow(def)
title('defect')
pause(0.1)
end
Calculating the area and the perimeter:
% area
area = sum(def(:))
% perimeter
vert = imdilate(def, [1; 1; 1]) - def;
horz = imdilate(def, [1 1 1]) - def;
perimeter = sum(vert(:)) + sum(horz(:))
area =
102
perimeter =
54
This question is much more difficult then your previous question.
Following solution uses an iterative approach (two iterations).
Includes heuristic about the difference from the cluster to it's neighbors.
Includes a heuristic that the cluster can't be too tall or too long.
Please read the comments:
clear
fig3 = imread('figure3.png');
fig3Gray = rgb2gray(fig3);
fig3Gray = im2double(fig3Gray); %Convert from uint8 to double (MATLAB math works in double).
%figure;imshow(fig3Gray);
%Apply median filter with large radius.
Med = medfilt2(fig3Gray, [51, 51], 'symmetric');
%figure;imshow(Med);
D = abs(fig3Gray - Med);
%figure;imshow(D);impixelinfo
BW = imbinarize(D, 0.3);
%figure;imshow(BW);impixelinfo
Coon = bwconncomp(BW);
fig3GrayMasked = fig3Gray;
%Cover the tall clusters and the long clusters.
for i = 1:length(Coon)
C = Coon.PixelIdxList{i}; %Cluster coordinates.
[Y, X] = ind2sub(size(fig3Gray), C); %Convert to x,y indices.
is_tall = (max(Y) - min(Y)) > 50; %true if cluster is tall.
is_wide = (max(X) - min(X)) > 50; %true if cluster is wide.
%Replace tall and long clusters by pixels from median image.
if ((is_tall) || (is_wide))
fig3GrayMasked(C) = Med(C);
end
end
%figure;imshow(fig3GrayMasked);impixelinfo
%Second iteration: search largest cluster on fig3GrayMasked image.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Med = medfilt2(fig3GrayMasked, [51, 51], 'symmetric');
D = abs(fig3GrayMasked - Med);
%figure;imshow(D);impixelinfo
BW = imbinarize(D, 0.3);
%figure;imshow(BW);impixelinfo
Coon = bwconncomp(BW);
%Find index of largest cluster in list of clusters Coon.PixelIdxList
[~, i] = max(cellfun(#numel, Coon.PixelIdxList));
%Get the indices of the largest cluster
C = Coon.PixelIdxList{i};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Paint cluster in yellow color (just for fun).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
BW = zeros(size(BW), 'logical');
BW(C) = 1;
Y = im2uint8(cat(3, ones(size(BW)), ones(size(BW)), zeros(size(BW))));
fig3(cat(3, BW, BW, BW)) = Y(cat(3, BW, BW, BW));
figure;imshow(fig3)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Result:

Resizing image increases noise?

I want to know that when we resize the image from 30x30 pixels image to 150x150 pixels image using Matlab. Does resizing adds extra noise in the image? Or vice versa case
Resize down may increase SNR (if for example, each destination pixel is sum of 2x2 source pixels). Resize up increases blur, but does not suppose to decrease the SNR.
You can make a simple test:
Load a "clean image", create noisy image by adding random Gaussian noise, and measure the SNR.
Example:
I = im2double(imread('cameraman.tif')); %I is the "clean" image.
J = imnoise(I); %Add noise
N = J - I; %Noise image
r = snr(I, N);
Result: r = 14.84
Resize down:
I2 = imresize(I, 0.5);
J2 = imresize(J, 0.5);
N2 = J2 - I2;
r2 = snr(I2, N2);
Result: r2 = 22.41 (SNR is improved by about factor of sqrt(2) - theoretical improvement).
Resize up:
I3 = imresize(I2, 2);
J3 = imresize(J2, 2);
N3 = J3 - I3;
r3 = snr(I3, N3);
Result: r3 = 23.66 (SNR is a about the same)

How to get mean and standard deviation of each channel (RGB) in an image

I am trying to output mean and standard deviation for each channel in the object located in the image. At the moment, my code produce mean and standard RGB as one figure, but instead, I would like to output mean and standard for R, G, B individualy.
Sample data: https://drive.google.com/file/d/0B_M7fjkKw1r3ZnM3N0I1aGkzbjA/edit?usp=sharing
This is my code:
function findspuds( image )
%findspuds function locates object boundaries and displays details in Command
%Windows
%read image
orginalImage = imread(image);
%convert to grayscale
grayImage = rgb2gray(orginalImage);
%convert to black/white with low threshold
blackWhiteImage = im2bw(grayImage,6/255);
%reverse binary values
reversedBlackWhiteImage = imcomplement(blackWhiteImage);
%compute distance transform to the nearest 0 pixel in the binary image
calReversedBlackWhiteImage = bwdist(reversedBlackWhiteImage);
%reverse back binary values
reversed2BlackWhiteImage = imcomplement(calReversedBlackWhiteImage);
%suppress pixel depth minimum
shallowImage = imhmin(reversed2BlackWhiteImage,10);
%compute a label matrix of watershed regions
waterImage = watershed(shallowImage);
%use watershed matrix to separate the touching objects in the binary image
blackWhiteImage(waterImage == 0) = 0;
%remove elements with fewer then 500 pixels
clnImage = bwareaopen(blackWhiteImage,500);
%remove holes in objects
filledImage = imfill(clnImage,'holes');
%get object boundaries
objectBoundries = bwboundaries(filledImage);
%label each object to get its measurements
labeledImage = bwlabel(filledImage);
%get all the object properties
objectMeasurements = regionprops(labeledImage, grayImage, 'all');
%align object labels in the centre of the object
labelShiftX = -7;
%display object boundaries on original image
imshow(orginalImage)
hold on
%print table header line in the command window
fprintf(1,'Object # Centroid Size Major/minor axis Circularity Mean/standard deviation\n');
%for each labelled object...
for thisObject = 1:length(objectBoundries)
%get and print its boundries
boundary = objectBoundries{thisObject};
plot(boundary(:,2), boundary(:,1), 'b', 'LineWidth', 2)
%get centroid
objectCentroid = objectMeasurements(thisObject).Centroid;
%get area
objectSize = objectMeasurements(thisObject).Area;
%get major axis length
objectMajorAxisLength = objectMeasurements(thisObject).MajorAxisLength;
%get minor axis length
objectMinorAxisLength = objectMeasurements(thisObject).MinorAxisLength;
%get circularity
objectCircularity = objectMeasurements(thisObject).Perimeter;
%get list of pixels in current object
objectPixels = objectMeasurements(thisObject).PixelIdxList;
%get mean intensity of grayImage
objectMean = mean(grayImage(objectPixels));
%get standard intensity of grayImage
objectStandard = std2(grayImage(objectPixels));
%print object properties
fprintf(1,'#%2d %8.1f %8.1f %10.1f %10.1f %8.1f %12.1f %15.1f %8.1f\n', thisObject, objectCentroid, objectSize, objectMajorAxisLength, objectMinorAxisLength, objectCircularity, objectMean, objectStandard);
%print object labels
text(objectCentroid(1) + labelShiftX, objectCentroid(2), num2str(thisObject), 'FontSize', 14, 'FontWeight', 'Bold', 'Color','w');
end
end
mask = false(size(grayImage));
mask(objectPixels) = true;
%on R channel
tmp = orginalImage(:,:,1);
objectMeanR = mean(tmp(mask));
objectStandard = std2(tmp(mask));
Similarly you can implement mean and std2 on G and B channels.

MATLAB Histogram equalization on GIF images

I'm having a bit of trouble understanding how to change a colormap of a grayscale GIF image after performing histogram equalization on the image. The process is perfectly simple with image compression types that don't have an associated colormap, such as JPEG, and I've gotten it to work with grayscale JPEG images.
clear
clc
[I,map] = imread('moon.gif');
h = zeros(256,1); %array value holds number of pixels with same value
hmap = zeros(256,1);
P = zeros(256,1); %probability that pixel intensity will appear in image
Pmap = zeros(256,1);
s = zeros(256,1); %calculated CDF using P
smap = zeros(256,1);
M = size(I,1);
N = size(I,2);
I = double(I);
Inew = double(zeros(M,N));
mapnew = zeros(256,3);
for x = 1:M;
for y = 1:N;
for l = 1:256;
%count pixel intensities and probability
end
end
end
for j = 2:256
for i = 2:j
%calculate CDF of P
end
end
s(1) = P(1);
smap(1) = Pmap(1);
for x = 1:M;
for y = 1:N;
for l = 1:256;
%calculates adjusted CDF and sets it to new image
end
end
end
mapnew = mapnew/256;
Inew = uint8(Inew);
I = uint8(I);
subplot(1,2,1), imshow(Inew,map); %comparing the difference between original map
subplot(1,2,2), imshow(Inew,mapnew); %to'enhanced' colormap, but both turn out poorly
All is fine in terms of the equalization of the actual image, but I'm not sure what to change about the color map. I tried performing the same operations on the colormap that I did with the image, but no dice.
Sorry that I can't post images cause of my low rep, but I'll try and provide all the info I can on request.
Any help would be greatly appreciated.
function J=histeqo(I)
J=I;
[m,n]=size(I);
[h,d]=imhist(I);
ch=cumsum(h); // The cumulative frequency
imagesize=(m*n); // The image size lightsize=size(d,1);// The Lighting range
tr=ch*(lightsize/imagesize); // Adjustment function
for x=1:m
for y=1:n
J(x,y)=tr(I(x,y)+1);
end
end
subplot(1,2,1);imshow(J);
subplot(1,2,2);imhist(J);
end

Using imnoise to add gaussian noise to an image

How do I add white Gaussian noise with SNR=5dB to an image using imnoise?
I know that the syntax is:
J = imnoise(I,type,parameters)
and:
SNR = 10log10[var(image)/var(error image)]
How do I use this SNR value to add noise to the image?
Let's start by seeing how the SNR relates to the noise. Your error image is the difference between the original image and the noisy image, meaning that the error image is the noise itself. Therefore, the SNR is actually:
SNR = 10log10[var(image)/var(noise)]
For a given image and SNR=5db, the variance of the noise would be:
var(noise) = var(image)/10SNR/10 = var(image)/sqrt(10)
Now let's translate all of this into MATLAB code. To add white Gaussian noise to an image (denote it I) using the imnoise command, the syntax is:
I_noisy = imnoise(I, 'gaussian', m, v)
where m is the mean noise and v is its variance. It is also important to note that imnoise assumes that the intensities in image I range from 0 to 1.
In our case, we'll add zero-mean noise and its variance is v = var(I(:))/sqrt(10). The complete code is:
%// Adjust intensities in image I to range from 0 to 1
I = I - min(I(:));
I = I / max(I(:));
%// Add noise to image
v = var(I(:)) / sqrt(10);
I_noisy = imnoise(I, 'gaussian', 0, v);
Clarification: we use var(I(:)) to treat compute the variance of all samples in image I (instead of var(I), which computes variance along columns).
Hope this helps!
Example
I = imread('eight.tif');
I = double(I);
%// Adjust intensities in image I to range from 0 to 1
I = I - min(I(:));
I = I / max(I(:));
%// Add noise to image
v = var(I(:)) / sqrt(10);
I_noisy = imnoise(I, 'gaussian', 0, v);
%// Show images
figure
subplot(1, 2, 1), imshow(I), title('Original image')
subplot(1, 2, 2), imshow(I_noisy), title('Noisy image, SNR=5db')
Here's the result: