Aligning RGB Channels (using SSD) of the given image to produce colored and properly aligned and clear image - matlab

The problem statement is - To search over a window of possible displacements (You will search [-10,10] pixels), score each one using some image matching metric, and take the displacement with the best score. The simplest one is the Sum of Squared Differences (SSD) distance, which simply subtracts one image region from the other and evaluates the sum of the squared values in each pixel. You need to do SSD based calculations on image regions which are of double type.
As R,G,B channels are highly correlated to each other, SSD metric is very likely to work. Your task is to hold the G channel as the reference and move around R and B channels over it and keep track of the SSD value for the 51x51 image regions at the center of the channels. For each channel, you will find the (x,y) displacement vector that gives the minimum SSD value.
The program should divide the image into three equal parts. The first image is Blue Channel, the second one is Green channel and the last one is Red channel.
You have to name your variables as below
Blue channel Image - B
Green channel Image - G
Red channel Image - R
Reference Green Channel center region (51x51) - ref_img_region (center of this region coincides with the center of image and indexes are always integers)
Final aligned image - ColorImg_aligned
Given input image-
Required output image-
I have done this so far and getting the almost same output as required but the compiler is showing incorrect value for ColorImg_aligned.
What's wrong with my code. I am new to Matlab. Sorry if the code is not efficient.
%Read the image
img = imread('course1image.jpg');
[r,c] = size(img);
B = img(1:r/3,:);
G = img((r/3)+1:(2*r/3),:);
R = img((2*r/3)+1:r,:);
ref_img_region = G;
[rg,cg] = size(ref_img_region);
ref_img_region = ref_img_region(ceil((rg-50)/2) :ceil((rg-50)/2) + 50,ceil((cg-50)/2) :ceil((cg-50)/2) + 50);
%disp(size(ref_img_region));
ref_img_region = double(ref_img_region);
% Naive way
% ColorImg_aligned = cat(3,R,G,B);
% imshow(ColorImg_aligned);
% SSD way
nR = align(G,R);
nB = align(G,B);
ColorImg_aligned = cat(3,nR,G,nB);
imshow(ColorImg_aligned);
function aligned = align(green,red)
[red_row,red_col] = size(red);
[green_row,green_col] = size(green);
% checking SSD for cropped part of the images for faster calculation
cropped_red = red(ceil((red_row-50)/2) : ceil((red_row-50)/2) + 50,ceil((red_col-50)/2) :ceil((red_col-50)/2) + 50);
cropped_green = green(ceil((green_row-50)/2) : ceil((green_row-50)/2) + 50,ceil((green_col-50)/2) :ceil((green_col-50)/2) + 50);
MiN = 9999999999;
r_index = 0;
r_dim = 1;
for i = -10:10
for j = 1:2
ssd = SSD(cropped_green,circshift(cropped_red,i,j));
if ssd < MiN
MiN = ssd;
r_index = i;
r_dim = j;
end
end
end
aligned = circshift(red,r_index,r_dim);
end
function ssd = SSD(a1,a2)
x = double(a1)-double(a2);
ssd = sum(x(:).^2);
end

Finally I was able to pass the assignment.
I just changed Y = circshift(A,K,dim)version of circshift to Y = circshift(A,[i,j])I'm still doing the same thing but the compiler accepted the answer this time.
Anybody having thoughts about why this happened?
After modification the code looks like this.
%Read the image
img = imread('course1image.jpg');
[r,c] = size(img);
B = img(1:r/3,:);
G = img((r/3)+1:(2*r/3),:);
R = img((2*r/3)+1:r,:);
ref_img_region = G;
[rg,cg] = size(ref_img_region);
ref_img_region = ref_img_region(ceil((rg-50)/2) :ceil((rg-50)/2) + 50,ceil((cg-50)/2) :ceil((cg-50)/2) + 50);
%disp(size(ref_img_region));
ref_img_region = double(ref_img_region);
% Naive way
% ColorImg_aligned = cat(3,R,G,B);
% imshow(ColorImg_aligned);
% SSD way
nR = align(G,R);
nB = align(G,B);
ColorImg_aligned = cat(3,nR,G,nB);
imshow(ColorImg_aligned);
function aligned = align(green,red)
[red_row,red_col] = size(red);
[green_row,green_col] = size(green);
% checking SSD for cropped part of the images for faster calculation
cropped_red = red(ceil((red_row-50)/2) : ceil((red_row-50)/2) + 50,ceil((red_col-50)/2) :ceil((red_col-50)/2) + 50);
cropped_green = green(ceil((green_row-50)/2) : ceil((green_row-50)/2) + 50,ceil((green_col-50)/2) :ceil((green_col-50)/2) + 50);
MiN = 9999999999;
r_index = 0;
r_dim = 1;
% Modifications
for i = -10:10
for j = -10:10
ssd =
SSD(cropped_green,circshift(cropped_red,[i,j])); %circshift(A,[i,j])
if ssd < MiN
MiN = ssd;
r_index = i;
r_dim = j;
end
end
end
aligned = circshift(red,[r_index,r_dim]);
end
function ssd = SSD(a1,a2)
x = double(a1)-double(a2);
ssd = sum(x(:).^2);
end
Output

Related

How to apply matched filter over surface of image instead of lines on 2d matrix: MATLAB

I have a 2d matrix and want to implement a matched filter on this matrix(image) of size 360x360
a=360x360
I tried to read about the matched filter but still unsure about it?
MY ATTEMPT(But this is not desired as this makes matched filter over lines and not on my image)
img=a;
s = 1.5; %sigma
L = 7;
theta = 0:15:165;
out = zeros(size(img));
m = max(ceil(3*s),(L-1)/2);
[x,y] = meshgrid(-m:m,-m:m);
for t = theta
t = t / 180 * pi;
u = cos(t)*x - sin(t)*y;
v = sin(t)*x + cos(t)*y;
N = (abs(u) <= 3*s) & (abs(v) <= L/2);
k = exp(-u.^2/(2*s.^2));
k = k - mean(k(N));
k(~N) = 0;
res = conv2(img,k,'same');
out = max(out,res);
end
imagesc(out)
My expectation was to get a more clear and bright image but I didn't get that
My expectation was to get a more clear and bright image of this coin but I didn't get that
I want to reduce noise and get a better image
I want to reduce noise and apply over image surface, not on lines get a better image

weighted CDF formula always returns 1

I am reading this paper for enhancing image quality.
my problem is that when I am calculating weighted CDF, I always get 1 as output.
here is the sequence of formulas:
which gamma is defined like this:
which Cw is the weighted CDF:
which I think my main problem would be here.
but to be more clear I will add the rest of the formulas too.
corresponding Weighted Histogram Distribution function is:
and Alpha=C(i) which:
which h_c(i) is clipped histogram , and M is the total intensity levels ( which I'm not sure what is the M, I assumed since sum of Pi should be 1 so it must be sum of the hc_i )
and this is how it is clipping the histogram :
and the clipping limit is calculated with this formula:
here is my code:
sample_img = imread('my image path');
sample_img = im2double(sample_img);
L = 256 % The magnitude of each and every color channel is confined within the range [0 , L-1]
redChannel = sample_img(:,:,1);
greenChannel = sample_img(:,:,2);
blueChannel = sample_img(:,:,3);
max_blue = max(max(blueChannel));
max_green = max(max(greenChannel));
max_red = max(max(redChannel));
min_blue = min(min(blueChannel));
min_green = min(min(greenChannel));
min_red = min(min(redChannel));
bn = blueChannel - min_blue;
rn = redChannel - min_red;
gn = greenChannel - min_green;
max_bn = max(max(bn));
max_rn = max(max(rn));
max_gn = max(max(gn));
b_stretched = bn/max_bn;
r_stretched = rn/max_rn;
g_stretched = gn/max_gn;
% Recombine separate color channels into an RGB image.
rgb_stretched_Image = cat(3, r_stretched, g_stretched, b_stretched);
% Convert RGB to HSI
hsi_image = rgb2hsi(rgb_stretched_Image);
intensity = hsi_image(:, :, 3);
figure()
[counts , binLocations] = imhist(intensity);
imhist(intensity);
hist = counts;
% the clipping limit is computed based on the mean value of the
Tc = mean(hist);
% histogram clipping
length_hist = length(hist);
clipped_hist = zeros(1,length_hist);
for hist_id = 1:length_hist
if hist(hist_id)<Tc
disp('<Tc')
disp(hist(hist_id));
clipped_hist(hist_id) = hist(hist_id);
continue
end
disp('>Tc')
clipped_hist(hist_id) = Tc;
end
% the corresponding PDF (p(i))
% this is where I just used sum(clipped_hist) instead of M
Pi = clipped_hist / sum(clipped_hist);
%CDF
Ci = sum(Pi(1:L));
Alpha = Ci;
%Weighted Histogram Distribution function
Pmin = min(Pi);
Pmax = max(Pi);
Pwi = Pmax * power((Pi-Pmin)/(Pmax-Pmin),Alpha);
%weighted PDF sum
intensity_max = max(max(intensity*L));
Sum_Pwi = sum(Pwi(1:intensity_max));
% weighted CDF
Cwi = sum(Pwi(1:intensity_max)/Sum_Pwi);
%gamma
gamma = 1 - Cwi;
%Transformed pixel intensity
tpi = round(power(intensity/intensity_max,gamma));
since as I said the CDF output is always 1 , the enhanced image is always a white image. and as I see this formula, it must always have 1 as it's output. Am I missing something here ?
and am I right with the M value ?

Im trying to hide an image inside another using LSB but the resulting image is Coming out with high contrast

hello i wrote a simple code using a simple algorithm to understand steganography better , using LSB i hide the pixel values of one image into another, the key in this case represents the amount of steps (pixels) the loop will take to hide consecutive pixels from the secret cat image into the tree image.
I know it's not very secure but that's not the point.
My code to hide image:
% Function that accepts dir for secret image and dir for image to hide it in
% it writes an image that contains the secret image.
% it return an array containing the dimensions of the secret image
% because we need them in the revealing function
function [dim] = hideMyimg(secret,image,Key)
img = imread(image);
egg = imread(secret);
% Setting the least significant bits to zero
img = img - mod(img,4);
%checking if the secret fits into the hiding place
img = check(img,egg);
dim = [size(egg,1),size(egg,2)];
% using modulus to lower the amount of steps, to simplify code
key = mod(Key,1000);
%Seperating color channels
r1 = img(:,:,1);
g1 = img(:,:,2);
b1 = img(:,:,3);
r2 = egg(:,:,1);
g2 = egg(:,:,2);
b2 = egg(:,:,3);
%Driver code
r = hide(r1,r2,key);
g = hide(g1,g2,key);
b = hide(b1,b2,key);
%Combining the color channels
output(:,:,1) = r;
output(:,:,2) = g;
output(:,:,3) = b;
imwrite(output,'output.png')
end
%Function to hid matrix inside another
function [hidden] = hide(image,egg,key)
[row,col] = size(egg);
% turning the matrices into vectors to make it easy to loop over
imgvec = image(:);
% Move the most significant bits of the secret image to the least significant bits
tempi = egg./64;
eggvec = tempi(:);
%max value of pixels to hide
max = row*col;
% counter to make sure the loop stops once all the pixels are hidden
i = 1;
% temp value we need to re-loop over the matrix from a new starting point
temp = 2;
%counter
n = 1;
while(i<max)
imgvec(n) = imgvec(n) + eggvec(i);
n = n + key;
if n>max
n = temp;
temp = temp + 1;
end
i = i + 1;
end
hidden = reshape(imgvec,[size(image,1),size(image,2)]);
end
% Function to check if image 1 is bigger than image 2
% And if so resize image 1 to be bigger than image 2
function [image] = check(img1,img2)
row1 = size(img1,1);
col1 = size(img1,2);
row2 = size(img2,1);
col2 = size(img2,2);
if row2*col2>row1*col1
val1 = ceil(row2/row1);
val2 = ceil(col2/col1);
if val1 > val2
image = imresize(img1,val1);
else
image = imresize(img1,val2);
end
else
image = img1;
disp('yes')
end
end
code to reveal image hidden:
function [] = getMyimg(key,dim)
image = imread('output.png');
%seperating color channels
r = image(:,:,1);
g = image(:,:,2);
b = image(:,:,3);
row = dim(1);
col = dim(2);
egg(:,:,1) = getimg(r,key,row,col);
egg(:,:,2) = getimg(g,key,row,col);
egg(:,:,3) = getimg(b,key,row,col);
% move least significant bits to the most significant
egg = egg * 64;
imwrite(egg,'secret.png');
end
function [egg] = getimg(image,key,row,col)
imgvec = image(:);
%initializing vector with the right dimensions for the secret image
eggvec = zeros(row*col,1);
max = row*col;
i = 1;
n = 1;
temp = 2;
while i < max
%get the least significant bits
eggvec(i) = mod(imgvec(n),4);
n = n + key;
if n>max
n = temp;
temp = temp + 1;
end
i = i + 1;
end
egg = reshape(eggvec,[row,col]);
end
resulting image:
why is it coming out like this?

How to process image before applying bwlabel?

I = imread('Sub1.png');
figure, imshow(I);
I = imcomplement(I);
I = double(I)/255;
I = adapthisteq(I,'clipLimit',0.0003,'Distribution','exponential');
k = 12;
beta = 2;
maxIter = 100;
for i=1:length(beta)
[seg,prob,mu,sigma,it(i)] = ICM(I, k, beta(i), maxIter,5);
pr(i) = prob(end);
hold on;
end
figure, imshow(seg,[]);
and ICM function is defined as
function [segmented_image,prob,mu,sigma,iter] = ICM(image, k, beta, max_iterations, neigh)
[width, height, bands] = size(image);
image = imstack2vectors(image);
segmented_image = init(image,k,1);
clear c;
iter = 0;
seg_old = segmented_image;
while(iter < max_iterations)
[mu, sigma] = stats(image, segmented_image, k);
E1 = energy1(image,mu,sigma,k);
E2 = energy2(segmented_image, beta, width, height, k);
E = E1 + E2;
[p2,~] = min(E2,[],2);
[p1,~] = min(E1,[],2);
[p,segmented_image] = min(E,[],2);
prob(iter+1) = sum(p);
%find mismatch with previous step
[c,~] = find(seg_old~=segmented_image);
mismatch = (numel(c)/numel(segmented_image))*100;
if mismatch<0.1
iter
break;
end
iter = iter + 1;
seg_old = segmented_image;
end
segmented_image = reshape(segmented_image,[width height]);
end
Output of my algorithm is a logical matrix (seg) of size 305-by-305. When I use
imshow(seg,[]);
I am able to display the image. It shows different component with varying gray value. But bwlabel returns 1. I want to display the connected components. I think bwlabel thresholds the image to 1. unique(seg) returns values 1 to 10 since number of classes used in k-means is 10. I used
[label n] = bwlabel(seg);
RGB = label2rgb(label);
figure, imshow(RGB);
I need all the ellipse-like structures which are in between the two squares close to the middle of the image. I don't know the number of classes present in it.
Input image:
Ground truth:
My output:
If you want to explode the label image to different connected components you need to use a loop to extract labels for each class and sum label images to get the out label image.
u = unique(seg(:));
out = zeros(size(seg));
num_objs = 0;
for k = 1: numel(u)
mask = seg==u(k);
[L,N] = bwlabel(mask);
L(mask) = L(mask) + num_objs;
out = out + L;
num_objs = num_objs + N ;
end
mp = jet(num_objs);
figure,imshow(out,mp)
Something like this is produced:
I have tried to do everything out of scratch. I wish it is of some help.
I have a treatment chain that get at first contours with parameters tuned on a trial-and-error basis, I confess. The last "image" is given at the bottom ; with it, you can easily select the connected components and do for example a reconstruction by markers using "imreconstruct" operator.
clear all;close all;
I = imread('C:\Users\jean-marie.becker\Desktop\imagesJPG10\spinalchord.jpg');
figure,imshow(I);
J = I(:,:,1);% select the blue channel because jpg image
J=double(J<50);% I haven't inverted the image
figure, imshow(J);
se = strel('disk',5);
J=J-imopen(J,se);
figure, imshow(J);
J=imopen(J,ones(1,15));% privilegizes long horizontal strokes
figure, imshow(J);
K=imdilate(J,ones(20,1),'same');
% connects verticaly not-to-far horizontal "segments"
figure, imshow(K);

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.