I am new to MATLAB, i wanted to know that can i extract a part of image from inside of a specified boundary,based on distinguishing color(red boundary in my case),The function,first traces the boundary of the image,then it extracts that part of image which is inside that particular boundary. I have my image(image of human head) attached, i wanted to extract the brain part from the head, other part of image should be ignored. I tried to find edges,using the following code(it shows 1's for boundaries, and 0 for no boundary),but it showed only 0's.
Any help will be greatly appreciated.
P.S. image attached shows original image and image with boundary....the code will be working on the one with boundary and will extract the part of image lying inside that boundary.
Below is the code i tried:
BW = edge(x)
BW = edge(x,'sobel')
BW = edge(x,'sobel',thresh)
BW = edge(x,'sobel',thresh,direction)
[BW,thresh] = edge(x,'sobel',...)
BW = edge(x,'prewitt')
BW = edge(x,'prewitt',thresh)
BW = edge(x,'prewitt',thresh,direction)
[BW,thresh] = edge(x,'prewitt',...)
BW = edge(x,'roberts')
BW = edge(x,'roberts',thresh)
[BW,thresh] = edge(x,'roberts',...)
BW = edge(x,'log')
BW = edge(x,'log',thresh)
BW = edge(x,'log',thresh,sigma)
[BW,threshold] = edge(x,'log',...)
BW = edge(x,'zerocross',thresh,h)
[BW,thresh] = edge(x,'zerocross',...)
BW = edge(x,'canny')
BW = edge(x,'canny',thresh)
BW = edge(x,'canny',thresh,sigma)
[BW,threshold] = edge(x,'canny',...)
since you have presented your problem domain to be CT-images. I have a good suggestion for you to extract the region of the brain tissues. There is a good assumption you can make.
A good assumption:
The brain region has no bones(normal cases) other than the cranium, and, based on some properties of CTs, you can easily extract(or remove) the bone(the cranium in this case) by looking up the Hounsfield Scale (http://en.wikipedia.org/wiki/Hounsfield_scale)
0) To get the correct housefield units, you need three elements i) original pixel value ii) rescale slope iii) rescale intercept (all three can be located in the original dicom header and HU can the be computed based on our high school math knowledge: y=mx+b, since you have the intercept, the slope and the input value).
1) Once you know where the bone is, you just need to subtract your image to get anything bounded by the cranium.
2) And upon looking at your matlab codes, im sure you can perform step 1) to segment the right regoin from the leftovers.
Just for the record. Mathematica code:
Edit
If you want only to extract the brain without tracing the outline, it is actually easier:
Related
Hello I have a work on this image:
My objective is to count all the sperm in this image .for this I'm thinking to detect just the lines so it make my work easy. because I am beginner, in this step I am completely lost there are any algorithms can help me to detect lines?? ( I have seen that there are hough transformation and scan line algorithm) I don't which algorithm can help me and if there are others
Here's a piece of code that might help you getting started.
By looking at the image it seems very difficult to label sperms by looking at straight lines and hence using Hough transform won't help a lot.
In the example below I focused on filtering the image and counting the number of blobs. The code is commented and should be easy to understand.
img = imread('d9S3Z.png');
figure, imshow(img)
% convert to binary image
[X,map] = rgb2ind(img,0.0);
img = ind2gray(X,map); % Convert indexed to grayscale
level = graythresh(img); % Compute an appropriate threshold
% or use your own, e.g. level = 0.46
img_bw = im2bw(img,level);% Convert grayscale to binary
% create mask to remove edge interference
mask = zeros(size(img_bw));
mask(2:end-2,2:end-2) = 1;
img_bw(mask<1) = 1;
%invert image
img_inv =1-img_bw;
% find blobs
img_blobs = bwmorph(img_inv,'majority',10);
figure, imshow(img_blobs);
% count blobs
CC = bwconncomp(img_blobs);
num_sperm = CC.NumObjects # sperm count
I need to find similar corners in image (for example: 4 corners of a rectangle, same corners, just different orientation?).
I have this code:
% read the image into MATLAB and convert it to grayscale
I = imread('s2.jpg');
Igray = rgb2gray(I);
figure, imshow(I);
% We can see that the image is noisy. We will clean it up with a few
% morphological operations
Ibw = im2bw(Igray,graythresh(Igray));
se = strel('line',3,90);
cleanI = imdilate(~Ibw,se);
figure, imshow(cleanI);
% Perform a Hough Transform on the image
% The Hough Transform identifies lines in an image
[H,theta,rho] = hough(cleanI);
peaks = houghpeaks(H,10);
lines = houghlines(Ibw,theta,rho,peaks);
figure, imshow(cleanI)
% Highlight (by changing color) the lines found by MATLAB
hold on
After running this code I convert my starting image into a binary image with:
binary = im2bw(I);
after this I get a product from those 2 binary images and I think I get corners..
product = binary .* cleanI;
now I imfuse this picture with grayscale starting picture and get this:
I dont know what to do to get only those 4 corners!
Ok second try. Below a code that does not finally do the job but it might help.
Edge identifies the contours and with regionprops you get the characteristica of each identified element. As soon as you know what characteristics your desired object has you can filter it and plot it. I went through the Areas in shapedata.Area and the 6th largest was the one you were searching for. If you combine Area with some of the other charateristica you might get the one you want. As I said not ideal and final but perhaps a start ...
clear all
close all
source = imread('Mobile Phone.jpg');
im = rgb2gray(source);
bw = edge(im ,'canny',[],sqrt(2));
shapedata=regionprops (bwlabel(bw,8),'all');
%index = find([shapedata.Area]== max([shapedata.Area]));
index = 213;
data = shapedata(index).PixelList;
figure
imshow(im)
hold on
plot(data(:,1),data(:,2),'ro');
I have an image shown below:
I am applying some sort of threshold like in the code. I could separate the blue objects like below:
However, now I have a problem separating these blue objects. I applied watershed (I don't know whether I made it right or wrong) but it didn't work out, so I need help to separate these connected objects.
The code I tried to use is shown below:
RGB=imread('testImage.jpg');
RGB = im2double(RGB);
cform = makecform('srgb2lab', 'AdaptedWhitePoint', whitepoint('D65'));
I = applycform(RGB,cform);
channel1Min = 12.099;
channel1Max = 36.044;
channel2Min = -9.048;
channel2Max = 48.547;
channel3Min = -53.996;
channel3Max = 15.471;
BW = (I(:,:,1) >= channel1Min ) & (I(:,:,1) <= channel1Max) & ...
(I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
(I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
maskedRGBImage = RGB;
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;
figure
imshow(maskedRGBImage)
In general, this type of segmentation is a serious research problem. In your case, you could do pretty well using a combination of morphology operations. These see widespread use in microscopy image processing.
First, clean up BW a bit by removing small blobs and filling holes,
BWopen = imopen(BW, strel('disk', 6));
BWclose = imclose(BWopen, strel('disk', 6));
(you may want to tune the structuring elements a bit, "6" is just a radius that seemed to work on your test image.)
Then you can use aggressive erosion to generate some seeds
seeds = imerode(BWclose, strel('disk', 35));
which you can use for watershed, or just assign each point in BW to its closest seed
labels = bwlabel(seeds);
[D, i] = bwdist(seeds);
closestLabels = labels(i);
originalLabels = BWopen .* closestLabels;
imshow(originalLabels, []);
I would try the following steps:
Convert the image to gray and then to a binary mask.
Apply morphological opening (imopen) to clean small noisy objects.
Apply Connected Component Analysis (CCA) using bwlabel. Each connected component contains at least 1 object.
These blue objects really look like stretched/distorted circles, so I would try Hough transform to detect cicles inside each labeled component. There is a built-in function (imfindcircles) or code available online (Hough transform for circles), depending on your Matlab version and available toolboxes.
Then, you need to take some decisions regarding the number of objects, N, inside each component (N>=1). I don't know in advance what the best criteria should be, but you could also apply these simple rules:
[i] An object needs to be of a minimum size.
[ii] Overlaping circles correspond to the same object (or not, depending on the overlap amount).
The circle centroids can then serve as seeds to complete the final object segmentation. Of course, if there is only one circle in each component, you just keep it directly as an object.
I didn't check all steps for validity in Matlab, but I quickly checked 1, 2, and 4 and they seemed to be quite promising. I show the result of circle detection for the most difficult component, in the center of the image:
The code I used to create this image is:
close all;clear all;clc;
addpath 'circle_hough'; % add path to code of [Hough transform for circles] link above
im = imread('im.jpg');
img = rgb2gray(im);
mask = img>30; mask = 255*mask; % create a binary mask
figure;imshow(mask)
% filter the image so that only the central part of 6 blue objects remains (for demo purposes only)
o = zeros(size(mask)); o(170:370, 220:320) = 1;
mask = mask.*o;
figure;imshow(mask);
se = strel('disk',3);
mask = imopen(mask,se); % apply morphological opening
figure;imshow(mask);
% check for circles using Hough transform (see also circle_houghdemo.m in [Hough transform for circles] link above)
radii = 15:5:40; % allowed circle radii
h = circle_hough(mask, radii, 'same', 'normalise');
% choose the 10 biggest circles
peaks = circle_houghpeaks(h, radii, 'nhoodxy', 15, 'nhoodr', 21, 'npeaks', 10);
% show result
figure;imshow(im);
for peak = peaks
[x, y] = circlepoints(peak(3));
hold on;plot(x+peak(1), y+peak(2), 'g-');
end
Some spontaneous thoughts. I assume the ultimate goal is to count the blue corpuscles. If so, I would search for a way to determine the total area of those objects and the average area of a corpuscle. As a first step convert to binary (black and White):
level = graythresh(RGB);
BW = im2bw(RGB,level);
Since morphological operations (open/close) will not preserve the areas, I would work with bwlabel to find the connected components. Looking at the picture I see 12 isolated corpuscles, two connected groups, some truncated corpuscles at the edge and some small noisy fragments. So first remove small objects and those touching edges. Then determine total area (bwarea) and the median size of objects as a proxy for the average area of one corpuscle.
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.
I have a set of shapes in an image I would like to label according to their area, I have used bwboundaries to find them, and regionprops to determine their area. I would like to label them such that they are labelled different based on whether their area is above or below the threshold i have determined.
I've thought about using inserObjectAnnotation, but I'm not sure how to add on a condition based on their area into the function?
Assuming TH to be the threshold area and BW to be the binary image and if you are okay with labeling them as o's and x's with matlab figure text at their centers (centroids to be exact), based on the thresholding, see if this satisfies your needs -
stats = regionprops(BW,'Area')
stats2 = regionprops(BW,'Centroid')
figure,imshow(BW)
for k = 1:numel(stats)
xy = stats2(k).Centroid
if (stats(k).Area>TH)
text(xy(1),xy(2),'L') %// Large Shape
else
text(xy(1),xy(2),'S') %// Small Shape
end
end
Sample output -
You could use CC = bwconncomp(BW,conn).
To get the number of pixels of every connected compontent you can use:
numPixels = cellfun(#numel,CC.PixelIdxList);
In CC.PixelIdxList you have a list of all found objects and the indices of the pixels belonging to the components. I guess to label your areas you could do something like:
for ind = 1:size(CC.PixelIdxList,2)
Image(CC.PixelIdxList{ind}) = ind;
end