Extract elliptical region and crop it with with manually in Matlab - 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);

Related

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.

Create a loop in order to create freehand ROIs

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.

Apply the same filter in a sequence of images while displaying it animated in the same figure in Matlab

I'm using MATLAB 2013a.
I have a folder with 1151 images that I want to animate in the same figure (window).
I want to find the imabsdiff of each image with only one image (maybe this one as a background image), and I would like it to display it animated and in the same figure, like if it was a video.
I found this code:
srcFiles = dir('C:\Users\coil-20-proc\*.jpeg'); % the folder in which ur images exists
for i = 1 : length(srcFiles)
filename = strcat('C:\Users\coil-20-proc\',srcFiles(i).name);
I = imread(filename);
figure, imshow(I);
end
which does read each image from my folder, but it creates a new figure(window) for each image, but I don't want 1151 windows!
You likely want to create a single imshow image object and then update the CData of this object each time through the loop.
directory = 'C:\Users\coil-20-proc';
srcFiles = dir(fullfile(directory, '*.jpeg');
srcFiles = cellfun(#(x)fullfile(directory, x), {srcFiles.name}, 'uni', 0);
hfig = figure();
him = imshow(NaN);
for k = 1:numel(srcFiles)
im = imread(srcFiles{k});
%// Perform your operation here
set(him, 'CData', im);
axis tight;
drawnow;
end

how can i save the image and roi to train classifier

i use this code
axes(handles.axes1)
h=imrect;
position = round(wait(h));
curImg=1;
I=imread(strcat(pathname, filename{k}));
[rows, columns, numberOfColorBands] = size(I);
% Crop image
I2 = imcrop(I,position);
figure;
imshow(I2);
data(curImg).imageFilename = I;
data(curImg).objectBoundingBoxes = position;
curImg = curImg + 1;
i select roi than i extract the position and i save the pathname and the position of the roi, when i use the struct data to train classifier it dosen't work, here is the code:
trainCascadeObjectDetector('Detector.xml',data,negativeFolder,'FalseAlarmRate',0.2,'NumCascadeStages',5);
hope to get a response.
Use trainingImageLabeler app to label your images. Then export the ROIs to your workspace, and pass them to trainCascadeObjectDetector.

Plot imellipse over image in MATLAB

I am trying to make a binary region of interest mask over an image stack (GUI). Here is what I have thus far:
% Initalize lesion mask
LesionMask = zeros(size(handles.ImageOne));
% Create an ellipse for roi analysis
Lesion = imellipse(handles.axes1);
% Save roi to 3D binary mask
LesionMask(:,:,handles.CurrentSlice) = Lesion.createMask();
boundary = bwboundaries(LesionMask(:,:,handles.CurrentSlice))
Now I would like to overlay the boundary over my image, in particular, I would like it to stay even when I go through my image stack.
In short, I would like to plot the edge of the ellipse over my image.
Thanks!
This might work for you when added to your code at the end -
hold on
for k = 1:numel(boundary)
plot(boundary{k}(:,2), boundary{k}(:,1), 'r', 'Linewidth', 3) %// Red border
end
Inspired from this blog
If you would like to keep the edge on the image saved for later usage, try this -
[M,N,C] = size(handles.ImageOne)
t1 = cell2mat(boundary);
ind1 = sub2ind([M N],t1(:,1),t1(:,2));
ind2 = bsxfun(#plus,ind1,[0:C-1].*(M*N));
handles.ImageOne(ind2)=0; %// Creates a black border