Using custom functions in blockproc in Matlab - matlab

I wanted to use my own (custom) function in blockproc function. But I am not able to figure out how to actually incorporate this. I am new to MATLAB.
In this function I am trying to embed info (the bits of LR_seq) into the block. I am selecting a pair of pixels at a time in the block and trying to embed my info into it.
This is the code of my function:
function dataencode(block_struct,LR_seq)
LR_seq = vec2mat(LR_seq,2,4);%changing it into a 2,4 mat to make it fit into the for loop
LR_mat = zeros(4,4);%adding zero columns in between to convert it into 4,4 mat to fit into the for loop
LR_mat(:,1:2:end) = LR_seq;
for r = 1 : 4
for c = [1 3]
x = uint16(block_struct.data(r,c)) ;
y = uint16(block_struct.data(r,c+1));
x1 = de2bi(x,12); y1 = de2bi(y,12);
if(~(2*x - y == 1) | ~(2*y - x == 1) | ~(2*x - y == 255) | ~(2*y - x == 255))
if((x1(1) == 0) & (y1(1) == 0)) %because in maltab lsb comes first
xt = (2*x - y) ; yt = (2*y - x);
xt_bin = de2bi(xt,12); xt_bin(1) = 1; xtd = bi2de(xt_bin);block_struct.data(r,c) =xtd;
yt_bin = de2bi(yt,12) ; yt_bin(1) = LR_mat(r,c); ytd = bi2de(yt_bin); block_struct.data(r,c+1) = ytd;
elseif((x1(1) == 1) | (y1(1) == 1))
x1(1) = 0 ; xtd = bi2de(x1) ; block.data(r,c) = xtd;
y1(1) = LR_mat(r,c); ytd = bi2de(y1) ; block_struct.data(r,c+1) = ytd;
end
else
x1(1) = 0; xtd = bi2de(x1) ; block.data(r,c) = xtd;
ytd = bi2de(y1); block_struct.data(r,c+1) = ytd;
end
end
end
end
M is a RGB 256x256 image in which I want to embed the sequence of bits LR_seq.
I am trying to call this function in the command window but it is giving me a empty matrix, please help out. This is my code for calling the function
for ii = 1 : 8 : size(LR_seq)
myfunc = #(block_struct) dataencode(block_struct,LR_seq(ii : ii+7));
U_im_new = blockproc(M,[4 4],myfunc)
end

dataencode should take a block_struct in parameter. But your function myfunc_red calls the encode function with the data of the block_struct.
You may prefer to do this:
myfunc = #(block_struct) dataencode(block_struct,LR_seq(1 : 8));
U_im_r = blockproc(M(:,:,1),[4 4],myfunc);

Related

Calculate a confusion matrix given two matrix matlab

I have two Xval(Predicted values) and Sv(validation test) matrices, one with the classifier output data and the other with the validation data for the same samples. Each column represents the predicted value, eg [0 0 1 0 0 0 0 0 0 0] represents digit 3 (1 in the digit that is). I would like to know if it is possible to calculate the confusion matrix in a vectorized way or with a built in function, the sizes of both matrices are 12000x10. The code who generates both matrices are this
load data;
load test;
[N, m] = size(X);
X = [ones(N, 1) X];
[Nt, mt] = size(Xt);
Xt = [ones(Nt, 1) Xt];
new_order = randperm(N);
X = X(new_order,: );
S = S(new_order,: );
part = 0.8;
Xtr = X(1: (part * N),: );
Xv = X((part * N + 1): N,: );
Str = S(1: (part * N),: );
Sv = S((part * N + 1): N,: );
v_c = [];
v_tx_acerto = [];
tx_acerto_max = 0;
c = 250;
w = (X'*X+c*eye(m+1))\X' * S;
Xval = Xv*w;
for i=1:12000
aux = Xval(i,:);
aux(aux == max(aux)) = 1;
aux(aux<1) = 0;
Xval(i,:) = aux;
end
There are build-in functions confusionmat or plotconfusion. But if you want to have full control, you can just write a simple function yourself, e.g:
function [CMat_rel,CMat_abs] = ConfusionMatrix(Cprd,Cact)
Cprd_uq = unique(Cprd);
Cact_uq = unique(Cact);
NumPrd = length(Cprd_uq);
NumAct = length(Cact_uq);
% assert(NumPrd == NumAct)
% allocate memory
CMat_abs = NaN(NumPrd,NumAct);
CMat_rel = NaN(NumPrd,NumAct);
for j = 1:NumAct
lgAct = Cact == Cact_uq(j);
SumAct = sum(lgAct);
for i = 1:NumAct
lgPrd = Cprd == Cact_uq(i);
Num = sum( lgPrd(lgAct) == true );
CMat_abs(i,j) = Num;
CMat_rel(i,j) = Num/SumAct;
end
end
end

My approximate entropy script for MATLAB isn't working

This is my Approximate entropy Calculator in MATLAB. https://en.wikipedia.org/wiki/Approximate_entropy
I'm not sure why it isn't working. It's returning a negative value.Can anyone help me with this? R1 being the data.
FindSize = size(R1);
N = FindSize(1);
% N = input ('insert number of data values');
%if you want to put your own N in, take away the % from the line above
and
%insert the % before the N = FindSize(1)
%m = input ('insert m: integer representing length of data, embedding
dimension ');
m = 2;
%r = input ('insert r: positive real number for filtering, threshold
');
r = 0.2*std(R1);
for x1= R1(1:N-m+1,1)
D1 = pdist2(x1,x1);
C11 = (D1 <= r)/(N-m+1);
c1 = C11(1);
end
for i1 = 1:N-m+1
s1 = sum(log(c1));
end
phi1 = (s1/(N-m+1));
for x2= R1(1:N-m+2,1)
D2 = pdist2(x2,x2);
C21 = (D2 <= r)/(N-m+2);
c2 = C21(1);
end
for i2 = 1:N-m+2
s2 = sum(log(c2));
end
phi2 = (s2/(N-m+2));
Ap = phi1 - phi2;
Apen = Ap(1)
Following the documentation provided by the Wikipedia article, I developed this small function that calculates the approximate entropy:
function res = approximate_entropy(U,m,r)
N = numel(U);
res = zeros(1,2);
for i = [1 2]
off = m + i - 1;
off_N = N - off;
off_N1 = off_N + 1;
x = zeros(off_N1,off);
for j = 1:off
x(:,j) = U(j:off_N+j);
end
C = zeros(off_N1,1);
for j = 1:off_N1
dist = abs(x - repmat(x(j,:),off_N1,1));
C(j) = sum(~any((dist > r),2)) / off_N1;
end
res(i) = sum(log(C)) / off_N1;
end
res = res(1) - res(2);
end
I first tried to replicate the computation shown the article, and the result I obtain matches the result shown in the example:
U = repmat([85 80 89],1,17);
approximate_entropy(U,2,3)
ans =
-1.09965411068114e-05
Then I created another example that shows a case in which approximate entropy produces a meaningful result (the entropy of the first sample is always less than the entropy of the second one):
% starting variables...
s1 = repmat([10 20],1,10);
s1_m = mean(s1);
s1_s = std(s1);
s2_m = 0;
s2_s = 0;
% datasample will not always return a perfect M and S match
% so let's repeat this until equality is achieved...
while ((s1_m ~= s2_m) && (s1_s ~= s2_s))
s2 = datasample([10 20],20,'Replace',true,'Weights',[0.5 0.5]);
s2_m = mean(s2);
s2_s = std(s2);
end
m = 2;
r = 3;
ae1 = approximate_entropy(s1,m,r)
ae2 = approximate_entropy(s2,m,r)
ae1 =
0.00138568170752751
ae2 =
0.680090884817465
Finally, I tried with your sample data:
fid = fopen('O1.txt','r');
U = cell2mat(textscan(fid,'%f'));
fclose(fid);
m = 2;
r = 0.2 * std(U);
approximate_entropy(U,m,r)
ans =
1.08567461184858

Weird phenomenon when converting RGB to HSV manually in Matlab

I have written a small Matlab funcion which takes an image in RGB and converts it to HSV according to the conversion formulas found here.
The problem is that when I apply this to a color spectrum there is a cut in the spectrum and some values are wrong, see images (to make the comparison easier I have used the internal hsv2rgb() function to convert back to RGB. This does not happen with Matlabs own function rgb2hsv() but I can not find what I have done wrong.
This is my function
function [ I_HSV ] = RGB2HSV( I_RGB )
%UNTITLED3 Summary of this function goes here
% Detailed explanation goes here
[MAX, ind] = max(I_RGB,[],3);
if max(max(MAX)) > 1
I_r = I_RGB(:,:,1)/255;
I_g = I_RGB(:,:,2)/255;
I_b = I_RGB(:,:,3)/255;
MAX = max(cat(3,I_r, I_g, I_b),[],3);
else
I_r = I_RGB(:,:,1);
I_g = I_RGB(:,:,2);
I_b = I_RGB(:,:,3);
end
MIN = min(cat(3,I_r, I_g, I_b),[],3);
d = MAX - MIN;
I_V = MAX;
I_S = (MAX - MIN) ./ MAX;
I_H = zeros(size(I_V));
a = 1/6*mod(((I_g - I_b) ./ d),1);
b = 1/6*(I_b - I_r) ./ d + 1/3;
c = 1/6*(I_r - I_g) ./ d + 2/3;
H = cat(3, a, b, c);
for m=1:size(H,1);
for n=1:size(H,2);
if d(m,n) == 0
I_H(m,n) = 0;
else
I_H(m,n) = H(m,n,ind(m,n));
end
end
end
I_HSV = cat(3,I_H,I_S,I_V);
end
Original spectrum
Converted spectrum
The error was in my simplification of the calculations of a, b, and c. Changing it to the following solved the problem.
function [ I_HSV ] = RGB2HSV( I_RGB )
%UNTITLED3 Summary of this function goes here
% Detailed explanation goes here
[MAX, ind] = max(I_RGB,[],3);
if max(max(MAX)) > 1
I_r = I_RGB(:,:,1)/255;
I_g = I_RGB(:,:,2)/255;
I_b = I_RGB(:,:,3)/255;
MAX = max(cat(3,I_r, I_g, I_b),[],3);
else
I_r = I_RGB(:,:,1);
I_g = I_RGB(:,:,2);
I_b = I_RGB(:,:,3);
end
MIN = min(cat(3,I_r, I_g, I_b),[],3);
D = MAX - MIN;
I_V = MAX;
I_S = D ./ MAX;
I_H = zeros(size(I_V));
a = 1/6*mod(((I_g - I_b) ./ D),6);
b = 1/6*((I_b - I_r) ./ D + 2);
c = 1/6*((I_r - I_g) ./ D + 4);
H = cat(3, a, b, c);
for m=1:size(H,1);
for n=1:size(H,2);
if D(m,n) == 0
I_H(m,n) = 0;
else
I_H(m,n) = H(m,n,ind(m,n));
end
if MAX(m,n) == 0
S(m,n) = 0;
end
end
end
I_HSV = cat(3,I_H,I_S,I_V);
end

How to reduce the time consumed by the for loop?

I am trying to implement a simple pixel level center-surround image enhancement. Center-surround technique makes use of statistics between the center pixel of the window and the surrounding neighborhood as a means to decide what enhancement needs to be done. In the code given below I have compared the center pixel with average of the surrounding information and based on that I switch between two cases to enhance the contrast. The code that I have written is as follows:
im = normalize8(im,1); %to set the range of pixel from 0-255
s1 = floor(K1/2); %K1 is the size of the window for surround
M = 1000; %is a constant value
out1 = padarray(im,[s1,s1],'symmetric');
out1 = CE(out1,s1,M);
out = (out1(s1+1:end-s1,s1+1:end-s1));
out = normalize8(out,0); %to set the range of pixel from 0-1
function [out] = CE(out,s,M)
B = 255;
out1 = out;
for i = s+1 : size(out,1) - s
for j = s+1 : size(out,2) - s
temp = out(i-s:i+s,j-s:j+s);
Yij = out1(i,j);
Sij = (1/(2*s+1)^2)*sum(sum(temp));
if (Yij>=Sij)
Aij = A(Yij-Sij,M);
out1(i,j) = ((B + Aij)*Yij)/(Aij+Yij);
else
Aij = A(Sij-Yij,M);
out1(i,j) = (Aij*Yij)/(Aij+B-Yij);
end
end
end
out = out1;
function [Ax] = A(x,M)
if x == 0
Ax = M;
else
Ax = M/x;
end
The code does the following things:
1) Normalize the image to 0-255 range and pad it with additional elements to perform windowing operation.
2) Calls the function CE.
3) In the function CE obtain the windowed image(temp).
4) Find the average of the window (Sij).
5) Compare the center of the window (Yij) with the average value (Sij).
6) Based on the result of comparison perform one of the two enhancement operation.
7) Finally set the range back to 0-1.
I have to run this for multiple window size (K1,K2,K3, etc.) and the images are of size 1728*2034. When the window size is selected as 100, the time consumed is very high.
Can I use vectorization at some stage to reduce the time for loops?
The profiler result (for window size 21) is as follows:
The profiler result (for window size 100) is as follows:
I have changed the code of my function and have written it without the sub-function. The code is as follows:
function [out] = CE(out,s,M)
B = 255;
Aij = zeros(1,2);
out1 = out;
n_factor = (1/(2*s+1)^2);
for i = s+1 : size(out,1) - s
for j = s+1 : size(out,2) - s
temp = out(i-s:i+s,j-s:j+s);
Yij = out1(i,j);
Sij = n_factor*sum(sum(temp));
if Yij-Sij == 0
Aij(1) = M;
Aij(2) = M;
else
Aij(1) = M/(Yij-Sij);
Aij(2) = M/(Sij-Yij);
end
if (Yij>=Sij)
out1(i,j) = ((B + Aij(1))*Yij)/(Aij(1)+Yij);
else
out1(i,j) = (Aij(2)*Yij)/(Aij(2)+B-Yij);
end
end
end
out = out1;
There is a slight improvement in the speed from 93 sec to 88 sec. Suggestions for any other improvements to my code are welcomed.
I have tried to incorporate the suggestions given to replace sliding window with convolution and then vectorize the rest of it. The code below is my implementation and I'm not getting the result expected.
function [out_im] = CE_conv(im,s,M)
B = 255;
temp = ones(2*s,2*s);
temp = temp ./ numel(temp);
out1 = conv2(im,temp,'same');
out_im = im;
Aij = im-out1; %same as Yij-Sij
Aij1 = out1-im; %same as Sij-Yij
Mij = Aij;
Mij(Aij>0) = M./Aij(Aij>0); % if Yij>Sij Mij = M/Yij-Sij;
Mij(Aij<0) = M./Aij1(Aij<0); % if Yij<Sij Mij = M/Sij-Yij;
Mij(Aij==0) = M; % if Yij-Sij == 0 Mij = M;
out_im(Aij>=0) = ((B + Mij(Aij>=0)).*im(Aij>=0))./(Mij(Aij>=0)+im(Aij>=0));
out_im(Aij<0) = (Mij(Aij<0).*im(Aij<0))./ (Mij(Aij<0)+B-im(Aij<0));
I am not able to figure out where I'm going wrong.
A detailed explanation of what I'm trying to implement is given in the following paper:
Vonikakis, Vassilios, and Ioannis Andreadis. "Multi-scale image contrast enhancement." In Control, Automation, Robotics and Vision, 2008. ICARCV 2008. 10th International Conference on, pp. 856-861. IEEE, 2008.
I've tried to see if I could get those times down by processing with colfiltand nlfilter, since both are usually much faster than for-loops for sliding window image processing.
Both worked fine for relatively small windows. For an image of 2048x2048 pixels and a window of 10x10, the solution with colfilt takes about 5 seconds (on my personal computer). With a window of 21x21 the time jumped to 27 seconds, but that is still a relative improvement on the times displayed on the question. Unfortunately I don't have enough memory to colfilt using windows of 100x100, but the solution with nlfilter works, though taking about 120 seconds.
Here the code
Solution with colfilt:
function outval = enhancematrix(inputmatrix,M,B)
%Inputmatrix is a 2D matrix or column vector, outval is a 1D row vector.
% If inputmatrix is made of integers...
inputmatrix = double(inputmatrix);
%1. Compute S and Y
normFactor = 1 / (size(inputmatrix,1) + 1).^2; %Size of column.
S = normFactor*sum(inputmatrix,1); % Sum over the columns.
Y = inputmatrix(ceil(size(inputmatrix,1)/2),:); % Center row.
% So far we have all S and Y, one value per column.
%2. Compute A(abs(Y-S))
A = Afunc(abs(S-Y),M);
% And all A: one value per column.
%3. The tricky part. If Y(i)-S(i) > 0 do something.
doPositive = (Y > S);
doNegative = ~doPositive;
outval = zeros(1,size(inputmatrix,2));
outval(doPositive) = (B + A(doPositive) .* Y(doPositive)) ./ (A(doPositive) + Y(doPositive));
outval(doNegative) = (A(doNegative) .* Y(doNegative)) ./ (A(doNegative) + B - Y(doNegative));
end
function out = Afunc(x,M)
% Input x is a row vector. Output is another row vector.
out = x;
out(x == 0) = M;
out(x ~= 0) = M./x(x ~= 0);
end
And to call it, simply do:
M = 1000; B = 255; enhancenow = #(x) enhancematrix(x,M,B);
w = 21 % windowsize
result = colfilt(inputImage,[w w],'sliding',enhancenow);
Solution with nlfilter:
function outval = enhanceimagecontrast(neighbourhood,M,B)
%1. Compute S and Y
normFactor = 1 / (length(neighbourhood) + 1).^2;
S = normFactor*sum(neighbourhood(:));
Y = neighbourhood(ceil(size(neighbourhood,1)/2),ceil(size(neighbourhood,2)/2));
%2. Compute A(abs(Y-S))
test = (Y>=S);
A = Afunc(abs(Y-S),M);
%3. Return outval
if test
outval = ((B + A) * Y) / (A + Y);
else
outval = (A * Y) / (A + B - Y);
end
function aval = Afunc(x,M)
if (x == 0)
aval = M;
else
aval = M/x;
end
And to call it, simply do:
M = 1000; B = 255; enhancenow = #(x) enhanceimagecontrast(x,M,B);
w = 21 % windowsize
result = nlfilter(inputImage,[w w], enhancenow);
I didn't spend much time checking that everything is 100% correct, but I did see some nice contrast enhancement (hair looks particularly nice).
This answer is the implementation that was suggested by Peter. I debugged the implementation and presenting the final working version of the fast implementation.
function [out_im] = CE_conv(im,s,M)
B = 255;
im = ( im - min(im(:)) ) ./ ( max(im(:)) - min(im(:)) )*255;
h = ones(s,s)./(s*s);
out1 = imfilter(im,h,'conv');
out_im = im;
Aij = im-out1; %same as Yij-Sij
Aij1 = out1-im; %same as Sij-Yij
Mij = Aij;
Mij(Aij>0) = M./Aij(Aij>0); % if Yij>Sij Mij = M/(Yij-Sij);
Mij(Aij<0) = M./Aij1(Aij<0); % if Yij<Sij Mij = M/(Sij-Yij);
Mij(Aij==0) = M; % if Yij-Sij == 0 Mij = M;
out_im(Aij>=0) = ((B + Mij(Aij>=0)).*im(Aij>=0))./(Mij(Aij>=0)+im(Aij>=0));
out_im(Aij<0) = (Mij(Aij<0).*im(Aij<0))./ (Mij(Aij<0)+B-im(Aij<0));
out_im = ( out_im - min(out_im(:)) ) ./ ( max(out_im(:)) - min(out_im(:)) );
To call this use the following code
I = imread('pout.tif');
w_size = 51;
M = 4000;
output = CE_conv(I(:,:,1),w_size,M);
The output for the 'pout.tif' image is given below
The execution time for Bigger image and with 100*100 block size is around 5 secs with this implementation.

How to vectorize a matlab script converting a 3d matrix to a single vector?

I am writing a graphical representation of numerical stability of differential operators and I am having trouble removing a nested for loop. The code loops through all entries in the X,Y, plane and calculates the stability value for each point. This is done by finding the roots of a polynomial of a size dependent on an input variable (length of input vector results in a polynomial 3d matrix of size(m,n,(lenght of input vector)). The main nested for loop is as follows.
for m = 1:length(z2)
for n = 1:length(z1)
pointpoly(1,:) = p(m,n,:);
r = roots(pointpoly);
if isempty(r),r=1e10;end
z(m,n) = max(abs(r));
end
end
The full code of an example numerical method (Trapezoidal Rule) is as follows. Any and all help is appreciated.
alpha = [-1 1];
beta = [.5 .5];
Wind = 2;
Wsize = 500;
if numel(Wind) == 1
Wind(4) = Wind(1);
Wind(3) = -Wind(1);
Wind(2) = Wind(4);
Wind(1) = Wind(3);
end
if numel(Wsize) == 1
Wsize(2) = Wsize;
end
z1 = linspace(Wind(1),Wind(2),Wsize(1));
z2 = linspace(Wind(3),Wind(4),Wsize(2));
[Z1,Z2] = meshgrid(z1,z2);
z = Z1+1i*Z2;
p = zeros(Wsize(2),Wsize(1),length(alpha));
for n = length(alpha):-1:1
p(:,:,(length(alpha)-n+1)) = alpha(n)-z*beta(n);
end
for m = 1:length(z2)
for n = 1:length(z1)
pointpoly(1,:) = p(m,n,:);
r = roots(pointpoly);
if isempty(r),r=1e10;end
z(m,n) = max(abs(r));
end
end
figure()
surf(Z1,Z2,z,'EdgeColor','None');
caxis([0 2])
cmap = jet(255);
cmap((127:129),:) = 0;
colormap(cmap)
view(2);
title(['Alpha Values (',num2str(alpha),') Beta Values (',num2str(beta),')'])
EDIT::
I was able to remove one of the for loops using the reshape command. So;
for m = 1:length(z2)
for n = 1:length(z1)
pointpoly(1,:) = p(m,n,:);
r = roots(pointpoly);
if isempty(r),r=1e10;end
z(m,n) = max(abs(r));
end
end
has now become
gg = reshape(p,[numel(p)/length(alpha) length(alpha)]);
r = zeros(numel(p)/length(alpha),1);
for n = 1:numel(p)/length(alpha)
temp = roots(gg(n,:));
if isempty(temp),temp = 0;end
r(n,1) = max(abs(temp));
end
z = reshape(r,[Wsize(2),Wsize(1)]);
This might be one for loop, but I am still going through the same number of elements. Is there a way to use the roots command on all of my rows at the same time?