現在この質問をフォロー中です
- フォローしているコンテンツ フィードに更新が表示されます。
- コミュニケーション基本設定に応じて電子メールを受け取ることができます。
Measurement in Images - Image Analysis
52 ビュー (過去 30 日間)
古いコメントを表示
Kev
2013 年 5 月 21 日
Hello there!
I'm faced with a project in which I'm assigned to have matlab calculate the fiber diameter from the images. We obtain these images from electron microscope. I've used ImageJ software for image processing and then calculating the diameter from the software. However, the process is tedious since we have lots of images and would like to automate the process. I've learned the macro feature in ImageJ, but it is the obtaining points from the picture that takes much of the time. Please, have a look at the sample microscopic image so you can have an idea. :)
Here is our process for ImageJ software:
1) Make image Smooth
2) Find Edges
3) Adjust Brightness/Contrast
4) Turn image into Binary
5) Use the line tool to calculate the distance b/w two fiber edges (the line is positioned perpendicularly along the fiber)
6) Paste the data into Excel and then calculate the fiber diameter by subtracting the distance along the line. We differentiate by black area and white area.
I can macro/automate part 1-4, but we would like to automate entire process, or most of it since we have lots of images.
So far, I have learned image processing in matlab. I have learned bw functions, gaussian filter, finding edges using different methods (prewitt, canny, sobel and etc.) I have no idea on how I can make matlab identify the fibers in images and then calculate the fiber diameter and then export it. Do note, there are regions where fiber overlaps with other fibers and that regions is little messy so calculate, so we avoid/reject that portions. I have attached a binarized image for your reference. I'd very much appreciate your input.
Sincrely,
Kev
12 件のコメント
Kev
2013 年 5 月 21 日
Matt Kindig
2013 年 5 月 21 日
I'm a little unclear how step 5 is performed? Do you just mean that the fiber diameter is determined by scaling the distance perpendicular to the fiber thickness by the microscope scale (5.00 um)? Or is there something more tricky going on? Could you upload an image showing how you've defined the "fiber diameter"?
Matt Kindig
2013 年 5 月 21 日
Also, will there be a single value of fiber diameter for each image, or do you have to take multiple thickness measurements? At what spacing do you need to take these measurements?
Kev
2013 年 5 月 21 日
It will be multiple measurements since fiber diameter would range slightly. There is no spacing necessary as long most of the fibers are considered. We can reject the outliers and the region where fibers overlap.
Image Analyst
2013 年 5 月 21 日
Why do that instead of just taking the mean continuously over the entire fiber like my algorithm? Why get fewer diameter samples and be more sensitive to noise than just bulk processing the whole image to get the overall mean diameter?
kanu
2014 年 2 月 26 日
I am working on retinal image. Can u tell me above measurement in images code. how you find out the diameter of any edges.
Image Analyst
2014 年 2 月 26 日
Edges don't have any diameter. Retinal image analysis methods are explained in Section 20.5 here in VisonBib
kanu
2014 年 2 月 26 日
edges diameter is change,i agree. but we can choose any place & calculate distance at different places of retinal vessel. I make my image smooth, find edges, brightness also adjust, binary conversion is also done. Now how to apply line tool on vessel edges is my problem? i think above kev's code will help me..plz image analyst try to solve my problem.
Image Analyst
2014 年 2 月 26 日
Sorry but this is not an easy problem to solve. Why do you think people work months or years on algorithms and then publish them? If there are publications on it, it's not trivial. It's not like some 5 minute demo I can whip together for you. You'll have to put a lot of work into it. Good luck.
Image Analyst
2014 年 2 月 26 日
I outlined my approach in my answer below but Kev chose to use a different approach. I'll help with code if it doesn't take too much time, so if you have something simpler in the future I can write some code, or if it's complicated I may just outline an algorithm, like I did for Kev, or point you to a place where you can find the answer, such as web sites like VisionBib which has virtually every paper on image processing ever published.
回答 (3 件)
Image Analyst
2013 年 5 月 21 日
That's not how I'd do it. First of all I wouldn't do edge detection - it's not necessary since the image is already basically an edge image. So first I'd take a blank shot (no fibers) and get a blank background image. Then smooth it and divide your test images by it to correct for local non-uniformities in the illumination. Then, for each background corrected image
- Threshold the image
- Fill in the centers of the fibers using the Euclidean Distance Transform (performed by bwdist()) and identifying regions with a small mean EDT value. Now you have solid fibers and you're practically done.
- Sum up the image - this gives you the area of the fibers.
- Skeletonize the fibers with bwmorph('skel')
- Sum up that image - this gives you the total length of all the fibers.
- Divide the area by the length to give you the mean width of the fibers.
The only somewhat tricky part is step #2. For that you need to find non-zero parts of the EDT image and use regionprops to find out the mean value of each region. Central fiber shafts will have small mean EDT values while the background will have huge mean EDT values. Then use ismember to extract out only the small regions - see my image segmentation tutorial at http://www.mathworks.com/matlabcentral/fileexchange/?term=authorid%3A31862 for an example of how to use ismember to do filtering like that. So after this you have a binary image of the center shafts of the fibers and you can use that to fill in the rest of the fibers. Then it's ultra simple to do steps 3-6 after that.
34 件のコメント
Kev
2013 年 5 月 22 日
編集済み: Kev
2013 年 5 月 22 日
Thanks my friend! Thanks for the outlining the steps. However I have a few queries. What is blank shot and blank background procedure for? Also, how should I perform that action? By correcting for non-unoformalities, you mean to correct for non-uniform illumination, right? I'm trying to understand your method. I understand image thresholding. If I understand correctly, your approach is to fill in the fibers then calculating the area. Then you use skeleton function to calculate fiber length and lastly, you obtain diameter from simple mathematical operation.
I'd like to point out that microscopic images are not perfectly focused (microscope issue). Some portions are bit blurry. Upon adjusting contrast and, we sometimes lose a portion of a fiber. It disappears into white. Will this method work? I'll take a look at your image segmentation examples and your matlab scripts also.
I'd like to understand the concepts theoretically too. I have basic knowledge of Matlab program. What textbooks or materials would you recommend for image processing and analysis? At present, I'm using Digital Image Processing for Matlab by Gonzelaez, but is there any image analysis book you would recommend?
Sincerely,
Kev
Microscopic image (slightly blurry at the bottom): http://s24.postimg.org/91padvdj9/6202_D_1000_X_18wv_25_G_20_KV_15cm_0_5mlh_2.jpg
Kev
2013 年 5 月 22 日
編集済み: Kev
2013 年 5 月 22 日
Also, I was thinking I can do image processing with with click of a button/GUI and then I can mouse over to the fiber region, draw a somewhat perpendicular line. I'd have matlab adjust the perpendicular line automatically then calculate the distance like that. This will not be too tedious. Copy/Pasting the data took much of our time, so after hand-picking the points and visually displaying the fiber diameters, we can have the program export selected fiber diamters into text or an excel file.
Image Analyst
2013 年 5 月 22 日
The concept behind background division is that if some pixel out at the corner has only 90% as much light as it should have, wouldn't you want to divide the image by 0.95 at that point to get it up to 100%? Of course you would. So you get an image that "should" be 100% completely uniform, but is not for some reason, such as the vignetting/shading that all camera systems have. Now you can divide and "fix" the shading problem.
So I think you understand. Basically we're going to assume the fibers are like a big rectangle. And if you know the area, and you know the length, you can calculate the width. Well it's not totally uniform in width since it might vary a pixel or two so this will give you the overall average width. So we fill it to get the area, then we skeletonize to get the length. Then divide to get the width. Make sense?
If it goes out of focus, then that could affect the width but it looks like those regions would be a very small portion so it won't affect the mean width very much. You could filter those out with a filter if you really thought they were going to cause a problem. But I doubt they will.
Kev
2013 年 5 月 22 日
編集済み: Kev
2013 年 5 月 22 日
Hi!
I've followed your instruction. Please have a look.
i = imread('abc.jpg');
bw = im2bw(i, 0.6);
imshow(bw)
d = bwdist(bw)
a = sum(d)
bw2 = bwmorph(bw, 'skel');
b = sum(bw2);
c = a/b = 0.1127. 5 um ~ 31 Pixels, but actual diameter is around 3 um. If c is pixel values, then 0.1127 pixels = 0.01817 um.
Also, I'm attempting to calculate diameter by observing binary intensity imshow('abc.jpg');
h = imline;
position = wait(h);
pos = getPosition(h)
This only give position in a matrix form. I can calculate the length of a line, but I think we can calculate the length along the fiber by observing binary intensity.
I was thinking I can make a gui to sketch lines along the fibers perpendicularly, have matlab measure the distance using color (binary) intensities. It's not necessary to calculate mean width. We're fine with 10-12 test points.
http://s24.postimg.org/9vn2l8j7p/Untitled2.png (Disregard lines with measured distance. I used imdistline function)
Image Analyst
2013 年 5 月 22 日
Hard to disregard since they are burned into the image. Can you give an image with no annotation on it and maybe I can look at it later tonight.
Kev
2013 年 5 月 22 日
https://dl.dropboxusercontent.com/u/44449411/6202D_1000X_18wv_25G_12KV_15cm_0.05mlh_1.jpg
Sean de Wolski
2013 年 5 月 22 日
@IA, I disagree with your suggestion to use the sum of the pixels to count the length. This will give the city-block distance not the quasi-euclidian distance.
I would recommend either:
1) Take the 'perimeter' from regionprops and divide it by two
2) Use the geodesic distance transform on each fiber with one of the end points selected. The maximum value will be the length using whatever distance metric your want
Image Analyst
2013 年 5 月 22 日
That's fine. I've not tried the geodesic transform yet - it's on my bucket list. It looks cool.
Jeff E
2013 年 5 月 22 日
I would add bwarea to the list, as it is a bit more straightforward way to get the length for an entire skeletonized image.
Kev
2013 年 5 月 29 日
編集済み: Kev
2013 年 5 月 29 日
Hi!
I've attempted the suggested answers. I've used both approaches with bwdist and rergionprops perimeter function, however, I wasn't getting diameter anywhere close to the actual diameter. When the perimeter function is used, it outlines all the perimeters (enclosed areas) within the images. Is there any way I can only outline the edges? I can then retry. :)
The following code is my initial approach, to outline the perimeters of fibers and have matlab calculate diameter by drawing a perpendicular line along the fiber. Matlab would determine the diameter by identifying the outline/color difference.
I'm looking for a way to reducing the fibers into just a line so that I can have matlab determine 100% perpendicular line.
I understand matlab can store the data/color information along the line, then I could subtract the distance by identifying the outermost (outlined) edges, but I'm not sure how I can achieve this. I'd really appreciate your input. :)
-----
My code thus far:
I = imread('(1).jpg');
g = rgb2gray(I);
K = imadjust(g,[0.55 0.69],[]);
bw = im2bw(K); %imshow(bw)
bw2 = imfill(bw,'holes');
bw4_perim = bwperim(bw2);
overlay1 = imoverlay(bw, bw4_perim, [1 1 0]);
imwrite(overlay1, 'overlayimg1.png');
figure, imshow('overlayimg1.png');
h = imline;
position = wait(h);
%bw5 = bwmorph(bw,'skel'); (for adjusting user drawn somewhat perpendicular %line to 100% perpendicular line)
----------------------------------------------------------------------------
Link to sample fiber images: https://dl.dropboxusercontent.com/u/44449411/%281%29.jpg https://dl.dropboxusercontent.com/u/44449411/overlayimg1.png
Jeff E
2013 年 5 月 29 日
If you look closely at your bw4_perim image, you'll notice that the mask is positive around most of the edges of the image. This results in much more perimeter being identified than there should be. You can alleviate this a bit by taking the logical inverse of your b4 image before applying bwperim, but you'll still have some extra perimeter.
The following lines of code identify the edges of your image, and remove them from your edge image:
edgemask = bwperim(true(size(bw4)));
bw4_perim = bw4_perim & ~edgemask;
Kev
2013 年 5 月 29 日
編集済み: Kev
2013 年 5 月 29 日
Hi Jeff!
I have removed the following two lines from the codes. I find erosion and areaopen unnecessary in this instance. I've also applied edgemask but I didn't notice any difference. Perhaps, your comment was in regards to my earlier code.
bw3 = imopen(bw2, ones(5,5));
bw4 = bwareaopen(bw3, 40);
I'm looking to make this kind of skeleton (bottom right picture) of the fibers to be able to make a perpendicular line along the fiber. There is a script on file exchage, but it doesn't appear to be working right. http://www.mathworks.com/matlabcentral/fileexchange/25865-euclidean-skeleton
Jeff E
2013 年 5 月 29 日
Well, given the one link to the example image, this code works for me to obtain a fiber thickness that is pretty close to what I measure by hand:
I = imread('6202_D_1000_X_18wv_25_G_12_KV_15cm_0_05mlh_1.jpg');
g = rgb2gray(I);
K = imadjust(g,[0.55 0.69],[]);
bw = im2bw(K); %imshow(bw)
bw2 = imfill(bw,'holes');
bw3 = imopen(bw2, ones(5,5));
bw4 = bwareaopen(bw3, 40);
bw4_perim = bwperim(bw3);
edgemask = bwperim(true(size(bw4)));
bw4_perim = bw4_perim & ~edgemask;
fiber_length = bwarea(bw4_perim) / 2;
fiber_area = sum(sum(~bw4));
fiber_thickness = fiber_area / fiber_length ;
Kev
2013 年 5 月 30 日
編集済み: Kev
2013 年 5 月 30 日
I have checked above code for our data. For each experiment, we have two pictures and the fiber thickness was roughly consistent. I'd like to know if the thickness calculated is in pixels? If so, I've converted the pixels into um and it comes to 1.71 um, which isn't the actual thickness. Actual thickness ~ 3.7 um (Scale > 31 Pixels = 5 um. Fiber thickness = 10.6137 pixles > 1.71 um).
Secondly, I'd like to know if fiber thickness would be compromised with imopen function? And if I change ones(5,5) matrix, the fiber thickness also changes.
Kev
2013 年 5 月 30 日
編集済み: Kev
2013 年 5 月 30 日
I'm getting (22.95 pixels) 3.7 um with imdistline. I've attached pictures for reference. I'm now looking to have matlab automatically calculate the distance using the perimeter/border (from yellow - yellow outermost edges). But, I'd also like to automatically have matlab determine perpendicular line if user drawn line is not 100% perpendicular to the fiber.
If anyone has any suggestion/pointers on how this can be achieved, it would be very much appreciated.
Jeff E
2013 年 5 月 30 日
The fiber_thickness is outputting pixels. From the picture you posted I am measuring the thickness at about 8 pixels, both manually and with the script. The scale bar, measured manually, is about 11 pixels for 5um, giving a pixel to micron ratio of 0.4545. You can apply a pixel to micron conversion like this:
pix_to_um = 0.4545;
fiber_thickness_microns = fiber_thickness * pix_to_um ;
This makes the fibers ~3.6 microns thick.
As to your second question, you can think of the imopen function used on a binary image as something that removes pixel structures that can't "fit" the given kernel. In this situation, you want the size of your kernel to be slightly larger than the largest white area you are trying to remove. I suggest you try playing around with the size of your kernel, and even to check out the strel function to define your kernels. I messed around with it a little bit, and larger kernels can adversely affect segmentation of fibers that run closely parallel to each other.
Kev
2013 年 5 月 30 日
編集済み: Kev
2013 年 5 月 30 日
Hi Jeff,
If I understand correctly, bwareaopen would remove objects below certain pixel values, whereas imopen would would multiply the image matrix with supplied matrix (ones, disk, diamond, and etc.). In essence, does it just multiply supplied matrix (in disk, diamond or line matrix format) with image matrix?
I've increased ones(7,7) and fibers appear very smooth (without any objects inside/outside), however, I think this matrix will only work for one image, wouldn't it? would this be ideal for batch processing? I've played around with bwareaopen also and it doesn't appear to make any difference in the images visually.
Secondly, am I missing something in the scale/ratio? When I scale the reference 5 um, it is ~ 31 pixels.
Zipped sample images for reference:
https://dl.dropboxusercontent.com/u/44449411/fib%20set%201.zip
Jeff E
2013 年 5 月 30 日
bwareaopen considers separately each contiguous white area in the image, and if the number of pixels in a given area is above the integer value given, the entire area is set to black. In the script above, the bwareaopen step removes any white area that is smaller than 40.
imopen is actually a sequential operation of an erosion then a dilation using the supplied matrix. Search the internet for "morphological opening" and check out the top few results.
I think the image you uploaded originally: http://s8.postimg.org/64tjh6fsl/6202_D_1000_X_18wv_25_G_12_KV_15cm_0_05mlh_1.jpg is at a different scale than your raw images. All my measurements and comments on kernel size are specific to that image.
Kev
2013 年 6 月 7 日
編集済み: Kev
2013 年 6 月 7 日
Hi!
I'm looking to make this program more robust. There are non uniform elements within the fibers itself. I have looked into binary image processing to remove them. I have defined strel function with different structure elements, but it affects the fiber area. I was thinking of filling in the fibers, so the non-uniform object may get replaced? I could use the filled area as fiber area in order to calculate fiber thickness, or is there any other technique to remove it.
Please have a look at the following two sample images for non uniform objects within the fibers:
I've also looked into bwdist transform, but those non-uniform elements are still visible.
Thank you very much for the support.
Image Analyst
2013 年 6 月 7 日
Filling could be a fix, like I originally suggested. I'mnot sure why you used imfill rather than thresholding teh EDT image like I suggested. I knew imfill() wouldn't work for your images because of the way they look (bright in the middle and going out to the edge of the image), and that's why I specifically didn't recommend imfill() and instead recommended using bwdist() instead. It's a little tricky (more than just a few steps) so perhaps you need my help. But I believe you can find the bright central core of the fibers and fill in just those. Please post your original images of the edge images you just referenced.
Kev
2013 年 6 月 7 日
編集済み: Kev
2013 年 6 月 10 日
Image_analyst, I only used imfill and strel function because I understood it. I'm learning the concept behind EDT. It essentially computes the straight line distance from closest black intensity.
Btw, Euclidean Transformed image looks much accurate (no change in thickness due to strel function.).
Can you help with threholding euclidean distance transformed image? I've tried imtool and adjusted contrast.
Original Jpeg Images:
Code:
clear all
I = imread('5.jpg');
g = rgb2gray(I);
fl = medfilt2(g);
imtool(fl);
%hist_eq = histeq(g, 256) ;
%ad = imadjust(hist_eq,[0.55 0.69],[]);
level = graythresh(fl);
bw = im2bw(fl, level);
%mtool(bw)
%bw = im2bw(hist_eq);
%imshow(bw);
edt = bwdist(bw, 'euclidean');
imtool(edt);
%bw2 = imfill(bw,'holes');
%se= strel('rectangle', [6 4]);
%bw3 = imopen(edt, se );
bw4 = bwareaopen(edt, 300);
bw4_perim = bwperim(bw4);
edgemask = bwperim(true(size(bw4)));
bw4_perim = bw4_perim & ~edgemask;
imtool(bw4_perim);
fiber_length = bwarea(bw4_perim) / 2;
fiber_area = sum(sum(~bw4));
fiber_thickness = fiber_area / fiber_length ;
pix_to_um = 0.16129;
fiber_thickness_microns = fiber_thickness * pix_to_um ;
disp(fiber_thickness_microns);
Kev
2013 年 6 月 11 日
編集済み: Kev
2013 年 6 月 11 日
Does any one have any suggestion on how to extract data from improfile? Using improfile I can get the distance along the line, or I'm looking to sketch a line along the fiber and then determine fiber diameter using binary values. It can determine thickness from outermost edges using corresponding binary values. Also, when a line is drawn along a fiber, it should be perpendicular to the fiber. So, I'm looking into thinning the fibers into a single line. However, my fibers still appear as dual lines. Will it always appear as such? And, how can I put skeletonized image behing binary image, so perpendicular line can be corrected.
I hope I'm being clear enough. I'd very much appreciate any input.
I've attempted EDT, but it is not giving right answer. Besides, I was told fibers cannot be assumed to be finite length in our situation.
^^ This distance (diameter) is very very accurate.
Kev
2013 年 6 月 12 日
編集済み: Kev
2013 年 6 月 12 日
I've discovered I could calculate diameter from Euclidean distance transform. I have compared the diameter obtained by EDT and ImageJ. It appears, there is only 1% error in the result. Perhaps, I can have matlab identify largest euclidean values at certain increments and multiply by 2 to get diameter. What do you think?
Btw, when I put imshow(edt), I don't get proper euclidean distance transform images (similar as in example or the one obtained by ImageJ. It used to show EDT image similar to ImageJ, but not anymore.
http://dl.dropboxusercontent.com/u/44449411/edt-imagej.png (edt by imagej)
Image Analyst
2013 年 6 月 12 日
That last image by imagej does not look like an edt image at all. I got a start on the edt code last week but didn't finish it. I've been doing an insane amount of world travel lately (Europe, US) and for the next two months (US, Europe, Asia, Latin America) so I don't have much time for in depth assistance of anyone.
Kev
2013 年 6 月 13 日
Enjoy your tours, Image Analyst. :) You may provide the support whenever time permits. In the meantime, can you tell if the pic uploaded @postimg is edt? I've looked into the Pixels or Euclidean values and I can obtain data only in solid white region (solid lines - no black line within fibers). I'd like to clear up the black stripes from fibers in order to be able to fully use this euclidean method to obtain diameter :)
http://s2.postimg.org/4sbdq7hop/edt0.png < Performed by matlab
EDT example @Mathworks.com
Code for Reference:
clear all
I = imread('(1).jpg');
%imtool(I);
g = rgb2gray(I);
%imtool(g);
fl = medfilt2(g);
level = graythresh(fl);
bw = im2bw(fl, level);
%imshow(bw)
edt = bwdist(bw, 'euclidean');
imtool(edt)
Kev
2013 年 6 月 17 日
編集済み: Kev
2013 年 6 月 17 日
Dear Matlab Experts,
I've learned of a way to fill in the fibers. Please have a look at the excerpt from the textbook, "The Image Processing Handbook by John C. Russ"
I was thinking of a way to put a color layer to fill in the gaps in the fibers, but this is nicer way to fill in the fibers. I'm at stuck at step (d). The author is inverting the image to find the holes and uses those holes to add on to original binarized image.
I'd very very much appreciate your input on how I can perform step (d). I think following this technique would eliminate the need for morphological processing, which changes fiber structures.
Sincerely,
Kev
Jeff E
2013 年 6 月 17 日
I refer to step d as a "closing by area", and is achieved by using the bwareaopen function:
bw_output_image = ~bwareaopen(~bw_input_image, area_of_hole_to_remove) ;
Jeff E
2013 年 6 月 17 日
My apologies for not being a bit more specific. The "area_of_hole_to_remove" should be more accurately named "area_below_which_all_holes_will_be_removed".
bwareaopen removes any contiguous objects below the specified area; the line of code I provided will remove any holes below the specified area.
Kev
2013 年 6 月 17 日
編集済み: Kev
2013 年 6 月 17 日
Hi Jeff,
I understand above bwareaopen removes objects below specified area, but perhaps I wasn't clear in explaining myself. I meant I can specify area values to be 10000 for example, but then it may also remove areas of interest.
I have uploaded a picture for reference. You may see triangle regions. I'm just playing with the code to see if I can extract only the gap areas and then I can combine/overlay on original binary image so I have solid fibers.
Thanks! :)
Jeff E
2013 年 6 月 17 日
Aha. I see. The below worked for me, with the caveat that the fibers along the edge of the image you uploaded didn't work due to the white border Matlab puts around figures. I'm hoping your actual image doesn't have that white border. You'll note this approach won't be perfect in that very small triangles won't be removed.
imgin = imread('abc2.png');
bwin = im2bw(imgin);
%make the size of this filter slightly larger than the width of your largest fiber
bw_open = imopen(bwin, strel('disk', 9));
bw_fin = imreconstruct(bw_open, bwin, 4);
Kev
2013 年 6 月 19 日
編集済み: Kev
2013 年 6 月 19 日
Hi Jeff,
I've implemented above lines and it is giving me solid fibers. Sincere thanks to Image_Analyst and JeffEA for ongoing support.
I'm looking to compare diameter obtained using EDT with manual (ImageJ or most accurate) method because I do see variations in diameter values. Some areas in same fibers I have ~ 10 % of error difference when compared with ImageJ. I'd like to mathematically determine whether this method is reliable and accurate. :)
If Matlab is calculating euclidean distance, should it not be very very same throughout the fiber? Suppose fiber is at 45 angle, is EDT calculated along 45 angle(perpendicularly) or horizontally?
How can I display text or annotation on image? I would not like to embed it in the image, just show the diameter after the line is drawn. I can pass string using text or annotation, but not integer/double values. I spent couple hours researching this. I must be missing something.
Lastly, how can I run the loop? How can I have a user draw a line over an image as many times as he wants.
Please have a look at the code. I'd appreciate if you can test it and provide feedback.
Thanks!
https://dl.dropboxusercontent.com/u/44449411/fib_dia.m
https://dl.dropboxusercontent.com/u/44449411/fib.zip (Sample Images)
Kev
2013 年 6 月 24 日
編集済み: Kev
2013 年 6 月 24 日
Found EDT Is calculated along straight line. I had know about it but wasn't too sure how it applied to fibers at angles. EDT falls short when fibers are at angles. The differences error is about 4.5 %.
I'm was thinking of another method. I found number of elements that are above zero, which means these are positive or on pixels and I can count these pixels to determine diameter, but it only works great if fiber is totally vertical.
Algorithm looks at the matrix of fibers. The matrix is created in rectangle form. It can work if I can make the matrix form from line to line only, so that way I can see positive pixels to count those pixels.
I'm looking to extract values along the line, so I can count on pixels to determine fibers. If you know any function or method, please share it.
I've figured out the for loop and text situation, btw.
extract_pos_element = bw_fin( pos(3): pos(4) , pos(1): pos(2));
on_pixels = extract_pos_element;
on_pixels_rows = sum(on_pixels~=0,2);
avg_row = sum(on_pixels_rows);
avg_dia_in_pixels = avg_row/size(on_pixels_rows, 1);
dia_in_microns = avg_dia_in_pixels/6.2;
disp(dia_in_microns)
http://pasteboard.co/B1ePevI.png [extracting elements along the line like box drawn.]
EDT findings:
Sean de Wolski
2013 年 6 月 26 日
Kev,
I think you would benefit a lot from the Vessel Tortuosity part of this webinar:
31 件のコメント
Kev
2013 年 7 月 2 日
編集済み: Kev
2013 年 7 月 2 日
Sean, that webinar was useful. Thanks!
I'm still looking for more robust and reliable approach. Euclidean transform is a good tool, but since the fibers aren't placed uniformly, EDT is not as accurate. I'm looking for a way to determine perpendicular distance along the fiber edges, which will give me true fiber thickness.
Sean de Wolski
2013 年 7 月 2 日
To do this you'll need to skeletonize the fiber, determine the local orientation at every few points, calculate the orthogonol orientation, and figure out how many pixels lie within this range that are part of the fiber.
I took one approach to it here:
Kev
2013 年 7 月 8 日
編集済み: Kev
2013 年 7 月 9 日
Hi Sean,
I'm able to skeletonize the fibers.
Global approach for determining fiber diameter:
- ~~ image processing binarization, filtering and etc
- skeletonize the fibers.
- overlay skeleton on to binary image with fibers filled in.
- user selects the fiber - by drawing a line or a dot
- program can determine orthogonal distance to fiber edges and return the fiber diameter
- repeat
- export data
Is this a proper approach?
Questions:
- How should I overlay skeleton on to binary image (with fibers filled in) fibers are filled in white, background is black. Skeleton can be a black line to distinguish. I've attempted adding two images, but it's not right.
Edit: I've tried imfuse function, but I'm looking to manipulate binary images and combine them in binary form to keep it simple. imfuse creates coloured image.
- How should I make matlab calculate orthogonal distance up to the fiber edges. I'm not sure how will matlab draw/determine orthogonal distance from skeleton to the edge.
Kev
2013 年 7 月 9 日
Looks like I keep struggling with determining orthogonal distance. I've searched matlab documentation, but haven't found a way to solve this.
I'd like to do this (as shown in the picture). It looks very simple to do, but I'm not able to achieve it.
Jeff E
2013 年 7 月 9 日
In that little snippet of image, take the center white line as your object (with 8-connectivity). Use regionprops to get the orientation of the major axis of the fitted ellipse, subtract 90 degrees to get the minor axis. Then use that to calculate the slope, along with any point on the line to find two points to make a line, or intersections with the pink-black border.
Jeff E
2013 年 7 月 10 日
Looking at that image you provided, the bwmorph operation 'spur' might also be helpful.
Kev
2013 年 7 月 11 日
I increased the spur value. Previous value seemed to have negligible effect. Can you explain again last line? I've used regionprops to get orientation of major axis and I've got minor axis by subtracting 90 degrees.
clear all
% Read image (RGB assumed)
read_image = imread('(5).jpg');
%imtool(read_image);
% Converts RGB image into grayscale image
colour_to_gray = rgb2gray(read_image);
%imtool(colour_to_gray);
% Apply median filtering on grayscale image for smoothing
filtered_image = medfilt2(colour_to_gray);
%imtool(filtered_image)
% Convert grayscale into Binary using Otsu Method
level = graythresh(filtered_image);
binarize_me = im2bw(filtered_image, level);
%imshow(binarize_me)
% Binary inversion to observe the empty region and to add these region with
% original image in order to fill in the fibers
inverted_binary= ~ binarize_me;
bw9 = bwareaopen(~inverted_binary, 10000) ;
i3 = binarize_me + bw9;
% size of this filter slightly larger than the width of your largest fiber
bw_open = imopen(i3, strel('disk', 8));
bw_fin = imreconstruct(bw_open, i3, 4);
bw_fin(bw_fin == 2) = 1;
bwinv = ~bw_fin;
%Skeletonization of solid fibers
bwm = bwmorph(bwinv, 'skel' , inf);
bwspur = bwmorph(bwm, 'spur' , 20);
% combining solid fibers with skeleton image for better visulization
% both in binary format
bwadded = ~bwspur == 0 + bwinv;
imshow(bwadded);
cc = bwconncomp(bwadded);
s = regionprops(cc, 'orientation' );
%Structure 2 cell then cell 2 mat and sub 90 to get minor axis.
orienntation = struct2cell(s);
%minor axis
sub90 = cell2mat(C)' - 90;
Kev
2013 年 7 月 16 日
編集済み: Kev
2013 年 7 月 16 日
Someone please help me. I'm lost. I'm learning all of this for the first time. I'm using several books as a reference, but I haven't found a single book that discusses measurement/calculation part with an example.
I learned regionprops function from matlab documentation, but I still don't know how I can manipulate it to follow above solution. Originally, I have considered this approach. It looks simple enough to me and seems doable.
Hopefully, I haven't offended anyone because I haven't selected any answer. The approach of mean fiber diameter is working well, but due to overlapping of fibers, I'd like to measure dia at several places in several fibers and then taking an average.
Sincerely,
Kev
Kev
2013 年 7 月 17 日
Sean,
I've sent an email at the email id (without Remove_me part) in your profile.
Zip package is also uploaded to dropbox: https://dl.dr opboxusercontent.com/u/44449411/Fiber%20Diameter.zip
Kev
2013 年 9 月 9 日
編集済み: Kev
2013 年 9 月 9 日
Hi Everyone,
I've been able to achieve my goal as I mentioned above. I can get fiber diameter using improfile and I obtain fiber diameter by identifying outermost edges.
At present, I'm looking for a better way to fill in the fibers. The method I used was mask and marker images to fill in the fibers, but when I used different image for calibration (which was about 10 microns glass fiber) I had to change these numbers. I'm looking for a more robust way to fill in the fibers. This step is crucial since skeleton images are created based on solid fibers. Also, I have to apply slight dilation on marker image to make the edge continuous. Is there any better way to make fibres solid. This is one approach I have come across. I've tried it, but I'm unable to do step d.
I appreciate your input. Thanks!
P.S. If possible, I'd also like to validate this method and code with an expert.
Edit: Is it possible to fill inside of the fiber edges only?
Saranya
2013 年 12 月 21 日
Hi kev, in my project i want to measure the thickness of a single chromosome so that i can find the centromere location( where the thickness is shorter). I am in need of matlab coding for measuring the thickness..
Can you help me..
Kev
2014 年 1 月 13 日
Hi Saranya!
I can help you with this. Please provide me a sample picture (original, without altering the resolution). I'll see if my program can determine this for you, or if it may require changes.
Soumitra
2014 年 1 月 15 日
Hi Kev, I have a similar project like fiber diameter measurement where fibers are crossing each other at some places. I have tried filling up the fibers to get solid fiber and then get skeleton of that. I am lost after that. How can I get fiber diameter from there? Can you please help me?
Kev
2014 年 1 月 21 日
編集済み: Kev
2014 年 1 月 21 日
Hi Soumitra,
I'd need to look at the image first to be able to comment on suggested methods. Can you post a sample picture? If you want to remove branchpoints, you can look at branchpoint removal function. Look at the following documentation on branchpoint. You can provide me your email for faster response.
Saranya
2014 年 1 月 23 日
Hi kev, in my project i want to measure the thickness of a single chromosome so that i can find the centromere location( where the thickness is shorter). I am in need of matlab coding for measuring the thickness..
Can you help me.
this is one of my input image
Kev
2014 年 1 月 28 日
編集済み: Kev
2014 年 1 月 28 日
Do you have batch of images to find measurements, or is it just one image? There is a free software imageJ that would allow you to get measurements. I looked at your image. What you can do is, get measurements on each line and then you can display each measurement on the image. Afterwards, you'd be able to observe and collect appropriate/correct measurements.
Saranya
2014 年 1 月 30 日
I want to compare 46 chromosome images. my input is Single chromosome.I tried on imageJ software before itself for Straightening purpose(to calculate the length). I should not use software for centromere identification.
Image Analyst
2014 年 1 月 30 日
Please explain "I should not use software for centromere identification." Do you mean any software at all, or just some published software for expressly that purpose, or somebody elses' software (like what we might give you here or in the File Exchange)?
Saranya
2014 年 1 月 31 日
Not like that sir. I was not supposed to use any softwares(like imageJ). I want to use only matlab coding to locate the centromere location.
Saranya
2014 年 2 月 1 日
Ya.. I accept it sir. I want to use only MATLAB software for finding the centromere location
Image Analyst
2014 年 2 月 1 日
Do you know how to program in MATLAB? I think you might have to do this on your own. I didn't see anything in the File Exchange. Check VisionBib for algorithms, and code one up.
Kev
2014 年 2 月 4 日
Hi Saranya,
You may want to use following reference book to write the matlab script. This is introduction to Matlab programming.
Good book for Image Processing:
kanu
2014 年 2 月 26 日
hey,how u find out the distance between the line points. I am working on retinal image. Where i want to find out the diameter of vessels. can u please help me.
Image Analyst
2014 年 2 月 26 日
I answered above, where you first asked: Retinal image analysis methods are explained in Section 20.5 here in VisonBib
Walter Roberson
2014 年 3 月 1 日
kanu asked,
hey kev,how u find out the distance between the line points. I am working on retinal image. Where i want to find out the diameter of vessels. can u please help me.
Kev
2014 年 3 月 4 日
I used the improfile function. You can have a line, for example, have a line along the image and you can obtain the data that correspond to individual points on the line. If you have a binary image, then you'd be able to identify the beginning and ending point. I hope this makes sense.
lu sun
2015 年 6 月 23 日
Hello Kev, I believe you have already solved this issue. Now I have the similar problems as you, could you maybe send me the code how you did this? It would be very appreciated!
Thank you!
参考
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!エラーが発生しました
ページに変更が加えられたため、アクションを完了できません。ページを再度読み込み、更新された状態を確認してください。
Web サイトの選択
Web サイトを選択すると、翻訳されたコンテンツにアクセスし、地域のイベントやサービスを確認できます。現在の位置情報に基づき、次のサイトの選択を推奨します:
また、以下のリストから Web サイトを選択することもできます。
最適なサイトパフォーマンスの取得方法
中国のサイト (中国語または英語) を選択することで、最適なサイトパフォーマンスが得られます。その他の国の MathWorks のサイトは、お客様の地域からのアクセスが最適化されていません。
南北アメリカ
- América Latina (Español)
- Canada (English)
- United States (English)
ヨーロッパ
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
アジア太平洋地域
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)