How to read images from folder, divide each image and store it in new folder serially - matlab

I am taking images from folder('E:\cicila\ME PROJECT\ME 4 SEM\brodatz\IMAGES TAKEN\TRY) Images are stored as 1. gif , 2.gif , and so on
I am dividing it . I want to store these images with new name . eg image taken is 1.gif
after diving it into 4 parts, I want to name these new images as 1. gif , 2.gif , 3.gif , 4.gif
Please help me . I have tried my code but it shows the error :
Error in feb11try (line 25)
Img1(i,j) = NewImage(startr+i, startc+j);
Code is :
clc;
close all;
clear all;
srcFiles = dir('E:\cicila\ME PROJECT\ME 4 SEM\brodatz\IMAGES TAKEN\TRY\*.gif'); % the folder in which ur images exists
%Taking the image from the given URL, it could have been the name of the file with extension if the root folder
n =2; %defining the number of rows
m =2; %defining the number of columns
for c = 1 : length(srcFiles)
NewImage = 'newimage.gif'; %granting permission to create a file and write in it
rf = floor(512/n); %generating the number of row pixels in the new file
cf = floor(512/m); %generating the number of row pixels in the new file
for v = 1:n
for s = 1:m %nXm files need to be made
startr = (v-1)*rf;
startc = (s-1)*cf;
for i = 1 : rf
for j = 1 : cf
Img1(i,j) = NewImage(startr+i, startc+j);
end
end
imwrite( NewImage,'c.gif');
end
end
end

You need to use imread() to read in the source image rather than treating the filename as an image. Based on what you have, I assume your image is single channel. I also made the assumption that your image is unsigned int. Also, keep in mind there are much faster ways to perform this using indexing.
I made a few changes to your sample that should get the job done under these assumptions. This is untested.
clc;
close all;
clear all;
srcFiles = dir('E:\cicila\ME PROJECT\ME 4 SEM\brodatz\IMAGES TAKEN\TRY\*.gif');
n = 2; %defining the number of rows
m = 2; %defining the number of columns
count = 0;
for c = 1 : length(srcFiles)
srcFilename = ['E:\cicila\ME PROJECT\ME 4 SEM\brodatz\IMAGES TAKEN\TRY\' srcFiles(c).name];
srcImg = imread(srcFilename); % Read source image
[~,srcName] = fileparts(srcFilename);
rf = floor(512/n); %generating the number of row pixels in the new file
cf = floor(512/m); %generating the number of row pixels in the new file
% initialize output image
destImg = uint8(zeros(rf,cf));
for v = 1:n
for s = 1:m %nXm files need to be made
startr = (v-1)*rf;
startc = (s-1)*cf;
for i = 1 : rf
for j = 1 : cf
destImg(i,j) = srcImg(startr+i, startc+j);
end
end
count = count + 1;
imwrite( destImg, sprintf('%d.gif', count) );
end
end
end

Related

Updating histogram in a for-loop without growing y-data

I have had zero luck finding this elsewhere on the site, so here's my problem. I loop through about a thousand mat files, each with about 10,000 points of data. I'm trying to create an overall histogram of this data, but it's not very feasible to concatenate all this data to give to hist.
I was hoping to be able to create an N and Bin variable each loop using hist (y), then N and Bin would be recalculated on the next loop iteration by using hist(y_new). And so on and so on. That way the source data doesn't grow and when the loop finally ends, I can just use bar(). If this method wouldn't work, then I am very open-minded to other solutions.
Also, it is probably not safe to assume that the x data will remain constant throughout each iteration. I'm using 2012a.
Thanks for any help!!
I think the best solution here is to loop through your files twice: once to set the bins and once to do the histogram. But, if this is impossible in your case, here's a one shot solution that requires you to set the bin width beforehand.
clear; close all;
rng('default') % for reproducibility
% make example data
N = 10; % number of data files
M = 5; % length of data files
xs = cell(1,N);
for i = 1:N
xs{i} = trnd(1,1,M);
end
% parameters
width = 2;
% main
for i = 1:length(xs)
x = xs{i}; % "load data"
range = [min(x) max(x)];
binsPos = 0:width:range(2)+width;
binsNeg = fliplr( 0:-width:range(1)-width );
newBins = [binsNeg(1:end-1) binsPos];
newCounts = histc(x, newBins);
newCounts(end) = []; % last bin should always be zero, see help histc
if i == 1
counts = newCounts;
bins = newBins;
else
% combine new and old counts
allBins = min(bins(1), newBins(1)) : width : max(bins(end), newBins(end));
allCounts = zeros(1,length(allBins)-1);
allCounts(find(allBins==bins(1)) : find(allBins==bins(end-1))) = counts;
allCounts(find(allBins==newBins(1)) : find(allBins==newBins(end-1))) = ...
allCounts(find(allBins==newBins(1)) : find(allBins==newBins(end-1))) + newCounts;
bins = allBins;
counts = allCounts;
end
end
% check
figure
bar(bins(1:end-1) + width/2, counts)
xFull = [xs{:}];
[fullCounts] = histc(xFull, bins);
fullCounts(end) = [];
figure
bar(bins(1:end-1) + width/2, fullCounts)

How to add standrad deviation and moving average

What I want to is:
I got folder with 32 txt files and 1 excle file, each file contain some data in two columns: time, level.
I already managed to pull the data from the folder and open each file in Matlab and get the data from it. What I need to do is create plot for each data file.
each of the 32 plots should have:
Change in average over time
Standard deviation
With both of this things I am straggling can't make it work.
also I need to make another plot this time the plot should have the average over each minute from all the 32 files.
here is my code until now:
clc,clear;
myDir = 'my path';
dirInfo = dir([myDir,'*.txt']);
filenames = {dirInfo.name};
N = numel(filenames);
data=cell(N,1);
for i=1:N
fid = fopen([myDir,filenames{i}] );
data{i} = textscan(fid,'%f %f','headerlines',2);
fclose(fid);
temp1=data{i,1};
time=temp1{1};
level=temp1{2};
Average(i)=mean(level(1:find(time>60)));
AverageVec=ones(length(time),1).*Average(i);
Standard=std(level);
figure(i);
plot(time,level);
xlim([0 60]);
hold on
plot(time, AverageVec);
hold on
plot(time, Standard);
legend('Level','Average','Standard Deviation')
end
the main problam with this code is that i get only average over all the 60 sec not moving average, and the standard deviation returns nothing.
few things you need to know:
*temp1 is 1x2 cell
*time and level are 22973x1 double.
Apperently you need an alternative to movmean and movstd since they where introduced in 2016a. I combined the suggestion from #bla with two loops that correct for the edge effects.
function [movmean,movstd] = moving_ms(vec,k)
if mod(k,2)==0,k=k+1;end
L = length(vec);
movmean=conv(vec,ones(k,1)./k,'same');
% correct edges
n=(k-1)/2;
movmean(1) = mean(vec(1:n+1));
N=n;
for ct = 2:n
movmean(ct) = movmean(ct-1) + (vec(ct+n) - movmean(ct-1))/N;
N=N+1;
end
movmean(L) = mean(vec((L-n):L));
N=n;
for ct = (L-1):-1:(L-n)
movmean(ct) = movmean(ct+1) + (vec(ct-n) - movmean(ct+1))/N;
N=N+1;
end
%mov variance
movstd = nan(size(vec));
for ct = 1:n
movstd(ct) = sum((vec(1:n+ct)-movmean(ct)).^2);
movstd(ct) = movstd(ct)/(n+ct-1);
end
for ct = n+1:(L-n)
movstd(ct) = sum((vec((ct-n):(ct+n))-movmean(ct)).^2);
movstd(ct) = movstd(ct)/(k-1);
end
for ct = (L-n):L
movstd(ct) = sum((vec((ct-n):L)-movmean(ct)).^2);
movstd(ct) = movstd(ct)/(L-ct+n);
end
movstd=sqrt(movstd);
Someone with matlab >=2016a can compare them using:
v=rand(1,1E3);m1 = movmean(v,101);s1=movstd(v,101);
[m2,s2] = moving_ms(v,101);
x=1:1E3;figure(1);clf;
subplot(1,2,1);plot(x,m1,x,m2);
subplot(1,2,2);plot(x,s1,x,s2);
It should show a single red line since the blue line is overlapped.

Vectorization of MATLAB code to optimize speed

Hey fellow MATLAB users. The following code is meant to analyze motion in films. However, when I run the script on a film, it takes almost 14 hours for MATLAB to run the code. I have heard that you can optimize running speed by vectorizing your code; however, I have no idea how to go about this with the code below, since I am far from a programmer.
Can anyone help me out, or point me in the right direction?
Thanks a lot – the m.code is as follows:
%calculates correlations in sequences of film shots 22 May 2014
%t = input vector of initial frames of all shots in the film
prompt1 = 'movie file = ';
movieavi = input(prompt1,'s');
mov = VideoReader(movieavi);
nshots = length(t)-1;
for n = 1:nshots
first = t(n);
last = t(n+1)-2;
slength = last - first + 1;
tempcor = 0;
for k = 1:(slength-1)
im1 = read(mov,first+k-1); %read the image
im2 = read(mov,first+k+1);
im1 = rgb2gray(im1); %convert to grayscale
im2 = rgb2gray(im2);
tmp = corr2(im1,im2);
if(isnan(tmp) == 1)
tmp = .9999;
end
tempcor = tempcor + tmp;
end
dataout(n,3) = tempcor/(slength-1); %mean Lag 1 correlation within a shot
dataout(n,1) = uint32(first/100); %frame in hundreds. Can't export 6 digit integer
dataout(n,2) = mod(first,100); %modolus 100, to be combined with above
cycle = t(n)
end;
xlswrite('dataout.xls', dataout) %this file appears in matlab folder and must
save dataout; %the Matlab version of same

Take a text line in an image file to create a new image file MATLAB

I need to take each line of text from an image file and create a new separate image for each of the lines. i already have a way to count how many lines are in the image file.
if anybody has any suggestions it would be a huge help because i'm not too good with images. im not allowed to use the image processing toolbox.
This is the code:
function out = countLines( imgFile )
% count the number of lines in the image file
im = imread(imgFile);
im = 255 - im;
imbw = uint8(0.33*im(:,:,1) + 0.34*im(:,:,2) + 0.33*im(:,:,3)) > 127;
imwrite(imbw, 'temp.jpg');
rvec = sum(imbw');
rvec1 = [0 rvec 0];
svec = [rvec 0 0];
out = sum(rvec1 == 0 & svec ~= 0);
I tried this method on a test image I found on the internet and it seemed to work alright provided the text is straight. Basically you look for entries in your rvec vector whose neighbouring entries are both smaller than them. That is to say you look for the local maximum entries (first image). After that you group the clusters of lines together to decide where to split the image (second image).
clear; clc;
im = imread('text.png'); % load the image
[Nrows,Ncols,~] = size(im); % get the size
imgray = rgb2gray(im); % convert to grayscale
vec = mean(imgray,2); % average intensities of each row
localMax=[]; % list of local maximum entries
for i = 2:Nrows-1 % accept local max rows that do not have text
hasText = sum( imgray(i,:)<100 )>0;
if vec(i)>vec(i-1) && vec(i)>vec(i+1) && ~hasText
localMax = [localMax;i];
end
end
numMax = length(localMax);
% get distances between local max rows
distances = localMax(2:end) - localMax(1:end-1);
thresh = mean(distances); % the average distance will be our threshold
splitRows = []; % rows where we will split the image
cluster = localMax(1); % start a cluster with the first local max row
for i = 1:numMax-1;
if distances(i) < thresh % if rows are close together, keep them in a cluster
cluster = [cluster;localMax(i+1)];
else % average the cluster to get the row where we split the image
newSplit = round(mean(cluster));
splitRows = [ splitRows ; newSplit ];
cluster = localMax(i+1);
end
end
newSplit = round(mean(cluster)); % add the last cluster as well
splitRows = [ splitRows ; newSplit ];

Rolling window for averaging using MATLAB

I have the following code, pasted below. I would like to change it to only average the 10 most recently filtered images and not the entire group of filtered images. The line I think I need to change is: Yout(k,p,q) = (Yout(k,p,q) + (y.^2))/2;, but how do I do it?
j=1;
K = 1:3600;
window = zeros(1,10);
Yout = zeros(10,column,row);
figure;
y = 0; %# Preallocate memory for output
%Load one image
for i = 1:length(K)
disp(i)
str = int2str(i);
str1 = strcat(str,'.mat');
load(str1);
D{i}(:,:) = A(:,:);
%Go through the columns and rows
for p = 1:column
for q = 1:row
if(mean2(D{i}(p,q))==0)
x = 0;
else
if(i == 1)
meanvalue = mean2(D{i}(p,q));
end
%Calculate the temporal mean value based on previous ones.
meanvalue = (meanvalue+D{i}(p,q))/2;
x = double(D{i}(p,q)/meanvalue);
end
%Filtering for 10 bands, based on the previous state
for k = 1:10
[y, ZState{k}] = filter(bCoeff{k},aCoeff{k},x,ZState{k});
Yout(k,p,q) = (Yout(k,p,q) + (y.^2))/2;
end
end
end
% for k = 2:10
% subplot(5,2,k)
% subimage(Yout(k)*5000, [0 100]);
% colormap jet
% end
% pause(0.01);
end
disp('Done Loading...')
The best way to do this (in my opinion) would be to use a circular-buffer to store your images. In a circular-, or ring-buffer, the oldest data element in the array is overwritten by the newest element pushed in to the array. The basics of making such a structure are described in the short Mathworks video Implementing a simple circular buffer.
For each iteration of you main loop that deals with a single image, just load a new image into the circular-buffer and then use MATLAB's built in mean function to take the average efficiently.
If you need to apply a window function to the data, then make a temporary copy of the frames multiplied by the window function and take the average of the copy at each iteration of the loop.
The line
Yout(k,p,q) = (Yout(k,p,q) + (y.^2))/2;
calculates a kind of Moving Average for each of the 10 bands over all your images.
This line calculates a moving average of meanvalue over your images:
meanvalue=(meanvalue+D{i}(p,q))/2;
For both you will want to add a buffer structure that keeps only the last 10 images.
To simplify it, you can also just keep all in memory. Here is an example for Yout:
Change this line: (Add one dimension)
Yout = zeros(3600,10,column,row);
And change this:
for q = 1:row
[...]
%filtering for 10 bands, based on the previous state
for k = 1:10
[y, ZState{k}] = filter(bCoeff{k},aCoeff{k},x,ZState{k});
Yout(i,k,p,q) = y.^2;
end
YoutAvg = zeros(10,column,row);
start = max(0, i-10+1);
for avgImg = start:i
YoutAvg(k,p,q) = (YoutAvg(k,p,q) + Yout(avgImg,k,p,q))/2;
end
end
Then to display use
subimage(Yout(k)*5000, [0 100]);
You would do sth. similar for meanvalue