Color-pass filter by Hue - matlab

Why doesn't color filter below find green peppers?
The code:
function [ outhsv ] = ColorFilter( hsv, h, s )
%COLORFILTER Summary of this function goes here
% Detailed explanation goes here
if nargin < 2
h = [];
end
if nargin < 3
s = [];
end
if size(h,2)==1
h = padarray(h, [0 1], 1/100, 'post');
end
if size(s,2)==1
s = padarray(s, [0 1], 1/100, 'post');
end
if isempty(h)
v_of_h = ones(size(hsv,1), size(hsv,2));
else
v_of_h = WeightFunction( hsv(:,:,1), h(:,1), h(:,2));
end
if isempty(s)
v_of_s = ones(size(hsv,1), size(hsv,2));
else
v_of_s = WeightFunctionOnce( hsv(:,:,2), s(:,1), s(:,2));
end
outhsv = hsv;
outhsv(:,:,3) = hsv(:,:,3) .* v_of_h .* v_of_s;
function y = WeightFunction( x, mu, sigma )
%y = WeightFunctionOnce(x,mu,sigma) + WeightFunctionOnce(x-1,mu,sigma);
y = 1 - (1-WeightFunctionOnce(x,mu,sigma)) .* (1-WeightFunctionOnce(x-1,mu,sigma));
function y = WeightFunctionOnce( x, mu, sigma )
if nargin<2
mu=0;
elseif nargin<3
sigma=1./100.;
end
if any(size(mu) ~= size(sigma))
error('mu and sigma should be of the same size');
end
y = zeros([size(x) numel(mu)]);
for i=1:numel(mu)
y(:,:,i) = exp(-((x - mu(i)) .^ 2 ./ (2 .* sigma(i) .^ 2)));
end
%y = sum(y,3)/size(y,3);
y = 1-prod(1-y,3);
Display code:
hue = 120;
h = [hue/360 0.05];
s = [];
rgb1 = imread('huescale.png');
%rgb1 = imread('peppers.png');
hsv1 = rgb2hsv(rgb1);
hsv2 = ColorFilter(hsv1, h, s);
rgb2 = hsv2rgb(hsv2);
bitmask = hsv1(:,:,1)>(h(1)-h(2)) & hsv1(:,:,1)<(h(1)+h(2));
figure;
subplot(3,1,1); imshow(rgb1);
subplot(3,1,2); imshow(rgb2);
subplot(3,1,3); imshow(bitmask);
result on scale
(works)
result on peppers:
(does not)
Why?

If you looked closer at the H values, those green peppers are kind of yellowish, so you might want to widen the rule a bit.
I would suggest something in between 0.15 and 0.5. You can also combine with saturation channel, say only consider portions of images that are vibrant, i.e., we want to get rid of the onions. Try the following codes to get a preview.
hsv_dat = rgb2hsv(imread('peppers.png'));
imagesc(hsv_dat(:,:,1) > 0.15 & hsv_dat(:,:,1) < 0.5 & hsv_dat(:,:,2) > 0.3)
colormap(gray)
You should get

Related

Finite Element assembly

I'm having serious problems in a simple example of fem assembly.
I just want to assemble the Mass matrix without any coefficient. The geometry is simple:
conn=[1, 2, 3];
p = [0 0; 1 0; 0 1];
I made it like this so that the physical element will be equal to the reference one.
my basis functions:
phi_1 = #(eta) 1 - eta(1) - eta(2);
phi_2 = #(eta) eta(1);
phi_3 = #(eta) eta(2);
phi = {phi_1, phi_2, phi_3};
Jacobian matrix:
J = #(x,y) [x(2) - x(1), x(3) - x(1);
y(2) - y(1), y(3) - y(1)];
The rest of the code:
M = zeros(np,np);
for K = 1:size(conn,1)
l2g = conn(K,:); %local to global mapping
x = p(l2g,1); %node x-coordinate
y = p(l2g,2); %node y-coordinate
jac = J(x,y);
loc_M = localM(jac, phi);
M(l2g, l2g) = M(l2g, l2g) + loc_M; %add element masses to M
end
localM:
function loc_M = localM(J,phi)
d_J = det(J);
loc_M = zeros(3,3);
for i = 1:3
for j = 1:3
loc_M(i,j) = d_J * quadrature(phi{i}, phi{j});
end
end
end
quadrature:
function value = quadrature(phi_i, phi_j)
p = [1/3, 1/3;
0.6, 0.2;
0.2, 0.6;
0.2, 0.2];
w = [-27/96, 25/96, 25/96, 25/96];
res = 0;
for i = 1:size(p,1)
res = res + phi_i(p(i,:)) * phi_j(p(i,:)) * w(i);
end
value = res;
end
For the simple entry (1,1) I obtain 0.833, while computing the integral by hand or on wolfram alpha I get 0.166 (2 times the result of the quadrature).
I tried with different points and weights for quadrature, but really I do not know what I am doing wrong.

Plot equally spaced markers along a spiral

I want to move a red star marker along the spiral trajectory with an equal distance of 5 units between the red star points on its circumference like in the below image.
vertspacing = 10;
horzspacing = 10;
thetamax = 10*pi;
% Calculation of (x,y) - underlying archimedean spiral.
b = vertspacing/2/pi;
theta = 0:0.01:thetamax;
x = b*theta.*cos(theta)+50;
y = b*theta.*sin(theta)+50;
% Calculation of equidistant (xi,yi) points on spiral.
smax = 0.5*b*thetamax.*thetamax;
s = 0:horzspacing:smax;
thetai = sqrt(2*s/b);
xi = b*thetai.*cos(thetai);
yi = b*thetai.*sin(thetai);
plot(x,y,'b-');
hold on
I want to get a figure that looks like the following:
This is my code for the circle trajectory:
% Initialization steps.
format long g;
format compact;
fontSize = 20;
r1 = 50;
r2 = 35;
r3= 20;
xc = 50;
yc = 50;
% Since arclength = radius * (angle in radians),
% (angle in radians) = arclength / radius = 5 / radius.
deltaAngle1 = 5 / r1;
deltaAngle2 = 5 / r2;
deltaAngle3 = 5 / r3;
theta1 = 0 : deltaAngle1 : (2 * pi);
theta2 = 0 : deltaAngle2 : (2 * pi);
theta3 = 0 : deltaAngle3 : (2 * pi);
x1 = r1*cos(theta1) + xc;
y1 = r1*sin(theta1) + yc;
x2 = r2*cos(theta2) + xc;
y2 = r2*sin(theta2) + yc;
x3 = r3*cos(theta3) + xc;
y3 = r3*sin(theta3) + yc;
plot(x1,y1,'color',[1 0.5 0])
hold on
plot(x2,y2,'color',[1 0.5 0])
hold on
plot(x3,y3,'color',[1 0.5 0])
hold on
% Connecting Line:
plot([70 100], [50 50],'color',[1 0.5 0])
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0, 0, 1, 1]);
drawnow;
axis square;
for i = 1 : length(theta1)
plot(x1(i),y1(i),'r*')
pause(0.1)
end
for i = 1 : length(theta2)
plot(x2(i),y2(i),'r*')
pause(0.1)
end
for i = 1 : length(theta3)
plot(x3(i),y3(i),'r*')
pause(0.1)
end
I can't think of a way to compute distance along a spiral, so I'm approximating it with circles, in hopes that it will still be useful.
My solution relies on the InterX function from FEX, to find the intersection of circles with the spiral. I am providing an animation so it is easier to understand.
The code (tested on R2017a):
function [x,y,xi,yi] = q44916610(doPlot)
%% Input handling:
if nargin < 1 || isempty(doPlot)
doPlot = false;
end
%% Initialization:
origin = [50,50];
vertspacing = 10;
thetamax = 5*(2*pi);
%% Calculation of (x,y) - underlying archimedean spiral.
b = vertspacing/(2*pi);
theta = 0:0.01:thetamax;
x = b*theta.*cos(theta) + origin(1);
y = b*theta.*sin(theta) + origin(2);
%% Calculation of equidistant (xi,yi) points on spiral.
DST = 5; cRes = 360;
numPts = ceil(vertspacing*thetamax); % Preallocation
[xi,yi] = deal(NaN(numPts,1));
if doPlot && isHG2() % Plots are only enabled if the MATLAB version is new enough.
figure(); plot(x,y,'b-'); hold on; axis equal; grid on; grid minor;
hAx = gca; hAx.XLim = [-5 105]; hAx.YLim = [-5 105];
hP = plot(xi,yi,'r*');
else
hP = struct('XData',xi,'YData',yi);
end
hP.XData(1) = origin(1); hP.YData(1) = origin(2);
for ind = 2:numPts
P = InterX([x;y], makeCircle([hP.XData(ind-1),hP.YData(ind-1)],DST/2,cRes));
[~,I] = max(abs(P(1,:)-origin(1)+1i*(P(2,:)-origin(2))));
if doPlot, pause(0.1); end
hP.XData(ind) = P(1,I); hP.YData(ind) = P(2,I);
if doPlot, pause(0.1); delete(hAx.Children(1)); end
end
xi = hP.XData(~isnan(hP.XData)); yi = hP.YData(~isnan(hP.YData));
%% Nested function(s):
function [XY] = makeCircle(cnt, R, nPts)
P = (cnt(1)+1i*cnt(2))+R*exp(linspace(0,1,nPts)*pi*2i);
if doPlot, plot(P,'Color',lines(1)); end
XY = [real(P); imag(P)];
end
end
%% Local function(s):
function tf = isHG2()
try
tf = ~verLessThan('MATLAB', '8.4');
catch
tf = false;
end
end
function P = InterX(L1,varargin)
% DOCUMENTATION REMOVED. For a full version go to:
% https://www.mathworks.com/matlabcentral/fileexchange/22441-curve-intersections
narginchk(1,2);
if nargin == 1
L2 = L1; hF = #lt; %...Avoid the inclusion of common points
else
L2 = varargin{1}; hF = #le;
end
%...Preliminary stuff
x1 = L1(1,:)'; x2 = L2(1,:);
y1 = L1(2,:)'; y2 = L2(2,:);
dx1 = diff(x1); dy1 = diff(y1);
dx2 = diff(x2); dy2 = diff(y2);
%...Determine 'signed distances'
S1 = dx1.*y1(1:end-1) - dy1.*x1(1:end-1);
S2 = dx2.*y2(1:end-1) - dy2.*x2(1:end-1);
C1 = feval(hF,D(bsxfun(#times,dx1,y2)-bsxfun(#times,dy1,x2),S1),0);
C2 = feval(hF,D((bsxfun(#times,y1,dx2)-bsxfun(#times,x1,dy2))',S2'),0)';
%...Obtain the segments where an intersection is expected
[i,j] = find(C1 & C2);
if isempty(i), P = zeros(2,0); return; end
%...Transpose and prepare for output
i=i'; dx2=dx2'; dy2=dy2'; S2 = S2';
L = dy2(j).*dx1(i) - dy1(i).*dx2(j);
i = i(L~=0); j=j(L~=0); L=L(L~=0); %...Avoid divisions by 0
%...Solve system of eqs to get the common points
P = unique([dx2(j).*S1(i) - dx1(i).*S2(j), ...
dy2(j).*S1(i) - dy1(i).*S2(j)]./[L L],'rows')';
function u = D(x,y)
u = bsxfun(#minus,x(:,1:end-1),y).*bsxfun(#minus,x(:,2:end),y);
end
end
Result:
Note that in the animation above, the diameter of the circle (and hence the distance between the red points) is 10 and not 5.

how to count foreground segmented faces in image?

i have applied foreground segmentation on an image.its now showing the white areas instead of those faces in original image.now i want to counnt those faces how to do it?? output image is attached.......................................................
close all;
clear all;
clc;
rgbInputImage = imread('Crowd-of-people-008.jpg');
labInputImage = applycform(rgbInputImage,makecform('srgb2lab'));
Lbpdfhe = fcnBPDFHE(labInputImage(:,:,1));
labOutputImage = cat(3,Lbpdfhe,labInputImage(:,:,2),labInputImage(:,:,3));
rgbOutputImage = applycform(labOutputImage,makecform('lab2srgb'));
figure, imshow(rgbInputImage);
figure, imshow(rgbOutputImage);
img=rgbOutputImage;
final_image = zeros(size(img,1), size(img,2));
if(size(img, 3) > 1)
for i = 1:size(img,1)
for j = 1:size(img,2)
R = img(i,j,1);
G = img(i,j,2);
B = img(i,j,3);
if(R > 92 && G > 40 && B > 20)
v = [R,G,B];
if((max(v) - min(v)) > 15)
if(abs(R-G) > 15 && R > G && R > B)
final_image(i,j) = 1;
end
end
end
end
end
end
binaryImage=im2bw(final_image,0.6);
figure, imshow(binaryImage);
binaryImage = imfill(binaryImage, 'holes');
figure, imshow(binaryImage);
%binaryImage = bwareaopen(binaryImage,1890);
%figure,imshow(binaryImage);
%labeledImage = bwlabel(binaryImage, 8);
%blobMeasurements = regionprops(labeledImage, final_image, 'all');
%numberOfPeople = size(blobMeasurements, 1);
%imagesc(rgbInputImage); title('Outlines, from bwboundaries()');
%hold on;
%boundaries = bwboundaries(binaryImage);
%for k = 1 : numberOfPeople
%thisBoundary = boundaries{k};
%plot(thisBoundary(:,2), thisBoundary(:,1), 'g', 'LineWidth', 2);
%end
%imagesc(rgbInputImage);
%hold on;
%title('Original with bounding boxes');
%for k = 1 : numberOfPeople
%thisBlobsBox = blobMeasurements(k).BoundingBox;
%x1 = thisBlobsBox(1);
%y1 = thisBlobsBox(2);
%x2 = x1 + thisBlobsBox(3);
%y2 = y1 + thisBlobsBox(4);
%x = [x1 x2 x2 x1 x1];
%y = [y1 y1 y2 y2 y1];
%plot(x, y, 'LineWidth', 2);
%end
binaryimage = bwboundaries(binaryimage);
imshow(binaryimage)
text(10,10,strcat('\color{green}Objects Found:',num2str(length(Binaryimage))))
hold on
for k = 1:length(Binaryimage)
boundary = Binaryimage{k};
plot(boundary(:,2), boundary(:,1), 'g', 'LineWidth', 0.2)
endB = bwboundaries(binaryimage);
imshow(binaryimage)
text(10,10,strcat('\color{green}Objects Found:',num2str(length(Binaryimage))))
hold on
end
for k = 1:length(B)
boundary = B{k};
plot(boundary(:,2), boundary(:,1), 'g', 'LineWidth', 0.2)
end
Use [L, num] = bwlabel(BW, n) to compute num, the number of connected components. See here.
You can use vision.CascadeObjectDetector in the Computer Vision System Toolbox to detect faces without background subtraction.

How do I plot the output of a system with an impulse response in matlab?

I am very new to matlab and need to plot y1[n] = x[n] + y1[n − 1] where x[n] = [1,2,4] and an impulse response, h[n] = [1,1,1,1,1] and am not sure if I have went about it the right way
My code so far is
x = [1,2,4];
h = [1,1,1,1,1];
y = [];
for n=1:length(x)
if (n==1)
y(n) = x(n);
else
y(n) = (x(n)*h(n)) + (y(n-1)*h(n));
end
end
stem(y);
Please note that I cannot use the conv() function
I don't really know why it got so complicated,
x = [1,2,4];
h = [1,1,1,1,1];
y = [];
lh = length(h);
lx = length(x);
t = -lh - lx : lh + lx;
x(end + 1 : end + lh + 1) = 0;
h(end + 1 : end + lx + 1) = 0;
x = padarray(x,[0 max(t)],'pre');
h = padarray(h,[0 max(t)],'pre');
xinv = x(end:-1:1);
for n = 1 : length(t)
xinv = circshift(xinv,[0 1]);
y(n) = sum(xinv .* h);
end
y = circshift(y,[0 find(t == 0)]);
subplot(311)
stem(t,x);
xlim([-10 10])
subplot(312)
stem(t,h);
xlim([-10 10])
subplot(313)
stem(t,y);
xlim([-10 10])
It works fine but I believe it can be coded in a more simpler way.
Can you use fft?
lx = numel(x);
lh = numel(h);
m = max(lx, lh);
y = ifft(fft([h zeros(1,max(lx-lh,0)+m)]) .* fft([x zeros(1,max(lh-lx,0)+m)]));
y = y(1:lx+lh-1);

Line with variable width in Matlab

How can I draw a line whose thickness varies at each point in Matlab? I need to plot an average line, and then the standard deviation plotted as a shadow below it. Any ideas?
Thanks,
This is something I've written a while ago - it's a bit long, but you can just copy the whole thing. It deals with variable size input and produces a beautifully shaded plot - with std and min/max. Signal should be 2D. If you need a version for plotting two signals - just ask :)
function H = plotp(varargin)
switch nargin
case{1}
signal = varargin{1};
time = 1:size(signal,2);
prop = 'r-';
new_figure = true;
case{2}
time = varargin{1};
signal = varargin{2};
prop = 'r-';
new_figure = true;
case{3}
time = varargin{1};
signal = varargin{2};
prop = varargin{3};
new_figure = true;
case{4}
time = varargin{1};
signal = varargin{2};
prop = varargin{3};
new_figure = varargin{4};
end
if ischar(new_figure)
temp7 = regexpi(new_figure,'true');
if isempty(temp7)
new_figure = false;
H = get(0,'CurrentFigure');
else
new_figure = true;
end
elseif isnumeric(new_figure)
H = new_figure;
new_figure = false;
end
% prepare vectors for plotting
time2 = [time fliplr(time)];
sigm = nanmean(signal);
sigs = nanstd(signal);
sigms = [sigm-sigs fliplr(sigm+sigs)];
sigmin = nanmin(signal);
sigmax = nanmax(signal);
sigmm = [sigmin fliplr(sigmax)];
% check color
if strcmpi(prop(1),'r')
c1 = [1 0 0];
elseif strcmpi(prop(1),'g')
c1 = [0 1 0];
elseif strcmpi(prop(1),'b')
c1 = [0 0 1];
else
c1 = [1 1 1];
end
color1 = c1 + .7*(1-c1);
color2 = c1 + .8*(1-c1);
%
if length(prop) == 1
prop(2) = '-';
end
if new_figure
H = figure;
else
figure(H);
end
whole_screen = get(0,'ScreenSize');
% max figure size - add
fig_size = whole_screen + [-4 -4+2*32 +4+4 4+4-2*32];
set(H,'OuterPosition',fig_size);
plot(time,sigm,prop,'LineWidth',1.5)
hold all
fill(time2(~isnan(sigms)), sigms(~isnan(sigms)),color1,'EdgeColor',color1,'FaceAlpha', 0.4);
fill(time2(~isnan(sigmm)), sigmm(~isnan(sigmm)),color2,'EdgeColor',color2,'FaceAlpha', 0.3);
legend([{'Mean'} {'\pm Stddev'} {'Min/Max'} ],'Location','Best')
could you plot three lines, one as an average and the other two as + and - standard deviations.
If you're feeling particularly masochistic you could calculate the confidence interval of your line and plot that.