how to change real time webcam background like this vid :
https://www.youtube.com/watch?v=YhJPbeI3vVU
can someone explain what to do and where to start , do i need chromakey,opencv or something like that ? it doesnt need to be video background, image will do.
im using matlab and already done the GUI
%% object initialitation
caminf = imaqhwinfo;
mycam = char(caminf.InstalledAdaptors(end));
mycaminfo = imaqhwinfo(mycam);
resolution = char(mycaminfo.DeviceInfo.SupportedFormats(end));
vd = videoinput(mycam, 1, resolution);
%% Previewing video
vidRes = get(vd, 'VideoResolution');
nBands = get(vd, 'NumberOfBands');
hImage = image(zeros(vidRes(2), vidRes(1), nBands));
preview(vd, hImage);
thx,
regards.
Here's a bit of code that should hopefully get you in the right direction. Basically you take a background image and a foreground image and where the two differ by more than a tolerance threshold value, those pixels are considered 'foreground'. Replace these same pixels in the new background with those captured on the webcam to get your background replacement image. Do that with images taken from a video to get a dynamic background.
% User Input:
threshVal = 0; % Tolerance for difference between 'webcam' background and foreground images
%%%%%%%%%%%%
% End User input
% Read in some images
% img1 is the webcam background image
img1 = imread('http://i.imgur.com/toD56.jpg');
% bkgdImg is the image to replace the background of img1 with
bkgdImg = imread('http://i.imgur.com/dIMct6u.jpg');
% Resize bkgdImg so it is the same size as img1. With two images from the same webcam this will not be necessary.
bkgdImg = imresize(bkgdImg, [size(img1, 1), size(img1, 2)]);
% Draw on 'webcam' image to make it different
% In actual algorithm, img2 would be a second image captured with the
% webcam with the same background but different foregrounds, such as a
% person now standing in front of camera.
img2 = img1;
% Draw Ncircles number of random-colored circles. Details here are not
% important except that it adds a unique foreground to the second 'webcam'
% image
Ncircles = 10;
X = bsxfun(#plus,(1:size(img1, 1))',zeros(1,size(img1, 2)));
Y = bsxfun(#plus,(1:size(img1, 2)),zeros(size(img1, 1),1));
for k = 1:Ncircles
circleCenter = rand(1,2).*[size(img1, 1), size(img1, 2)];
circleRadii = 50*rand(1);
B = sqrt(sum(bsxfun(#minus,cat(3,X,Y),reshape(circleCenter,1,1,[])).^2,3))<=circleRadii;
Npix = sum(B(:));
img2(repmat(B, 1, 1, 3) == 1) = reshape(255*ones(Npix, 1)*rand(1,3), [], 1);
end
% Take difference of background and foreground images
% If difference is greater than threshVal, then add those pixels to the
% mask.
% The operation has to be done both ways because images are unsigned
% integers and negative values are ignored.
diffMask = ((img1 - img2) > threshVal) | ((img2 - img1) > threshVal);
% Reduce mask by taking any value along 3rd dimension as logical true
diffMask = any(diffMask, 3);
% Replicate replacement background
bkgdImgReplace = bkgdImg;
% In regions where mask is true (ie where background ~= foreground from
% webcam) replace those pixels in the replacement background image with the
% foreground pixels
bkgdImgReplace(repmat(diffMask, 1, 1, 3)) = img2(repmat(diffMask, 1, 1, 3));
% Display
figure()
subplot(2, 2, 1)
imshow(img1)
title('Original Background')
subplot(2,2,2)
imshow(img2)
title('Modified Background w/ New foreground')
subplot(2,2,3)
imshow(bkgdImg)
title('Replacement Background')
subplot(2,2,4)
imshow(bkgdImgReplace);
title('Replacement Background w/ New foreground')
Related
I have calculated difference of h,s and v value of current and background frame of a video and want to display the value in order to do random checkness of the difference value for further action. I got final output as 360x640 matrix. Guess it displays difference value of last frame. Can anyone help me to display all the difference value of h, s and v.
videoObject = VideoReader(movieFullFileName)
% Determine how many frames there are.
% numberOfFrames = videoObject.NumberOfFrames;
vidHeight = videoObject.Height;
vidWidth = videoObject.Width;
for frame = 1 : numberOfFrames
% Extract the frame from the movie structure.
thisFrame = read(videoObject, frame);
% Now let's do the differencing
alpha = 0.5;
if frame == 1
Background = thisFrame;
else
% Change background slightly at each frame
% Background(t+1)=(1-alpha)*I+alpha*Background
Background = (1-alpha)* thisFrame + alpha * Background;
end
% Display the changing/adapting background.
subplot(2, 2, 3);
imshow(Background);
title('Adaptive Background', 'FontSize', fontSize);
% Do color conversion from rgb to hsv
x=rgb2hsv(thisFrame);
y=rgb2hsv(Background);
% Split the hsv component to h,s,v value
Hx = x(:,:,1);
Sx = x(:,:,2);
Vx = x(:,:,3);
Hy = y(:,:,1);
Sy = y(:,:,2);
Vy = y(:,:,3);
dh=(abs(double(Hx) - double(Hy)));
ds1=(abs(double(Sx) - double(Sy)));
dv1=(abs(double(Vx) - double(Vy)));
disp(dh);
disp(ds1);
disp(dv1);
end
end
If you want to show the complete image
First you need to evaluate the full HSV image
hsv=zeros(size(x,1),size(x,2))
hsv(:,:,1) = dh;
hsv(:,:,2) = ds1;
hsv(:,:,3) = dv1;
then convert to RGB using:
rgb = hsv2rgb(hsv);
then you can show it using:
image(rgb);
If you want to show single h,s and v image
just use:
for frame = 1 : numberOfFrames
subplot(3,1,1)
imshow(dh)
subplot(3,1,2)
imshow(ds1)
subplot(3,1,3)
imshow(ds2)
impixelinfo;
pause;
end
You will see the pixel value on the bottom left part of the image, when the cursor is above the image.
To continue with the next image press any keyboard key
You should add drawnow at the end of the for-loop to update the figure window every frame.
Moreover, disp will show you the difference matrices as numbers. Consider using something like
subplot(2, 2, 1)
imshow(dh)
with proper color scaling to visualize the difference matrices.
New to MATLAB and image processing.I need to know how to segment an image into foreground and background, then generate a binary image as output.
I need this as an output:
I have already tried to accomplish this with online tutorials and this is what i managed to get:
Its a good start but not exactly what i need.
My Code:
I = imread('AssignmentInput.jpg');
figure;
imshow(I);
title('Step-1: Load input image');
img_filtered = I;
for c = 1 : 3
img_filtered(:, :, c) = medfilt2(I(:, :, c), [3, 3]);
end
figure;
imshow(img_filtered);
title('Step-3:Noise Removal');
H = fspecial('gaussian'); % Create the filter kernel.
img_filtered = imfilter(img_filtered,H); % Blur the image.
Mask = im2bw(img_filtered, 0.9); % Now we are generating the binary mask.
img_filtered([Mask, Mask, Mask]) = 0; % Now we have the image.
figure;
imshow(img_filtered);
title('Step-5:Segmented Image');
For a better noise removal process and cleaner separation between foreground and background, you can also add morphological operations like:
se = strel('square',2);
I = imclose(I,se);
You can try out different variations of 'strel' class also. The image below is after imclose operation with a square of 2 pixel
I am working on developing a CBIR system, where I have to segment my RGB image in the following way:
I am implementing the code in matlab, but I am unable to build the proper masks for it.
I used imellipse but that requires the image handle which is achieved using imshow, but I don't want to show my image.
My code is
img=imread('peppers.png');
h_im=imshow(img); %I want to get rid of imshow because I don't want to show the image
[height, width, planes]=size(img);
%(cX,cY) is image center
cX=width/2;
cY=(height)/2;
%Here I define my ROI which is an ellipse that stretches to 75 percent of
%height and width of the image
e=imellipse(gca,[(1/2-3/8)*width, (1/2-3/8)*height,(3/4)*width,(3/4)*height]);
mymask=createMask(e,h_im);
%extending mask to three channels
mymask=repmat(mymask,[1 1 3]);
ROI=img;
ROI(mymask==0)=0;
figure, imshow(ROI);
You can generate the ellipse mask yourself rather than using the imellipse command.
% Create a meshgrid the same size of the image in order to generate the mask
[x y] = meshgrid(1:size(img, 1), 1:size(img, 2));
% Create the eclipse mask using the general form of an eclipse
% This will be centered in the middle of the image
% and have a height and width of 75% of th eimage
A = (0.75/2)*size(img, 2);
B = (0.75/2)*size(img, 1);
mask = A^2*(x - floor(size(img, 1)/2)).^2 + B^2*(y - floor(size(img, 2)/2)).^2<=A^2*B^2;
% Apply the eclipse mask
masked_image = img.*repmat(mask, [1, 1, 3]);
A bit of a hack but you could create a 'hidden' figure. The only difference is that I added: figure('Visible', 'off') at the start of your code.
figure('Visible', 'off');
img=imread('peppers.png');
h_im = imshow(img); %I want to get rid of imshow because I don't want to show the image
[height, width, planes]=size(img);
%(cX,cY) is image center
cX=width/2;
cY=(height)/2;
%Here I define my ROI which is an ellipse that stretches to 75 percent of
%height and width of the image
e=imellipse(gca,[(1/2-3/8)*width, (1/2-3/8)*height,(3/4)*width,(3/4)*height]);
mymask=createMask(e,h_im);
%extending mask to three channels
mymask=repmat(mymask,[1 1 3]);
ROI=img;
ROI(mymask==0)=0;
figure, imshow(ROI);
I think this code is easy to understand and easily adjustable to address an arbitrary part of your image (It has the same output as your code) :
img = imread('peppers.png');
% define the size of your ellipse relatively to the image dimension
factor = 0.75;
hwidth = size(img, 2) / 2.0;
hheight = size(img, 1) / 2.0;
a = hwidth * factor;
b = hheight * factor;
[x, y] = meshgrid(1:hwidth, 1:hheight);
% simple ellipse equation gets us part three of your mask
bottom_right_mask = (((x.^2)/a^2+(y.^2)/b^2)<=1);
% flip to get the remaining ones
top_right_mask = flipud(bottom_right_mask);
bottom_left_mask = fliplr(bottom_right_mask);
top_left_mask = flipud(bottom_left_mask);
mask = [top_left_mask, top_right_mask; ...
bottom_left_mask, bottom_right_mask];
multichannel_mask = repmat(mask,[1 1 3]);
ROI = img;
ROI(multichannel_mask==0) = 0;
figure;
imshow(ROI);
This is my original image:
I've asked the user to crop it, converted it to grayscale and ran this line of code on it:
edgeImg = edge(grayImg,'canny',0.23);
This is the result:
I want to "cut out" everything the middle circle and the outside edge, essentially. I'm having a really hard time figuring out how to do this and honestly I'm at a loss.
I considered trying to fill in the area that I want to keep in the binary image, and then I could use it as a stamp, but I couldn't come up with a way that didn't fill in the middle circle as well.
Any ideas?
Thanks.
EDIT: This white area is what I want to keep:
I would suggest not to do edge detection in the first place, you are loosing valuable information related to color. You may try some clustering algorithm, like K-Means (including source code) or whatever else.
After clustering is done, you may keep pixels that are related to cluster(s) with the object. Desirable cluster(s) may be selected based on the object position in the image (including cropping of the image) and its color.
Code example of K-Means clustering for 2 clusters is below:
he = imread('D:\1.jpg');
imshow(he);
cform = makecform('srgb2lab');
lab_he = applycform(he,cform);
ab = double(lab_he(:,:,2:3));
nrows = size(ab,1);
ncols = size(ab,2);
ab = reshape(ab,nrows*ncols,2);
%One cluster for your object and one for background
nColors = 2;
[cluster_idx, cluster_center] = kmeans(ab,nColors,'distance','sqEuclidean', ...
'Replicates',2);
pixel_labels = reshape(cluster_idx,nrows,ncols);
segmented_images = cell(1,3);
rgb_label = repmat(pixel_labels,[1 1 3]);
for k = 1:nColors
color = he;
color(rgb_label ~= k) = 0;
segmented_images{k} = color;
end
%Show both clusters: object and non-object
imshow(segmented_images{1});
figure;
imshow(segmented_images{2});
The resulting segmentation is quite good:
Instead of using K-Means, you can simply use the color thresholder since you have so much color information. Then you can call the mask function automatically generated called createMask and further post process your image there. The code is below. The best part of this method is that createMask is reusable for any image, not just your own!
% Read Image
I = imread('r8ATB.jpg');
figure; imshow( I );
% Crop Image
C = I(75:490,40:460,:);
figure; imshow( C );
% Plot Noisy Mask
[BW,MK] = createMask( C );
figure; imshow( BW );
figure; imshow( BW );
% Fix Holes
imopen( ... );
This is the original image.
Cropped Image
Start threshold window.
Threshold Parameters
Created mask
Final Image
The createMask.m function that is automatically generated using my parameter is as follows.
function [BW,maskedRGBImage] = createMask(RGB)
%createMask Threshold RGB image using auto-generated code from colorThresholder app.
% [BW,MASKEDRGBIMAGE] = createMask(RGB) thresholds image RGB using
% auto-generated code from the colorThresholder App. The colorspace and
% minimum/maximum values for each channel of the colorspace were set in the
% App and result in a binary mask BW and a composite image maskedRGBImage,
% which shows the original RGB image values under the mask BW.
% Auto-generated by colorThresholder app on 23-Apr-2015
%------------------------------------------------------
% Convert RGB image to chosen color space
I = rgb2hsv(RGB);
% Define thresholds for channel 1 based on histogram settings
channel1Min = 0.983;
channel1Max = 0.167;
% Define thresholds for channel 2 based on histogram settings
channel2Min = 0.205;
channel2Max = 1.000;
% Define thresholds for channel 3 based on histogram settings
channel3Min = 0.341;
channel3Max = 1.000;
% Create mask based on chosen histogram thresholds
BW = ( (I(:,:,1) >= channel1Min) | (I(:,:,1) <= channel1Max) ) & ...
(I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
(I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
% Invert mask
BW = ~BW;
% Initialize output masked image based on input image.
maskedRGBImage = RGB;
% Set background pixels where BW is false to zero.
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;
You can then proceed to use imopen and imclose to clean up your mask. Then apply it to the image. My method requires tuning to get it perfect as per any method, but it will give you consistent results.
To obtain the complement of your image, all you need to do is invert the mask and apply it.
Using MATLAB, I am trying to convert a randomly sized image into four equal blocks. I am working with "for" loops to create blocks. The problem I am facing is that these blocks are being converted into gray scale whereas I want the blocks to retain their original form i.e. RGB channel. Here is the code I am using:
clear all;
img1 = imread('ABC.png');
[rs, cols, colorchan] = size(img1);
rnew = int32(rs/2);
cnew = int32(cols/2);
for i = 1:4
for j = 1:4
imgij = img1((i-1)*rnew+1:i*rnew, (j-1)*cnew+1:j*cnew);
figure();
imshow(imgij);
%do some other stuff here%
end
end
I am new to MATLAB and that's the best I could do myself. Can somebody please tell me how to retain the original form of every block of the parent image? Any help will be highly appreciated.
You have considered only the width and height of the image. But actually for a colour image, colour is the 3rd dimension in Matlab. Try the following code.
img = imread('onion.png');
figure; imshow(img);
w = size(img,2); % width of the original image
h = size(img,1); % height of the original image
wm = floor(w/2); % middle of the width
hm = floor(h/2); % middle of the height
figure;
imgtl = img(1:hm,1:wm,:); % top left image
subplot(2,2,1); imshow(imgtl);
imgtr = img(1:hm,wm+1:w,:); % top right image
subplot(2,2,2); imshow(imgtr);
imgbl = img(hm+1:h,1:wm,:); % bottom left image
subplot(2,2,3); imshow(imgbl);
imgbr = img(hm+1:h,wm+1:w,:); % bottom right image
subplot(2,2,4); imshow(imgbr);
Original image:
Partitioned image: