Let's suppose I have a vector x and 2 constants initialized as follows:
x = [ones(1,21) zeros(1,79)]; %step of 100 components
p = 2; q = 0;
Now, I want to build this matrix:
But in this case for example x(q-1) = x(-1) doesn't exist, so I want it to be 0, and I was wondering if there is a way to do it with the minimum lines of code. Note that the matrix can be written with the function toeplitz(), but I don't know how to replace nonexistent position of my vector x with zeros.
I hope someone can help me. Thank you for your answers.
You need to be careful about zero-based or one-based indexing.
In your question, you state that negative indices are invalid - in MATLAB the index 0 is also invalid. The below code assumes your x(q) is zero-based as described, but I do a +1 conversion. Be aware of this if q+p-1 is near numel(x).
x = [ones(1,21) zeros(1,79)]; %step of 100 components
p = 2; q = 0;
% Set up indexing matrix using implicit expansion (R2016b or newer)
m = ( q:-1:q-p+1 ) + ( 0:1:q+p-1 ).';
% Convert from 0-based to 1-based for MATLAB
m = m + 1;
% Set up output matrix, defaulting to zero
M = zeros( size( m ) );
% Put elements where 'm' is valid from 'x' into output 'M'
M( m > 0 ) = x( m( m > 0 ) );
The output is a (q+p) * p matrix.
I know this looks somehow not related to code errors and development but
I want to know if someone can understand these codes of
integral image and local binary pattern, and tell me how they affect the resulting histograms.
Before the use of integral image the output histogram is normal, but after applying the integral image method I found that most of the histogram changed to zeros. To clarify things, the expected benefit from the use of an integral image is to speed up the process of lbp method. In fact, I haven't seen this before because I'm trying it for the first time. Does anybody who knows about this may help me please?
These are the codes of every method:
Integral image
function [outimg] = integral( image )
[y,x] = size(image);
outimg = zeros(y+1,x+1);
disp(y);
for a = 1:y+1
for b = 1:x+1
rx = b-1;
ry = a-1;
while ry>=1
while rx>=1
outimg(a,b) = outimg(a,b)+image(ry,rx);
rx = rx-1;
end
rx = b-1;
ry = ry-1;
end
% outimg(a,b) = outimg(a,b)-image(a,b);
end
end
% outimg(1,1) = image(1,1);
disp('end loop');
end
CS-LBP
function h = CSLBP(I)
%% this function takes patch or image as input and return Histogram of
%% CSLBP operator.
h = zeros(1,16);
[y,x] = size(I);
T = 0.1; % threshold given by authors in their paper
for i = 2:y-1
for j = 2:x-1
% keeping I(j,i) as center we compute CSLBP
% N0 - N4
a = ((I(i,j+1) - I(i, j-1) > T ) * 2^0 );
b = ((I(i+1,j+1) - I(i-1, j-1) > T ) * 2^1 );
c = ((I(i+1,j) - I(i-1, j) > T ) * 2^2 );
d = ((I(i+1,j-1) - I(i - 1, j + 1) > T ) * 2^3 );
e = a+b+c+d;
h(e+1) = h(e+1) + 1;
end
end
end
Matlab has an inbuilt function for creating integral images, integralimage(). If you don't want to use the computer vision system toolbox you can achieve the same result by calling:
IntIm = cumsum(cumsum(double(I)),2);
Possibly adding padding if needed. You should check out that the image is not saturated, they do that sometimes. Calculating the cumulative sum goes to integers way above the range of uint8 and uint16 quickly, I even had it happen with a double once!
I am a bit confused and would greatly appreciate some help.
I have read many posts about finding neighboring pixels, with this being extremely helpful:
http://blogs.mathworks.com/steve/2008/02/25/neighbor-indexing-2/
However I have trouble applying it on a 4D matrix (A) with size(A)=[8 340 340 15]. It represents 8 groups of 3D images (15 slices each) of which I want to get the neighbors.
I am not sure which size to use in order to calculate the offsets. This is the code I tried, but I think it is not working because the offsets should be adapted for 4 dimensions? How can I do it without a loop?
%A is a 4D matrix with 0 or 1 values
Aidx = find(A);
% loop here?
[~,M,~,~] =size(A);
neighbor_offsets = [-1, M, 1, -M]';
neighbors_idx = bsxfun(#plus, Aidx', neighbor_offsets(:));
neighbors = B(neighbors_idx);
Thanks,
ziggy
Have you considered using convn?
msk = [0 1 0; 1 0 1; 0 1 0];
msk4d = permute( msk, [3 1 2 4] ); % make it 1-3-3-1 mask
neighbors_idx = find( convn( A, msk4d, 'same' ) > 0 );
You might find conndef useful for defining the basic msk in a general way.
Not sure if I've understood your question but what about this sort of approach:
if you matrix is 1D:
M = rand(10,1);
N = M(k-1:k+1); %//immediate neighbours of k
However this could error if k is at the boundary. This is easy to fix using max and min:
N = M(max(k-1,1):min(k+1,size(M,1))
Now lets add a dimenion:
M = rand(10,10);
N = M(max(k1-1,1):min(k1+1,size(M,1), max(k2-1,1):min(k2+1,size(M,2))
That was easy, all you had to do was repeat the same index making the minor change of using size(M,2) for the boundary (and also I changed k to k1 and k2, you might find using an array for k instead of separate k1 and k2 variables works better i.e. k(1) and k(2))
OK so now lets skip to 4 dimensions:
M = rand(10,10,10,10);
N = M(max(k(1)-1,1):min(k(1)+1,size(M,1)), ...
max(k(2)-1,1):min(k(2)+1,size(M,2)), ...
max(k(3)-1,1):min(k(3)+1,size(M,3)), ...
max(k(4)-1,1):min(k(4)+1,size(M,4))); %// Also you can replace all the `size(M,i)` with `end` if you like
I know you said you didn't want a loop, but what about a really short loop just to refactor a bit and also make it generalized:
n=ndims(M);
ind{n} = 0;
for dim = 1:n
ind{dim} = max(k(dim)-1,1):min(k(dim)+1,size(M,dim));
end
N = M(ind{:});
Here's how to get the neighbors along the second dimension
sz = size( A );
ndims = numel(sz); % number of dimensions
[d{1:ndims}] = ind2sub( sz, find( A ) );
alongD = 2; % work along this dim
np = d{alongD} + 1;
sel = np <= sz( alongD ); % discard neighbors that fall outside image boundary
nm = d{alongD} - 1;
sel = sel & nm > 0; % discard neighbors that fall outside image boundary
d = cellfun( #(x) x(sel), d, 'uni', 0 );
neighbors = cat( 1, ...
ind2sub( sz, d{1:alongD-1}, np(sel), d{alongD+1:end} ),...
ind2sub( sz, d{1:alongD-1}, nm(sel), d{alongD+1:end} ) );
I am trying to to subtract the background from a picture of an object to leave only the foreground object. I have found the RGB values of the background as 218 220 219 using imshow(). How can I use the RGB values with imsubtract()?
y = [218 220 219];
z = imsubtract(img,y);
Error using imsubtract (line 55)
X and Y must have the same size and class, or Y must be a scalar double.
You can use bsxfun to do that
z = bsxfun( #minus, img, permute( [218 220 219], [1 3 2] ) );
You need to pay attention to data type and range. If img is of type uint8 pixel values will be in range 0..255 but it will be difficult to subtract values as you'll see results underflowing at 0: uint8(4) - uint8(10) is 0...
Thus, you might want to convert img to double using im2double having pixel values in range 0..1. In that case you'll have to convert the "gray" vector [2218 220 219] to 0..1 range by dividing it by 255.
So, a more complete solution would be
z = bsxfun( #minus, im2double(img), permute( [218 220 219]/255, [1 3 2] ) );
The following ended up getting me closer to the answer I was looking for, although not without your guidance!
img = imread('IMG_0792.jpg');
img = im2double(img);
rows = numel(img(:,1,1));
columns = numel(img(1,:,1));
for i = 1:rows
for j = 1:columns
if ( ( img(i,j,1) > 0.75) && ( img(i,j,2) > 0.7) && ( img(i,j,3) > 0.7) )
img(i,j,1) = 1;
img(i,j,2) = 1;
img(i,j,3) = 1;
end
end
end
imshow(img);
I have 5 variables A,V,h,l and b which all stem from different distributions. I'd like to make a 1,000 equally distributed samples from each distribution by the method of latin hypercube sampling. Is this a realistic request, ie is it really better than simple random sampling? Do you have any references of how I can do this in matlab? This page suggests I would need to transform the sample somehow...
UPDATE #2: solution using built-in function of Statistics Toolbox
The basic question is whether you want your samples on a regular grid or not. If not, you could use the built-in function lhsdesign:
p = 1000 % Number of points
N = 5 % Number of dimensions
lb = [1 1 1 1 1]; % lower bounds for A,V,h,l and b
ub = [10 10 10 10 10]; % upper bounds for A,V,h,l and b
X = lhsdesign(p,N,'criterion','correlation');
D = bsxfun(#plus,lb,bsxfun(#times,X,(ub-lb)));
'criterion','correlation' would give you the desired "equal distribution".
D then contains the irregular coordinate-distribution for your parameters.
First I thought you we're looking for samples on a regular grid, which really seems to be a tough task. I tried to modify the approach above D = round(bsxfun...), but it won't give you satisfying results. So for this case I still provide my initial idea here:
The following solution is far from fast and elegant, but it's at least a solution.
% For at least 1000 samples M=6 divisions are necessary
M = 6;
N = 5;
% the perfect LHC distribution would have 1296 samples for M=6 divisions
% and 5 dimensions
counter_max = M^(N-1); %=1296
% pre-allocation
D = zeros(6,6,6,6,6);
counter = 0;
while counter < 1000
c = randi(6,1,5);
if ( sum( D( c(1) , c(2) , c(3) , c(4) , : )) < 1 && ...
sum( D( c(1) , c(2) , c(3) , : , c(5) )) < 1 && ...
sum( D( c(1) , c(2) , : , c(4) , c(5) )) < 1 && ...
sum( D( c(1) , : , c(3) , c(4) , c(5) )) < 1 && ...
sum( D( : , c(2) , c(3) , c(4) , c(5) )) < 1 )
D(c(1),c(2),c(3),c(4),c(5)) = 1;
X(counter,:) = c;
counter = counter+1;
end
end
X is finally containing the coordinates of all your samples.
As you see I used a while-loop with an underlying if-condition. You wish 1000 samples, that's a realistic number and can be done in a reasonable time. I actually would recommend you to use a number of samples as close as possible to the maximum of 1296. That could take you a pretty while. But as you create the resulting matrix just once and use it again and again, don't hesitate to run it 24hrs. You could also implement an interuption code as described here: In MatLab, is it possible to terminate a script, but save all its internal variables to workspace? and see how many samples you got until then. (I got 900 samples in 20min when I was testing)
UPDATE: Example to show limitations of method:
The following example shall illustrate, what the asker could be willing to do and what the result is actually supposed to look like. Because I'm also very interested in a good solution, mine is limited and cannot provide the "100% result".
Imagine a cube (N=3) with M=10 divisions.
M = 10;
N = 3;
counter_max = M^(N-1); %=100 maximum number of placeable samples
% pre-allocations
D = zeros(10,10,10);
counter = 0;
while counter < counter_max
c = randi(10,1,3);
% if condition checks if there is already a sample in the same row,
% coloumn or z-coordinate,
if ( sum( D( c(1) , c(2) , : )) < 1 && ...
sum( D( c(1) , : , c(3) )) < 1 && ...
sum( D( : , c(2) , c(3) )) < 1 )
%if not a new sample is generated
D(c(1),c(2),c(3)) = 1;
counter = counter+1;
X(counter,:) = c;
end
end
After about 10000 iterations one gets the following distribution with 85 of 100 possible placed samples:
where the color indicates the normalized distance to the closest neighbor. For most of the points it's fine (1), but as there are 15 missing samples, some points are more distant from others.
The problem is: I doubt that it's possible to get all 100 samples in a reasonable time. When one plots the generated samples over the number of iterations you get:
...so the desired result seems hardly obtainable.
Please see this answer more as an encouragement than a solution.
By combining 1-D latin hypercube samples (LHS), you can make a full set of LHS for regular grid in higher order dimension. For example, imagine 3X3 LHS (ie 2-D and 3 divisions). First, you just make 1-D LHS for regular grid. (1,0,0), (0, 1, 0), (0, 0, 1) for 1-D. And then, combine the 1-D LHS to make 2-D LHS.
1, 0, 0
0, 1, 0
0, 0, 1
or
0, 1, 0
1, 0, 0
0, 0, 1
... etc.
LHS for 3-D can also be created using the same method(by combining 2-D LHS).
There are 12 possible LHS for 3X3. Generally, the number of possible LHS is N x ((M-1)!)^(M-1).
(N=divisions, M=dimensions)
The following code shows LHS for 3-D and 10 divisions.
This code generates only one LHS.
result is random.
it takes 0.001288 sec for 100% result
clear;
clc;
M = 3; % dimension
N = 10; % division
Sel2 = ':,';
stop = 0;
P_matrix = repmat([num2str(N),','],1,M);
P_matrix = P_matrix(1:end-1);
eval(['P = zeros(', P_matrix, ');']);
P(1,1) = 1;
tic
while stop == 0
for i = 1 : M-1
for j = 2:N
if i == 1
P(end , j, 1) = P(1 , j-1, 1);
P(1:end-1, j, 1) = P(2:end, j-1, 1);
else
Sel_2 = repmat(Sel2,1,i-1);
Sel_2 = Sel_2(1:end-1);
eval(['P(', Sel_2, ',end , j, 1) = P(', Sel_2 , ', 1 , j-1, 1);']);
eval(['P(', Sel_2, ',1:end-1 , j, 1) = P(', Sel_2 , ', 2:end, j-1, 1);']);
end
end
if i == 1
P(:,:,1) = P(randperm(N),:,1);
elseif i <M-1
Sel_2 = repmat(Sel2,1,i);
Sel_2 = Sel_2(1:end-1);
eval(['P(',Sel_2,',:,1) = P(',Sel_2,',randperm(N),1);']);
else
Sel_2 = repmat(Sel2,1,i);
Sel_2 = Sel_2(1:end-1);
eval(['P(',Sel_2,',:) = P(',Sel_2,',randperm(N));']);
end
end
% you can add stop condition
stop = 1;
end
toc
[x, y, z] = ind2sub(size(P),find(P == 1));
scatter3(x,y,z);
xlabel('X');
ylabel('Y');
zlabel('Z');
Result
This code gives the same result as the accepted one in this discussion.
Check it out!
n=1000; p=5;
distr=lhsdesign(n,p); %creates LHS of n samples on each of your p dimensions
% Then, you can choose any inverted distribution. in this case it is the Discrete Uniform Distribution
Parameters=[unidinv(distr(:,1),UB1) unidinv(distr(:,2),UB2) ...
unidinv(distr(:,3),UB3) unidinv(distr(:,4),UB4) ...
unidinv(distr(:,5),UB5) ];
%At the end, you'll do a simple work of indexing.