Find difference between two RGB similar image - python-imaging-library

I have two RGB images and want to find the difference between two.
Different pixels should be in red color and same pixels should be in grayscale.
I tried using PIL but unable to get the desired results.

You are after Pixel Access - https://pillow.readthedocs.io/en/5.2.x/reference/PixelAccess.html#pixelaccess-class. This lets you read and write individual pixels in an image.
I am presuming that the two images are the same size. I have used a simple method of converting the relevant pixels to grayscale - averaging the R, G, B values.
from PIL import Image
px1 = im1.load()
px2 = im2.load()
imOut = Image.new('RGB', im1.size)
pxOut = imOut.load()
for x in range(0, im1.width):
for y in range(0, im1.height):
if px1[x, y] == px2[x, y]:
r, g, b = px1[x, y]
grayscale = int((r + g + b) / 3)
pxOut[x, y] = (grayscale, grayscale, grayscale)
else:
pxOut[x, y] = (255, 0, 0)
imOut.show()

Related

How do I calculate the bending of filtration in matlab?

I have 2 variables:
Image which contain original image.
FilteredImage which is filtered image.
Both are RGB images. I know how to calculate the bending for 2-D images
Image = unread('C:\Users\klass\Pictures\man.jpeg');
NoiseImage = minimise(Image,'gaussian');
ImageFiltered = NoiseImage;
for c = 1 : 3
ImageFiltered (:, :, c) = medfilt2(NoiseImage(:, :, c) [3, 3]
end
Bending = norm(im2double(Image - FilteredImage))/norm(im2double(FilteredImage)) * 100;
When I try to use this formula to my figures I get this error:
Error using norm
Input must be 2-D.
I tried pass 3-D images to norm() function. The work around is convert each image to 2-D by rgb2gray()function.
Therefore I evacuate banding with formula:
Bending = norm(im2double(rgb2gray(Image) - rgb2gray(FilteredImage)) / norm(im2double(rgb2gray(Image))) * 100

Specifying value of each pixel in a superpixel

I could specify superpixels for an image an their properties.
L = superpixels(A, 200);
K=regionprops(L, 'PixelIdxList');
I know that mean intensity value of each superpixel could be specified as follows:
K=regionprops(L, 'MeanIntensity')
The question is how it is possible to specify values of all pixels within a superpixel?
The syntax for getting a list of all pixel values within each label is K = regionprops(L, A, 'PixelValues'). But this only works for grey-value A.
The simplest solution is to iterate over the channels, and call the above function for each channel:
A = imread('~/tmp/boat.tiff'); % whatever RGB image
L = superpixels(A, 200);
n = size(A,3); % number of channels, typically 3
K = cell(max(L(:)),n);
for ii=1:n
tmp = regionprops(L, A(:,:,ii), 'PixelValues');
K(:,ii) = {tmp.PixelValues};
end
We now have a cell array K that contains the values for each labeled pixel: K{lab,1} is the set of values for the pixels labeled lab, for the first channel.
The following code collates the components of each pixel into a single array:
K2 = cell(size(K,1),1);
for ii=1:numel(K2)
K2{ii} = [K{ii,:}];
end
Now K2 contains RGB arrays of data: K{lab} is a Nx3 matrix with RGB values for each of the N pixels labeled lab.

MATLAB: applying filter to ROI or mask in greyscale image

I have a greyscale image (I), and would like to apply different filters to different regions of that image in matlab (R2015b) (random and irregular shaped regions). I have a binarized version of what I would like the first filter applied to (attached). I'm not sure the best way to make a mask...I can load this binary image and use bwconncomp to locate connected components and define them as single vectors which won't work with poly2mask. Any suggestions for A. how to get a mask out of this binary image and B. how to use this mask to apply a filter to that part of the greyscale image?
Thanks in advance!
MASK=imread('/Users/bk/Desktop/FIJI_image/mask4.tif');
BACK=imcomplement(MASK);
I=imread('/Users/bk/Desktop/FIJI_image/Orig.tif');
I(~MASK)=0;
SE=ones(13,13);
A=stdfilt(I, SE);
minZ=min(min(A));
maxZ=max(max(A));
Low_High=[minZ maxZ];
var5=255/maxZ;
B=uint8(A*var5);
C=(imadjust(B,stretchlim(B),[]));
imtool(C);
A binary image is a mask.
Given a grayscale image I and a binary image M with the same size, you can get the image I filtered by the mask M using:
J = I;
J(~M) = 0;
This is just masking. For filtering you can apply a filter on I with imfilter or any other one of MATLAB's filter functions. For example:
h = fspecial('motion', 50, 45);
K = imfilter(I, h);
Now you can get the original values of the pixels which are not in M:
K(~M) = I(~M);
So now K have filtered pixels in the locations where M is true, and untempered pixels in the locations where M is false.
Code for the example you added:
inputDir = 'temp2';
I = imread(fullfile(inputDir, 'PJlUm.png'));
M = imread(fullfile(inputDir, 'ewSPv.png'));
M = logical(M); % Convert M to a logical matrix, i.e. a mask.
Imasked = I;
Imasked(~M) = 0;
ImaskedAndStretched = Imasked;
ImaskedAndStretched(M) = imadjust(ImaskedAndStretched(M),stretchlim(ImaskedAndStretched(M)),[]);
IstretchedAtMask = I;
IstretchedAtMask(M) = ImaskedAndStretched(M);
figure;
subplot(3,2,1);
imshow(I);
title('Input Image');
subplot(3,2,2);
imshow(M);
title('Mask');
subplot(3,2,3);
imshow(Imasked);
title('Image Masked');
subplot(3,2,4);
imshow(ImaskedAndStretched);
title('Image Masked & Stretched');
subplot(3,2,5);
imshow(IstretchedAtMask);
title('Image Stretched At Mask');
The output:

How to convert RGB images to grayscale in matlab without using rgb2gray

I'm currently using code:
i = imread('/usr/share/icons/matlab.png');
for k=1:1:m
for l=1:1:n
%a(k,l)=m*n;
a(k,l) = (.299*i(k,l,1))+(.587*i(k,l,2))+(.114*i(k,l,3));
end
end
imshow(a);
It shows only a white screen. Also the newly generated dimensions are n x m x 3 whereas it should be only m x n x 1.
If I use mat2gray it display the image like this
Since the image is a PNG, imread() is returning an integer image, with intensity values in the range [0 255] or equivalent, depending on the original bit depth. The conversion formula makes a a double image, which is expected to have intensities in the range [0 1]. Since all the pixel values in a are probably much greater than 1, they get clipped to 1 (white) by imshow().
The best option is to explicitly convert the image format before you start - this will take care of scaling things correctly:
i = imread('/usr/share/icons/matlab.png');
i = im2double(i);
a = .299*i(:,:,1) + .587*i(:,:,2) + .114*i(:,:,3); % no need for loops
imshow(a);
input=imread('test.jpg');
subplot(1,2,1), imshow(input), title('RGB Scale image');
[x,y,~] = size(input);
for i = 1:1:x
for j = 1:1:y
output(i,j) = 0.40*input(i,j,1) + 0.50*input(i,j,2) + 0.30*input(i,j,3);
end
end
subplot(1,2,2), imshow(output), title('Gray Scale image');

how to count number of color in an image in matlab

Actually, I am new in Matlab. I don't know much about it.
How can I count number of color in am image?
For an example I have an image of a DNA microarray (which is an RGB image) and I want to count how many yellow dot, red dot and green dot it has.
If I is your image you can use this:
size(unique(reshape(I, [], 3), 'rows'), 1)
First reshape the image to an nx3, where n stands for the number of pixels in your image, the apply the unique function to collapse equal rows (pixel with same colour) and finally the size of the resulting matrix will give you the number of unique colours.
If you are using RGB then it too depends on whether it's 24, 32 or 64 bit.
e.g. for 24 bit image, there are 256*256*256 = 16,777,216 of possible combinations of RGB. ;)
Wouldn't it be easier to separate the colours R, G, B, then you count each of those separated subplots ? ;)
Try this out:
get each R, G, B channels out. Then do a histogram on it to count each R, G, B pixels.
DNA = imread('peppers.png');
redChannel = DNA(:, :, 1);
greenChannel = DNA(:, :, 2);
blueChannel = DNA(:, :, 3);
For red:
[redCount grayCount] = imhist(redPlane);
subplot(2, 2, 2);
imshow( DNA(:,:,2));
>> redcount
ans = 38385 // SAMPLE count
You may use a loop from 1:3 if you prefer so.
If you have single pixel dots and the "red", "yellow" and "green" means exactly [255 0 0], [0 255 255] and [0 255 0], then your question can be answered quite simple:
red_dots = (DNA(:,:,1)==255);
n_red_dots = sum(red_dots(:));
yellow_dots = (DNA(:,:,2)==255 & DNA(:,:,3)==255);
n_yellow_dots = sum(yellow_dots(:));
green_dots = (DNA(:,:,2)==255);
n_green_dots = sum(green_dots(:));
if your colors are not that exact, but still single-pixel (or they are around the same size and you are rather interested in rough proportions), you can do thresholding:
redish_dots = (DNA(:,:,1)>200 & DNA(:,:,2)<40 & DNA(:,:,3)<40);
n_redish_dots = sum(redish_dots(:));
and so on...