3D double Array to RGB in MATLAB - matlab

I have 256 x 256 x 3 double Array. How to create (RGB) picture from it in Mat-lab. The values are like (3091, 986, 1003, 1699). Thanks in advance..

You can normalise the values in the matrix so that they lie between 0 and 1 and then use the command imshow:
// create a random example of a matrix
I = 4000*rand(256, 256, 3);
// normalise the values in I
for i = 1:3
I(:, :, i) = I(:, :, i)/max(max(I(:, :, i)));
end
// display as image
imshow(I, 'InitialMagnification', 'fit')

Related

How to convert a 3D array directly to a video in matlab

I have a 3D matrix with a dimension of 600x600x28 which the last index is the number of frames and want to convert it to a video file. As you can see in the code below I convert the array into a 4D matrix with the size of 600X600X3X28 to make it compatible with WriteVideo format. but I am not sure why the output video is empty!
Orig = randi([1 1000],600,600,28);
x = uint8(255 * mat2gray(Orig));
map=jet;
for i=1:size(x,3)
x_all(:,:,:,i) = ind2rgb(x(:,:,i),map);
end
x_all = uint8(x_all);
v = VideoWriter('myvideo');
open(v);
writeVideo(v,x_all);
close(v)
You don't have to convert the video to RGB, you may create a Grayscale video.
Example:
x = randi([0, 255], 600, 600, 28, 'uint8');
v = VideoWriter('myvideo_grayscale.avi', 'Grayscale AVI');
open(v);
writeVideo(v, x);
close(v)
The reason you are getting a black video is that ind2rgb returns values in range [0, 1] and when converting to uint8: x_all = uint8(x_all);, all the values are 0s and 1s (instead of range [0, 255]).
Example for creating colored video:
Orig = randi([1 1000],600,600,28);
x = im2uint8(mat2gray(Orig));
map = jet(256); % Use colormap with 256 colors (the default is 64).
x_all = zeros(size(x, 1), size(x, 2), 3, size(x, 3), 'uint8'); % Allocate space
for i=1:size(x,3)
x_all(:,:,:,i) = im2uint8(ind2rgb(x(:,:,i), map));
end
v = VideoWriter('myvideo.avi');
open(v);
writeVideo(v,x_all);
close(v)
In case you are actually getting an empty video file (not just black video), something is wrong with your setup.

How to find and highlight the brightest region an image in Matlab?

Dears,
I would like to kindly ask you for support. My goal is to find the brightest region of the RGB image and highlight it without additional tools. Please see my example below.
rgbImage = imread( 'Zoom1_WhiteImage.png' );
imshow(rgbImage);
[rows, columns, numberOfColorChannels] = size(rgbImage)
[x, y] = meshgrid(1:columns, 1:rows);
% Extract the individual red, green, and blue color channels.
% Need to cast to double or else x and y will be clipped to 255 when we concatenate them.
if numberOfColorChannels == 1
% Leave as gray scale.
% Get array listing [r, g, b, x, y]. Using (:) will turn all the 2-D arrays into column vectors.
output = [rgbImage(:), x(:), y(:)];
else
redChannel = double(rgbImage(:, :, 1));
greenChannel = double(rgbImage(:, :, 2));
blueChannel = double(rgbImage(:, :, 3));
% Get array listing [r, g, b, x, y]. Using (:) will turn all the 2-D arrays into column vectors.
output = [redChannel(:), greenChannel(:), blueChannel(:), x(:), y(:)];
end
[rows, columns] = find(rgbImage == 155);
imshow(rgbImage);
hold on
Unfortunately, I am struggling with how to proceed with the plot of the points that should overlay the grey image.
Would you be so kind and help me to finish the code, please?
I'd recommend you read about logical indexing in MATLAB - it's a very powerful concept, and it allows you to skip most of the things you're trying to do by flattening the arrays, and creating separate arrays of indices with meshgrid. Here is an article that addresses logical indexing down at the bottom, for example.
I've modified and added to your code so it accomplishes the job using logical indexing. I tested this in R2019b.
rgbImage = imread( 'Zoom1_WhiteImage.png' );
imshow(rgbImage);
[rows, columns, numberOfColorChannels] = size(rgbImage)
% This is unnecessary - the 'find' command will generate the indices
% without you preparing a matrix of them:
% [x, y] = meshgrid(1:columns, 1:rows);
if numberOfColorChannels == 1
% No need to flatten the image, or combine it with indices:
%output = [rgbImage(:), x(:), y(:)];
brightness = rgbImage; % For a 1 channel image, brightness is the same as the original pixel value.
else
% redChannel = double(rgbImage(:, :, 1));
% greenChannel = double(rgbImage(:, :, 2));
% blueChannel = double(rgbImage(:, :, 3));
% Get array listing [r, g, b, x, y]. Using (:) will turn all the 2-D arrays into column vectors.
% output = [redChannel(:), greenChannel(:), blueChannel(:), x(:), y(:)];
% For an RGB image, the brightness can be estimated in various ways, here's one standard formula:
brightness = (0.2126*rgbImage(:, :, 1) + 0.7152*rgbImage(:, :, 2) + 0.0722*rgbImage(:, :, 3));
end
% Establish a brightness threshold - pixels brighter than this value will
% be highlighted
threshold = 215;
% Create a zero-filled mask of equal size to the image to hold the
% information of which pixels met the brightness criterion:
mask = zeros(rows, columns, 'logical');
% Assign "1" to any mask pixels whose corresponding image pixel met the
% brightness criterion:
mask(brightness > threshold) = 1;
figure;
% Overlay and display mask. imoverlay was introduced in R2017, but the
% syntax has changed a bit, so check the version you're using. You can also
% use imfuse, or imshowpair, or make your own image blending algorithm,
% depending on how you want it to look.
imshow(imoverlay(rgbImage, mask, 'red'));
hold on

Gradient colors for faces of surface

I have the following code for MATLAB:
close all
clear all
clc
edges= linspace(0,1,10);
[X,Y] = meshgrid(edges);
Z=rand(10);
h= surf(X,Y,Z,'FaceColor','none')
I need to paint the faces on this surface. The face with coordinate (0,0) should be green and the face with coordinate(1,1) should be red. All faces on diagonal should be yellow.
Could You help me to perform this painting?
If you have a closer look at the surf command, you'll see, that you can set a custom "colormap", which is then used instead of the Z data as a color indicator.
So, you just have to set up a proper "colormap". That one must have the same dimensions as your X and Y data, and for each data point you must specify the [R, G, B] triplet of your choice, i.e. [0, 1, 0] for the [0, 0] coordinate, [1, 0, 0] for the [1, 1] coordinate, and some "diagonal" interpolation between those two.
Luckily, you already have that, have a look at your X and Y data! Adding both will give that kind of "diagonal" interpolation for the green channel. The inverse of that will give the proper red channel. (The scaling is a bit corrupt, since you have values larger than 1.0, but these will "clipped".)
Here's the enhanced code:
edges = linspace(0, 1, 10);
[X, Y] = meshgrid(edges);
Z = rand(10);
cm(:, :, 1) = (X + Y); % Red channel
cm(:, :, 2) = 2 - cm(:, :, 1); % Green channel
cm(:, :, 3) = zeros(size(X)); % Blue channel (empty)
h = surf(X, Y, Z, cm); % No need for the FaceColor property
The output looks like this:
Hope that helps!
One way would be the following:
edges= linspace(0,1,10);
[X,Y] = meshgrid(edges);
Z=rand(10);
% Fake some color data
cdata = zeros(size(Z));
for i = 1:size(cdata,1)
cdata(i,i) = i;
end
%make a suitable colormap
cm = ones(size(cdata,1), 3);
cm = cm .*[ 1 1 0 ] % everything yellow
cm(1, :) = [1 1 1] % except for 0
cm(2, :) = [1 0 0] % except for 1
cm(end, :) = [0 1 0] % except for 10
ax = axes();
h = surface(ax, X,Y,Z);
h.CData = cdata;
ax.Colormap = cm;

MATLAB get xyrgb pixel values

I'm trying to get a five column matrix with one row for each pixel in an image. The first two columns are the location (x,y) of the pixel, and the remaining columns are the RGB values of the pixel.
I can use a loop to create this matrix, but I would like to vectorize this operation for efficiency purposes. I can get the RGB values with img(:,:,1), img(:,:,2), and img(:,:,3) respectively, but I don't know how to get the x and y value of the associated pixel while vectorizing.
You can use meshgrid to get all x and y coordinates and then append these to your data resulting in a N x 5 matrix.
[x, y] = meshgrid(1:size(img, 2), 1:size(img, 1));
out = cat(2, x(:), y(:), reshape(img, [], 3));
Find is one way to query the coordinates.
You can separate the RGB channels, find the coordinates and then concatenate the results:
imgR = img(:, :, 1);
imgG = img(:, :, 2);
imgB = img(:, :, 3);
[rows, cols] = find(imgR + 1); % +1 to avoid zeros!
M = [rows, cols, imgR(:), imgG(:), imgB(:)];

extracting contents and calculating area within an image

Objective :
I need to extract and highlight a specific color from a given image[Say X] and finally I need to calculate the Area of X.
I need help in :
Detecting individual labels in the image[below] in form of a circle.
What I have done :
Below is my code and I have attached the RGB variable's image[below]. I have extracted the "beige color" from the given image(that is X) and labeled it.
To detect the individual component, I tried like the classical "Coins Example [Identifying different coin values from an image using MATLAB", to first detect element. But here as the regions are not uniform, So, I am bit confused.
Code :
clear all; clc;
close all;
I = imread('19.jpg');
%figure;imshow(I);
B = White_Beige(I); // The Function is used to threshold the RGB image
to LAB colorspace. Here, we extract the Beige
color present in the image and provide the final
Black and White image with the presence of Beige
color as Black and rest as white.
%figure; imshow(B);
BW2 = imfill(~B,'holes');
figure; imshow(BW2);
Border = imclearborder(BW2);
[OBL,nbOBObjets] = bwlabel(Border,8);
RGB = label2rgb(OBL,'jet',[0 0 0]);
figure, imshow(RGB);
Any help is much appreciated
maybe this will help:
Note that in this code the "area" occupied by a color is represented as a real number on the interval (0, 1), where 0 means no pixel in the image is that color, and 1 means that all of the pixels in the image are that color.
[A, map] = imread('L8IZU_2.png');
image(A); % display the image
if ~isempty(map)
A = ind2rgb(X, map); % convert image to RGB
end
color_counts = zeros(256, 256, 256);
% color_counts(x, y, z) records the number of pixels in the image
% which have RGB color [x-1, y-1, z-1];
% For example color_counts(1, 1, 1) records the number of pixels in
% the image which have color [0, 0, 0];
% As another example, color_counts(65, 43, 11) records the number of
% pixels in the image which are of color [64, 42, 10];
time_of_last_progress_report = clock;
% traverse the image pixel by pixel
for m = 1:size(A, 1)
for n = 1:size(A, 2)
current_time = clock;
if etime(current_time, time_of_last_progress_report) > 2
percent_progress = 100*(((m - 1)*size(A, 2) + n)/(size(A, 1)*size(A, 2)));
disp(strcat(num2str(percent_progress),'% of the image has been scanned'));
time_of_last_progress_report = clock;
end
current_color = A(m, n, :);
current_color = squeeze(current_color);
% squeeze removes singleton dimensions
% in other words, squeeze converts current_color from a 1x1x3 array into
% a 3x1 array
index = current_color + uint8(ones(size(current_color)));
% Let us say that index = [1, 3, 4];
% We want to increment color_counts(1, 3, 4);
% However, color_counts([1, 3, 4]), or color_counts(index),
% does not return a reference to one single element at that location
% Instead, color_counts([1, 3, 4]) returns a 1x3 vector containing
% the 1st, 3rd, and 4th elements of the color_counts array
% we convert index into a cell array and then convert the cell
% array into a comma separated list.
index2 = num2cell(index);
old_count = color_counts(index2{:});
color_counts(index2{:}) = 1 + old_count;
end
end
disp(' ');% line break
disp('Now sorting colors by how often they apeared....');
color_counts_linear = reshape(color_counts, 1, numel(color_counts));
[color_counts_sorted, indicies] = sort(color_counts_linear, 'descend');
[R,G,B] = ind2sub(size(color_counts),indicies);
R = R - ones(size(R));
G = G - ones(size(G));
B = B - ones(size(B));
areas = (1/(size(A, 1)*size(A, 2))) * color_counts_sorted;
% display the top 5 most common colors
disp(' '); % line break
disp('Top 5 most common colors:');
for k = 1:min(5, numel(areas))
disp(strcat('[', num2str(R(k)), ',', num2str(B(k)), ',', num2str(G(k)),'] : ', num2str(100*areas(k)), '%'));
end