Matlab Transparent PNG (Upside Down/ Smaller Image) - matlab

I am trying to load a transparent image. It seems to work fine in the first part of the code but then fails. Here is the code
for l = 1:4
color = he;
color(something ~= l) = 0;
A = ((color(:,:,1)));
A( all(color == 0, 3 ) ) = 1;
file = strcat(file{k}, '.png');
segmented_images{k} = color;
transparency{k} = A;
chk = segmented_images{k};
f = imshow(chk);
set(f, 'AlphaData', transparency{k});
figure, imshow(chk), title("Working Fine");
end
Here the images appear to be transparent.
If I test it outside the loop:
my_alpha = transparency{1};
chk2 = segmented_images{1};
f = imagesc(chk2);
set(f, 'AlphaData', transparency{1});
figure, imshow(chk2),title('transparent Final');
imwrite(chk2, 'G:\path.png');
I see black color in transparent region. If I do this:
imwrite(chk2, 'G:\wamp\www\final_check.png', "Alpha", my_alpha);
I am able to save a transparent image. I am new to this color processing thing, so do excuse me if I am making a really silly mistake. Thank you
EDIT
Inside the loop image is printed twice, first time as transparent and second time with black background. It seems I am not displaying the image in correct way. Plus the title 'Working Fine' is attached to the black background image not to the other one.
EDIT2:
The real problem is that the image with alpha channel are being upside down.
What I get as a result is:
This is the code:
figure
hold on
h1 = image(segmented_images{1});
set(h1, 'AlphaData', transparency{1});
h2 = image(last_image);
set(h2, 'AlphaData', transparency{2});
h3 = image(segmented_images{3});
set(h3, 'AlphaData', transparency{3});
h4 = image(segmented_images{4});
set(h4, 'AlphaData', transparency{4});
hold off;
There are two issues here: one the image is smaller and upside down. Am I overlaying it correctly. Again I suspect it would be silly mistake that I can't find. Any help would be appreciated.
UPDATE:
When I change
h1 = image(segmented_images{1});
to
h1 = imshow(segmented_images{1});
I get the desired results. Can somebody explain how getting handler is different? I guess I need to go through documentation.

To change the y-direction use:
set ( axesHandle, 'YDir', 'reverse' )

Related

Overlay png image with transparent regions on another image in MATLAB

I have a set of 450 jpg images, each approximately 1200x1500 pixels. I want to apply a black border to every image to make them all 1500x1500 pixels.
Here is an example image: test01.jpg
And I want to turn it into as image that looks like this: 1500x1500 image with border
The way I have been trying to do it is by superimposing a png image of a black border on top of the original image. However, this hasn't worked very well :( Here's my code so far:
A = imread('test01.jpg'); %open image
A2 = imresize(A,[1500 1200]); %resize image to 1500 x 1200 just to make sure it is correct height
RA = imref2d(size(A2));
B = imread('cropper_and_outline_1500x1500.png'); %open cropper
RB = imref2d(size(B));
C = imfuse(A2,B,'blend','Scaling','joint'); %fuse images
imshow(C)
Here's my current output.
There are a few errors... a) the black border is not opaque, b) transparent colour is set to green not transparent, c) the two images are aligned at the top-left corner but I need them centre aligned.
I have been playing with the alpha level to try and fix the green but I didn't really understand what it meant so didn't get far! I also know this might not be the simplest way to do it so if anyone has any other ideas I would really love to hear them. I am trying to do this in MATLAB because I already have a script for renaming the files and I would ideally like to combine both into a single script.
Thanks a lot!
Why not just add black lines to the original image?
I = imread(yourfile);
expectedSize = [1500, 1500];
% Add horizontal lines of pixels (if needed)
line1 = zeros(1, size(I, 2));
Im = [repmat(line1, [(expectedSize(1) - size(I, 1))/2, 1, 3]); ... % add lines on top
I; ...
repmat(line1, [(expectedSize(1) - size(I, 1))/2, 1, 3])]; % add lines on the bottom
% Add vertical lines of pixels (if needed)
line2 = zeros(size(Im, 1), 1);
Im = [repmat(line2, [1, (expectedSize(2) - size(Im, 2))/2, 3]), ... % add lines to the left
Im, ....
repmat(line2, [1, (expectedSize(2) - size(I, 2))/2]), 3]; % add lines to the right
Well, this was done assuming that the result of expectedSize(i) - size(I, i) is divisible by 2, but you get the idea...

Transparent overlapping bar plots

I want to have two transparent bar plots that overlape in one figure. I tried this way:
bar(list2(:,1),list2(:,2),'r','FaceAlpha',0.5)
hold on
bar(list1(:,1),list1(:,2),'g','FaceAlpha',0.5)
but the output is:
Why the second plot is not transparent and has these strange strips?
I use matlab 2016a
your approach is correct, and it works for a few bars:
[list1(:,2),list1(:,1)] = hist(randn(200,1));
[list2(:,2),list2(:,1)] = hist([randn(100,1)-0.5 ; randn(100,1)+0.5]);
bar(list2(:,1),list2(:,2),'r','FaceAlpha',0.5)
hold on
bar(list1(:,1),list1(:,2),'g','FaceAlpha',0.5)
However, you can notice that there are black lines contouring each bar. As the bar number increases, the black contours will cover everything:
[list1(:,2),list1(:,1)] = hist(randn(3000,1), 300);
[list2(:,2),list2(:,1)] = hist([randn(1500,1)-2 ; randn(1500,1)+2], 300);
h1 = bar(list2(:,1),list2(:,2),'r','FaceAlpha',0.5)
hold on
h2 = bar(list1(:,1),list1(:,2),'g','FaceAlpha',0.5)
(The result will depend on the Matlab version. In 2016b it appears that the problem is automatically corrected).
The solution: remove the black contours:
h1.EdgeColor = 'none';
h2.EdgeColor = 'none';

Find a nearly circular band of bright pixels in this image

This is the problem I have: I have an image as shown below. I want to detect the circular region which I have marked with a red line for display here (that particular bright ring).
Initially, this is what I do for now: (MATLAB)
binaryImage = imdilate(binaryImage,strel('disk',5));
binaryImage = imfill(binaryImage, 'holes'); % Fill holes.
binaryImage = bwareaopen(binaryImage, 20000); % Remove small blobs.
binaryImage = imerode(binaryImage,strel('disk',300));
out = binaryImage;
img_display = immultiply(binaryImage,rgb2gray(J1));
figure, imshow(img_display);
The output seems to be cut on one of the parts of the object (for a different image as input, not the one displayed above). I want an output in such a way that it is symmetric (its not always a perfect circle, when it is rotated).
I want to strictly avoid im2bw since as soon as I binarize, I lose a lot of information about the shape.
This is what I was thinking of:
I can detect the outer most circular (almost circular) contour of the image (shown in yellow). From this, I can find out the centroid and maybe find a circle which has a radius of 50% (to locate the region shown in red). But this won't be exactly symmetric since the object is slightly tilted. How can I tackle this issue?
I have attached another image where object is slightly tilted here
I'd try messing around with the 'log' filter. The region you want is essentially low values of the 2nd order derivative (i.e. where the slope is decreasing), and you can detect these regions by using a log filter and finding negative values. Here's a very basic outline of what you can do, and then tweak it to your needs.
img = im2double(rgb2gray(imread('wheel.png')));
img = imresize(img, 0.25, 'bicubic');
filt_img = imfilter(img, fspecial('log',31,5));
bin_img = filt_img < 0;
subplot(2,2,1);
imshow(filt_img,[]);
% Get regionprops
rp = regionprops(bin_img,'EulerNumber','Eccentricity','Area','PixelIdxList','PixelList');
rp = rp([rp.EulerNumber] == 0 & [rp.Eccentricity] < 0.5 & [rp.Area] > 2000);
bin_img(:) = false;
bin_img(vertcat(rp.PixelIdxList)) = true;
subplot(2,2,2);
imshow(bin_img,[]);
bin_img(:) = false;
bin_img(rp(1).PixelIdxList) = true;
bin_img = imfill(bin_img,'holes');
img_new = img;
img_new(~bin_img) = 0;
subplot(2,2,3);
imshow(img_new,[]);
bin_img(:) = false;
bin_img(rp(2).PixelIdxList) = true;
bin_img = imfill(bin_img,'holes');
img_new = img;
img_new(~bin_img) = 0;
subplot(2,2,4);
imshow(img_new,[]);
Output:

Colouring specific pixels in an image

Say I have an image. How can I colour some specific pixels in that image using MATLAB?
Thanks.
RGB Pixels
I'd suggest working with an RGB image, so that you can easily represent color and gray pixels. Here's an example of making two red blocks on an image:
img = imread('moon.tif');
imgRGB = repmat(img,[1 1 3]);
% get a mask of the pixels you want and set an RGB vector to those pixels...
colorMask = false(size(imgRGB,1),size(imgRGB,2));
colorMask(251:300,151:200,:) = true; % two discontiguous blocks
colorMask(50:100,50:100,:) = true;
redPix = permute([255 0 0],[1 3 2]);
imgRGB(repmat(colorMask,[1 1 3])) = repmat(redPix, numel(find(colorMask)),1);
AlphaData image property
Another cool way of doing this is with an image's AlphaData property. See this example on a MathWorks blog. This essentially turns color on or off in certain parts of the image by making the gray image covering the color image transparent. To work with a gray image, do like the following:
img = imread('moon.tif');
influenceImg = abs(randn(size(img)));
influenceImg = influenceImg / (2*max(influenceImg(:)));
imshow(img, 'InitialMag', 'fit'); hold on
green = cat(3, zeros(size(img)), ones(size(img)), zeros(size(img)));
h = imshow(green); hold off
set(h, 'AlphaData', influenceImg)
See the second example at the MathWorks link.

Stretching an ellipse in an image to form a circle

I want to stretch an elliptical object in an image until it forms a circle. My program currently inputs an image with an elliptical object (eg. coin at an angle), thresholds and binarizes it, isolates the region of interest using edge-detect/bwboundaries(), and performs regionprops() to calculate major/minor axis lengths.
Essentially, I want to use the 'MajorAxisLength' as the diameter and stretch the object on the minor axis to form a circle. Any suggestions on how I should approach this would be greatly appreciated. I have appended some code for your perusal (unfortunately I don't have enough reputation to upload an image, the binarized image looks like a white ellipse on a black background).
EDIT: I'd also like to apply this technique to the gray-scale version of the image, to examine what the stretch looks like.
code snippet:
rgbImage = imread(fullFileName);
redChannel = rgbImage(:, :, 1);
binaryImage = redChannel < 90;
labeledImage = bwlabel(binaryImage);
area_measurements = regionprops(labeledImage,'Area');
allAreas = [area_measurements.Area];
biggestBlobIndex = find(allAreas == max(allAreas));
keeperBlobsImage = ismember(labeledImage, biggestBlobIndex);
measurements = regionprops(keeperBlobsImage,'Area','MajorAxisLength','MinorAxisLength')
You know the diameter of the circle and you know the center is the location where the major and minor axes intersect. Thus, just compute the radius r from the diameter, and for every pixel in your image, check to see if that pixel's Euclidean distance from the cirlce's center is less than r. If so, color the pixel white. Otherwise, leave it alone.
[M,N] = size(redChannel);
new_image = zeros(M,N);
for ii=1:M
for jj=1:N
if( sqrt((jj-center_x)^2 + (ii-center_y)^2) <= radius )
new_image(ii,jj) = 1.0;
end
end
end
This can probably be optimzed by using the meshgrid function combined with logical indices to avoid the loops.
I finally managed to figure out the transform required thanks to a lot of help on the matlab forums. I thought I'd post it here, in case anyone else needed it.
stats = regionprops(keeperBlobsImage, 'MajorAxisLength','MinorAxisLength','Centroid','Orientation');
alpha = pi/180 * stats(1).Orientation;
Q = [cos(alpha), -sin(alpha); sin(alpha), cos(alpha)];
x0 = stats(1).Centroid.';
a = stats(1).MajorAxisLength;
b = stats(1).MinorAxisLength;
S = diag([1, a/b]);
C = Q*S*Q';
d = (eye(2) - C)*x0;
tform = maketform('affine', [C d; 0 0 1]');
Im2 = imtransform(redChannel, tform);
subplot(2, 3, 5);
imshow(Im2);