Create a loop in order to create freehand ROIs - matlab

I have the following code done whereby I import a frame from a film, convert to grayscale and draw by freehand the region of interest. I then use Chan-Vese region fill to get my region of interest and create a mask based on this. I can finally get the binary image I'm looking for which is called BW3 in the code. Now this is the silly part. How do I create a loop such that the code will run (load frames 1 to 58), present me with the grayscale image for frame 1, allow me to draw the region of interest and then create and save the final binary image BW3?
Regards,
J
% Select Initial Image
for n = 5:87
frame = read(obj,n);
%Isolate the Blade
imggray = rgb2gray(frame);
h_im=imshow(imggray);
%Region of interest
% r = imrect(gca,[646,188,18,-648]);
% BW2 = createMask(r,h_im);
hROI = imfreehand(gca);
Position = getPosition(hROI);
BW2 = createMask(hROI);
%Get blade Binary
BW3 = activecontour(imggray, BW2, 1000, 'Chan-Vese');
% Fill Holes
BW3 = imfill(BW3, 'holes');
% Form masked image from input image and segmented image.
maskedImage = h_im;
maskedImage(~BW3) = 0;
%Save binary frame
filename = sprintf('C:..........\\binaryimage%d.png', n);
imwrite(BW3,filename,'png');
end

Assuming that you have a limited number of frames (ie up to 58) you could just use a for loop to accomplish this. In your code, you will have to change the initial image code so that it iterates up with the loop.
for counter=1:58
frame=read(obj,counter);
imwrite(frame,strcat('frame',num2str(counter),'.png'))
.....% the remainder of your code likely remains unchanged.
end
When writing your results, you would likely need to drop it into a struct of some sort so that you can loop through unless you write your results to a file in each loop.

Related

Matlab video reader - draw disk on objects

i try to draw a disk on objects in video (the object are cars are move on road from left to right).
my code:
obj = VideoReader('Cars.avi');
get(obj)
im = read(obj,71);
nframes = get(obj,'NumberOfFrames');
sedisk = strel('disk',10);
im_new = imopen(im,sedisk);
stats = regionprops(im_new);
area_array = [stats.Area];
im2 = read(obj,1);
figure,imagesc(im2);
for i=1:nframes-1
stats(i).Centroid
frame = read(obj,i);
imshow(frame);
end
i see the frames but not the disk on the cars, why it's not working?
maybe something in the logic is wrong?
thank's everyone
You need to put the regionprops code into the for loop, and plot the regions over the image.
Start by following MATLAB regionprops documentation
I built a sample code with traffic.avi as input file.
traffic.avi file comes with my MATLAB installation (in folder toolbox/images/imdata/).
Here is a code sample (please read the comments):
clear
close all
%obj = VideoReader('Cars.avi');
obj = VideoReader('traffic.avi');
nframes = get(obj, 'NumberOfFrames');
%sedisk = strel('disk', 10);
sedisk = strel('disk', 2); %Smaller disk fits traffic.avi (you can keep sedisk = strel('disk', 10))
%Read first image (assume no cars). In your code you can keep: im = read(obj,71);
im1 = read(obj,1);
for i = 2:nframes
im = read(obj, i);
imshow(im); %Show the frame
%Subtract frame form the first frame - assume the cars will pop up in the difference image.
diff_im = uint8(abs(double(im) - double(im1)));
I = rgb2gray(diff_im); %Convert to grayscale image
BW = imbinarize(I); %Convert to binary image.
im_new = imopen(BW, sedisk);
stats = regionprops('table', im_new, 'Centroid', 'MajorAxisLength', 'MinorAxisLength'); %MATLAB documentation code sample
%imshow(im_new);
if (~isempty(stats))
%stats(i).Centroid
centers = stats.Centroid; %Get centers (MATLAB documentation code sample)
%Get radius of the circles (MATLAB documentation code sample).
diameters = mean([stats.MajorAxisLength stats.MinorAxisLength],2);
radii = diameters/2;
%Plot the circles on the displayed video frame.
hold on
viscircles(centers,radii);
hold off
end
pause(0.1); %Pause 0.1 seconds
end
The code is not marking the cars accurately (just demonstrates the stages).
Here is a sample frame:

Find biggest contour for shadow detection

I have this problem in image processing and I couldn't find an algorithm to perform well under this condition.It's so simple to understand but I don't know how to implement it in ‍‍OpenCV or in Matlab, so any algorithm or function in one of them (MATLAB or opencv) is helpful.
1 . lets suppose that an image and background of scene is like the below
2 . We apply an edge detector to image and my current image will be like the below picture.
now my Problem is that how we can find the biggest contour or area like the below in edge image?
If you want original picture the original picture is
and in matlab you can get edge image by below codes.
clc
clear
img = imread('1.png'); % read Image
gray = rgb2gray(img); % Convert RGB to gray-scale
edgeImage = edge(gray,'canny',0.09); % apply canny to gray-scale image
imshow(edgeImage) % Display result in figure(MATLAB)
In OpenCV you can use below code
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat img = imread("1.png");
Mat gray;
cvtColor(img, //BGR form image
gray, //Mat for gray(destination)
CV_BGR2GRAY); //type of transform(in here BGR->GRay)
Mat edgeImage;
Canny(gray, //Input Array
edgeImage, //Output Array
40, // Lower threshold
120); //Upper threshold
namedWindow("Edge-Image"); //create a window for display image
imshow("Edge-Image",edgeImage); //Display edgeImage in window that in before line create
waitKey(0); //stick display window and wait for any key
return 0;
}
Here is a solution in Matlab using imdilate to close the contours and regionprops to get the closed objects area:
% Your code to start
img = imread('Image.png'); % read Image
gray = rgb2gray(img); % Convert RGB to gray-scale
edgeImage = edge(gray,'canny',0.09); % apply canny to gray-scale image
% First dilate to close contours
BW = imdilate(edgeImage, strel('disk',4,8));
% Then find the regions
R = regionprops(~BW, {'Area', 'PixelIdxList'});
% Find the second biggest region (the biggest is the background)
[~, I] = sort([R(:).Area], 'descend');
Mask = zeros(size(img));
Mask(R(I(2)).PixelIdxList) = 1;
% Display
clf
imshow(Mask)
An the result is:
Best,
First close the contour with morphological closing since you can't find it now as it is not really a distinct contour, but a part of the larger one.
After closing, just use the findContours() function and use its output to get the area of each contour and eventually find the maximum one by using the contourArea() function.

Split up a binary image using their white boundaries in MATLAB

I'm trying to read the values in this image into variables using OCR in MATLAB. I'm having trouble doing so, so I tried to split up this image into smaller parts using the white boundary lines then trying to read it, but I dont know how to do this. Any help would be appreciated, thanks.
If the blocks are always delimited by a completely vertical line, you can find where they are by comparing the original image (here transformed from RGB to grayscale to be a single plane) to a matrix that is made of repeats of the first row of the original image only. Since the lines are vertical the intensity of the pixels in the first line will be the same throughout. This generates a binary mask that can be used in conjunction with a quick thresholding to reject those lines that are all black pixels in every row. Then invert this mask and use regionprops to locate the bounding box of each region. Then you can pull these out and do what you like.
If the lines dividing the blocks of text are not always vertical or constant intensity throughout then there's a bit more work that needs to be done to locate the dividing lines, but nothing that's impossible. Some example data would be good to have in that case, though.
img = imread('http://puu.sh/cU3Nj/b020b60f0b.png');
imshow(img);
imgGray = rgb2gray(img);
imgMatch = imgGray == repmat(imgGray(1,:), size(imgGray, 1), 1);
whiteLines = imgMatch & (imgGray > 0);
boxes = regionprops(~whiteLines, 'BoundingBox');
for k = 1:6
subplot(3,2,k)
boxHere = round(boxes(k).BoundingBox);
imshow(img(boxHere(2):(boxHere(2)+boxHere(4)-1), boxHere(1):(boxHere(1)+boxHere(3)-1), :));
end
You can sum along the columns of a binary image corresponding to that input image and find peaks from the sum values. This is precisely achieved in the code here -
img = imread('http://puu.sh/cU3Nj/b020b60f0b.png');
BW = im2bw(img,0.1); %// convert to a binary image with a low threshold
peak_sum_max = 30; %// max of sum of cols to act as threshold to decide as peak
peaks_min_width = 10; %// min distance between peaks i.e. min width of each part
idx = find( sum(BW,1)>=peak_sum_max );
split_idx = [1 idx( [true diff(idx)>peaks_min_width ] )];
split_imgs = arrayfun(#(x) img(:,split_idx(x):split_idx(x+1)),...
1:numel(split_idx)-1,'Uni',0);
%// Display split images
for iter = 1:numel(split_imgs)
figure,imshow(split_imgs{iter})
end
Please note that the final output split_imgs is a cell array with each cell holding image data for each split image.
If you would like to have the split images directly without the need for messing with cell arrays, after you have split_idx, you can do this -
%// Get and display split images
for iter = 1:numel(split_idx)-1
split_img = img(:,split_idx(iter):split_idx(iter+1));
figure,imshow(split_img)
end
There is now a built-in ocr function in the Computer Vision System Toolbox.

Extract elliptical region and crop it with with manually in Matlab

I have many face images, I want to extract an elliptical region from the images by manually and crop and save it automatically(like imcrop but not a rectangle).
Could you help me about this?
Thanks for your help
You can use the imellipse function.
%This is what you would do after creating the mask to get the coordinates.
structBoundaries = bwboundaries(binaryImage);
xy=structBoundaries{1}; % Get n by 2 array of x,y coordinates.
x = xy(:, 2); % Columns.
y = xy(:, 1); % Rows.
However a better way would be to use the code below. Essentially, it asks the user to select an image and then the user crops the image manually and then it saves to the location of where the original image is.
[FileName,PathName] = uigetfile({'*.jpg;*.tif;*.png;*.gif','All Image Files'},'Please Select an Image');
image = imread([PathName FileName]);
imshow(image) %needed to use imellipse
user_defined_ellipse = imellipse(gca, []); % creates user defined ellipse object.
wait(user_defined_ellipse);% You need to click twice to continue.
MASK = double(user_defined_ellipse.createMask());
new_image_name = [PathName 'Cropped_Image_' FileName];
new_image_name = new_image_name(1:strfind(new_image_name,'.')-1); %removing the .jpg, .tiff, etc
new_image_name = [new_image_name '.png']; % making the image .png so it can be transparent
imwrite(image, new_image_name,'png','Alpha',MASK);
msg = msgbox(['The image was written to ' new_image_name],'New Image Path');
waitfor(msg);

how to embed a watermark inside roi in matlab

the region of interest in the image are calculated. Now how to embed the watermark into the roi..i ve put the code for embedding it in the whole image in lsb. How can it modified for roi alone?
clear all;
file_name='pout.tif';
cover_object=imread(file_name);
file_name='cameraman.tif';
message=imread(file_name);
message=double(message);
message=round(message./256);
message=uint8(message);
Mc=size(cover_object,1);
Nc=size(cover_object,2);
Mm=size(message,1);
Nm=size(message,2);
for ii = 1:Mc
for jj = 1:Nc
watermark(ii,jj)=message(mod(ii,Mm)+1,mod(jj,Nm)+1);
end
end
watermarked_image=cover_object;
for ii = 1:Mc
for jj = 1:Nc
watermarked_image(ii,jj)=bitset(watermarked_image(ii,jj),1,watermark(ii,jj));
end
end
imwrite(watermarked_image,'watermarkedimage','bmp');
figure(1)
imshow(watermarked_image,[])
title('Watermarked Image')
If your roi is rectangular, just loop over the appropriate subsection of the image rather than the whole thing.
If not, and you can define the watermarking as some function:
imgout = watermark(img1, img2);
Then you can use roifilt2 to apply that function just in your roi.
In this simple example,mask is a BW matrix where 1 indicates part of our roi (a mask can be created several different ways including using some of the interactive roi functions, see bottom section). img1 and img2 have already been loaded:
f = #(x) watermark(x,img2); % our very basic function
imgout = roifilt2(img1,mask,f);
Complications may arise if your img2 is smaller than img1 (or if you want to resize it to just cover the roi area). In this case, do everything on a subsection of img1/mask and then assemble the final image:
img1_s = img1(a:b,c:d); % these return the same size as img2
mask_s = mask(a:b,c:d);
imgout_s = roifilt2(img1_s,mask1_s,f);
imgout = img1;
imgout(a:b,c:d) = imgout_s;
A mask can be created several ways, some using the interactive roi functions, some not. A lot depends on how you have your roi in the first place - do you have a centre/radius, or do you want to hand-pick the location interactively, etc. Here are a few examples making use of the Image Processing Tool Box:
Interactive ROI function and createMask.
This will work for any of the interactive roi functions (imellipse, imfreehand, etc). You can interactively adjust the mask between the second and third steps. Do not close the image window before calling createMask.
h = imshow(img); %display image
e = imellipse(gca,[50 50 100 100]); % select roi
mask = createMask(e,h); % return mask
List of x/y points and poly2mask
If you have a list of points defining the outer edge of your roi, a quick non-interactive way of producing a mask is to use poly2mask. The third and fourth values define the total size of the mask returned.
mask = poly2mask(x,y,size(img,1),size(img,2));
Using morphological operators
strel defines a structuring element, and imdilate performs a dilation using that structuring element. Given an image which contains a single point, what that does is replace the point with the structuring element - in this case disk which will produce a circle (or as close as you can get using pixels). Other shapes (e.g. diamond) can be used with strel
mask = zeros(size(img));
mask(a,b) = 1; % a,b is the centre point of the circle
se = strel(disk,r,0); %r is the radius of the circle
mask = imdilate(mask,se);