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.
Related
I am trying to add noise to an image that varies based on the intensity of an image.
I = imread(filename);
figure, imshow(I);
v = I(:);
J = imnoise(I, 'localvar', v, 0.04*v);
figure, imshow(J);
But when I run the algorithm, I get the following exception:
error using max: Integers can only be combined with integers of the
same class, or scalar doubles
I'm not sure what my issue is either. Thank you so much!
Most likely, you read I from the file in one format, and imnoise function uses different format. After reading I, write the following line:
I = double(I)
That would help you. Here is the whole example from a similar question:
Using imnoise to add gaussian noise to an image:
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')
I am trying to remove moving shadows in video using the 'stationary wavelet transform technique' as mentioned in the reference paper. I coded in MATLAB but not getting expected output. I am begineer in MATLAB so Can anyone please review my code to check whether it followed all the steps as mentioned in the paper.
Recap of the algorithm followed in the reference paper:
(i) Convert the rgb video frame to hsv
(ii)split the hsv into individual component
(iii)Find the absolute difference between h,s and v component of current and background frame
(iv)Apply the SWT transformation on difference 's' and 'v'
(V)Compute the skewness value for the swt output
(vi)For shadow detection: If the swt output of 'v' greater than its skewness, assign those pixel value to '1' else'0'
(vii) For shadow removal: thresholding operation is applied based on swt output of's' reference paper
function shadowremoval()
obj = setupSystemObjects();
while ~isDone(obj.reader)
frame = readFrame();
mask1 = shadow(frame);
displayTrackingResults();
end
%% Create System Objects
function obj = setupSystemObjects()
% Create a video file reader.
obj.reader = vision.VideoFileReader('visiontraffic.avi');
% Create two video players, one to display the video,
% and one to display the foreground mask.
obj.videoPlayer = vision.VideoPlayer('Position', [10, 250, 700, 400]);
obj.maskPlayer = vision.VideoPlayer('Position', [720, 250, 700, 400]);
obj.detector = vision.ForegroundDetector('NumGaussians', 3, ...
'NumTrainingFrames', 40, 'MinimumBackgroundRatio', 0.7);
end
%% Read a Video Frame
% Read the next video frame from the video file.
function frame = readFrame()
frame = obj.reader.step();
end
%% Perform the operation to remove shadows
function mask1 = shadow(frame)
Background=0.0;
% Detect foreground.
mask1 = obj.detector.step(frame);
mask1 = uint8(repmat(mask1, [1, 1, 3])) .* 255;
% Apply morphological operations to remove noise and fill in holes.
% mask1 = imerode(mask1, strel('rectangle', [3,3]));
% mask1 = imclose(mask1, strel('rectangle', [15, 15]));
mask1 = imopen(mask1, strel('rectangle', [15,15]));
mask1 = imfill(mask1, 'holes');
% Now let's do the differencing
alpha = 0.5;
if frame == 1
Background = frame;
else
% Change background slightly at each frame
% Background(t+1)=(1-alpha)*I+alpha*Background
Background = (1-alpha)* frame + alpha * Background;
end
% Do color conversion from rgb to hsv
x=rgb2hsv(mask1);
y=rgb2hsv(Background);
% Split the hsv component to h,s,v value
Hx = x(:,:,1);
Sx = x(:,:,2);
Vx = x(:,:,3);
Hy = y(:,:,1);
Sy = y(:,:,2);
Vy = y(:,:,3);
% Calculate a difference between this frame and the background.
dh=(abs(double(Hx) - double(Hy)));
ds1=(abs(double(Sx) - double(Sy)));
dv1=(abs(double(Vx) - double(Vy)));
% Perform the 'swt'
[as,hs,vs,ds] = swt2(ds1,1,'haar');
[av,hv,vv,dv] = swt2(dv1,1,'haar');
%Compute the skewness value of 'swt of v'
sav=skewness(av(:));
shv=skewness(hv(:));
svv=skewness(vv(:));
sdv=skewness(dv(:));
%Compute the skewness value of 'swt of s'
sas=skewness(as(:));
shs=skewness(hs(:));
svs=skewness(vs(:));
sds=skewness(ds(:));
%Perform the thresholding operation
b=(av>=sav);
c=(hv>=shv);
d=(vv>=svv);
e=(dv>=sdv);
f=(as>=sas);
g=(hs>=shs);
h=(vs>=svs);
i=(ds>=sds);
j=(b&f);
k=(c&g);
l=(d&h);
m=(e&i);
%Perform the inverse 'swt'operation
recv = iswt2(b,c,d,e,'haar');
recs= iswt2(j,k,l,m,'haar');
de_shadow=cat(3,dh,recs,recv);
mask1=hsv2rgb(de_shadow);
mask1=rgb2gray(mask1);
end
function displayTrackingResults()
% Convert the frame and the mask to uint8 RGB.
frame = im2uint8(frame);
mask1 = uint8(repmat(mask1, [1, 1, 3])) .* 255;
% Display the mask and the frame.
obj.maskPlayer.step(mask1);
obj.videoPlayer.step(frame);
end
end
I did :
I = imread('abc.jpg');
BW = roipoly(I);
I am trying to get the pixel value of all the points that I have clicked while creating a polygon.
r= BW(:, :, 1 );
g= BW(:, :, 2 );
b= BW(:, :, 3 );
This doesn't work.
Finally I would like to write to text file:
filename = fullfile('C:\Users\ABC\Documents\MATLAB','test.txt');
fid = fopen(filename,'w');
fprintf(fid, '%d %d %d', r,g,b);
fclose(fid);
Your problem is that size(BW) is only 2D while I is 3D. BW is only a binary mask indicating what pixels were selected by roipoly.
A possible solution is to use the BW mask to select the pixels from I:
rI = reshape(I,[],3); %// "flatten" the image
selectedRGB = rI(BW,:); %// select the pixels in the polygon
Now you can write to file
dlmwrite( fullfile('C:\Users\ABC\Documents\MATLAB','test.txt'), selectedRGB, 'delimiter', ' ');
See dlmwrite for more info.
If you are only interested in the RGB values of the polygon's corners (and not the entire area), you can use the following code
[BW xi yi] = roipoly(I);
Now you should ignore BW which represent the area, and work only with xi and yi:
sel = sub2ind( size(I(:,:,1)), yi, xi ); %// convert indices to linear indices
selectedRGB = rI(sel,:); %// will give you the RGB of the corners only.
Alternatively, you can use ginput to select points in image.
This code creates points in the corners of the polygon using pixel coordinates,
creats the mask of the region of interest, uses the BW mask to create a grayscale image of the region and then the grayscale region is converted back to RGB.
The text file created in the end of the code contains the Unit8 data of the image.
Is it only the manually specified coordinates all you want to the text file?
I = imread('image.jpg');
c = [62 95 103 70]; % specify column coordinates (more than 4 if you want)
r = [126 122 193 197]; % specify row coordinates (more than 4 if you want)
BW = roipoly(I,c,r); % convert to binary mask
[R C] = size(BW);
for i = 1:R
for j = 1:C
if BW(i,j) == 1
outputImage(i,j) = I(i,j); % get grayscale image of the specified region
else
outputImage(i,j) = 0;
end
end
end
imtool(outputImage, []); % in imtool you can see that pixels have only one value
rgbBinary = cat(3,outputImage,outputImage,outputImage); % convert grayscale image to binary rgb
finalImage = im2uint8(rgbBinary); % convert image from double binary rgb (0 1) to unit8 256 value rgb
imtool(finalImage) % analyze image using (Inspect pixel values)
for i = 1:R
for j = 1:C
if BW(i,j) == 1
finalImage(i,j,1)=I(i,j,1);
finalImage(i,j,2)=I(i,j,2);
finalImage(i,j,3)=I(i,j,3);
end
end
end
imshow(finalImage) % the specified area in rgb
txtdoc = fopen( 'imageData.txt', 'wt' ); % creates txt file if it doesn't exist or overwrites the existing file
dlmwrite('imageData.txt',finalImage,'delimiter',' ') % writes the data to txt file delimited by space
fclose(txtdoc);
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
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.