compare pixel values to each other? Is ther afunction in Matlab that can analyze the composition of an image as a function of distance?
4 次查看(过去 30 天)
显示 更早的评论
I am interested in looking at how the image changes over a distance within the image, any recommendations?
Thanks!
8 个评论
Walter Roberson
2022-12-16
编辑:Walter Roberson
2022-12-16
What do you mean by "composition of an image" in this situation ? What is "distance" in this situation ?
You can calculate distances between positions in an image without too much difficulty if distances are linear.
WIth the Computer Vision toolbox, you can correct for image distortion before calculating distances with a little more work.
But if you have uncorrected perspective then figuring out distances can be tricky. Is the brick wall curving away, allowing you to use the mortor for distance calculations, or is it just an oddly shaped object that happens to be squished-looking toward the edges?
Neo
2022-12-21
移动:Walter Roberson
2022-12-21
By composition of the image I mean:
Determining the area, size and density of the spot in the image that you want to know. For example if I have a cell in the image I want to know that cells composition: area, size and density. Thank you I hope that’s more specific
Walter Roberson
2022-12-21
移动:Rena Berman
2022-12-22
And you want to know how the size and area and density of the one cell changes over distance from ... something??
Neo
2022-12-21
移动:Rena Berman
2022-12-22
It’s not a cell it’s just an example because I’m still trying to identify the image but yes if it’s a cell I want to know the size area and density of the cells in one region and how they change over the length of the image.
Image Analyst
2022-12-22
If you have any more questions, then attach your image and code to read it in with the paperclip icon after you read this:
And somehow indicate, in a separate image, the things in the image you'd like to use in computations.
采纳的回答
Image Analyst
2022-12-22
That pretty much explains the basics. You can probably adapt it to your particular image.
10 个评论
Neo
2022-12-26
I actually did try that. Happy holidays.
i had a good look and I am not sure how your image processing tutorial can spit out the density, area and size of the region of interests.
Neo
2022-12-26
@Image Analyst I found it super insightful and learned alot but how can I adapt it to measure the area, size and density of the regions of interests in my image?
Image Analyst
2022-12-27
roi variables have a createMask method that you can call to get the binary image mask. Or you can call createMask and pass it the roi variable as an input. Some ROI drawing demos attached.
Image Analyst
2022-12-27
@Neo did that help? If not, attach your image and say what the ROI is and how you determined it, like from thresholding or from manual drawing.
If you have any more questions, then attach your data and code to read it in with the paperclip icon after you read this:
Neo
2022-12-28
Thank you @Image Analyst. I used the first polygon code attachment. (draw multiple..) and I tried to get the density, area and size of the region of interest.
i have googled this extensively and I am confident that my question is posed correctly. My question stated boils down to: How do I properly call regionprops to get the area, density and size of a ROI? Here's my code:
% Demo to draw multiple polygons with roipoly() and make a single binary image from them all.
%----- Initializing steps -----
% Clean up
clc;
clear vars;
close all;
workspace; % Display the workspace panel.
fontSize = 20;
hasIPT = license('test', 'image_toolbox');
if ~hasIPT
% User does not have the toolbox installed.
message = sprintf('Sorry, but you do not seem to have the Image Processing Toolbox.\nDo you want to try to continue anyway?');
reply = questdlg(message, 'Toolbox missing', 'Yes', 'No', 'Yes');
if strcmpi(reply, 'No')
% User said No, so exit.
return;
end
end
% Display images to prepare for the demo.
originalImage = imread('coins.png');
[rows, columns, numberOfColorChannels] = size(originalImage);
subplot(2, 2, 1);
imshow(originalImage);
title('Original Image. DRAW POLYGON HERE!!!', 'FontSize', fontSize);
subplot(2, 2, 2);
imshow(originalImage);
subplot(2, 2, 4);
imshow(originalImage);
title('Original Image with regions burned into image', 'FontSize', fontSize);
set(gcf, 'units','normalized','outerposition',[0 0 1 1]); % Maximize figure.
set(gcf,'name','Image Analysis Demo','numbertitle','off')
%----- Ask user to draw polygons ---------------------------------------------------------------------
% Create a binary image for all the regions we will draw.
cumulativeBinaryImage = false(rows, columns);
subplot(2, 2, 4);
imshow(cumulativeBinaryImage);
title('Cumulative Binary Image', 'FontSize', fontSize);
% Create region mask, h, as an ROI object over the second image in the bottom row.
axis on;
again = true;
regionCount = 0;
while again && regionCount < 20
promptMessage = sprintf('Draw region #%d in the upper left image,\nor Quit?', regionCount + 1);
titleBarCaption = 'Continue?';
button = questdlg(promptMessage, titleBarCaption, 'Draw', 'Quit', 'Draw');
if strcmpi(button, 'Quit')
break;
end
regionCount = regionCount + 1;
% Ask user to draw freehand mask.
message = sprintf('Left click vertices in the upper left image.\nRight click the last vertex to finish.\nThen double click in the middle to accept it.');
uiwait(msgbox(message));
subplot(2, 2, 1); % Switch to image axes.
% Ask user to draw a polygon.
% Use roipolyold() if you want to finish at the right click
% and not have the user need to double-click inside the shape to confirm it.
% [thisSinglePolygonImage, xi, yi] = roipolyold();
% Use roipoly() if you want to close the polygon at the right click
% but give the user the opportunity to adjust the positions of the vertices, and then
% the user needs to double-click inside the shape to confirm/accpet it.
[thisSinglePolygonImage, xi, yi] = roipoly();
% Display the last drawn polygon.
subplot(2, 2, 3);
imshow(thisSinglePolygonImage);
caption = sprintf('Binary mask you just drew');
title(caption, 'FontSize', fontSize);
% Draw the polygon over the image in the upper right.
subplot(2, 2, 2); % Switch to upper right image axes.
hold on;
plot(xi, yi, 'r-', 'LineWidth', 2);
caption = sprintf('Original Image with %d regions in overlay.', regionCount);
title(caption, 'FontSize', fontSize);
% OR it in to the "all regions" binary image mask we're building up.
cumulativeBinaryImage = cumulativeBinaryImage | thisSinglePolygonImage;
% Display the regions mask.
subplot(2, 2, 4);
imshow(cumulativeBinaryImage);
caption = sprintf('Binary mask of the %d regions', regionCount);
title(caption, 'FontSize', fontSize);
end
% cumulativeBinaryImage is your final binary image mask that contains all the individual masks you drew.
%WHERE MY CODE ATTEMPT BEGINS
BW = a < 100;
info = regionprops('table',BW, 'density', 'area', 'size')
Image Analyst
2022-12-28
Not sure how you're defining "density" but maybe it's MeanIntensity. So you'd change the last 3 lines of the program to look like:
% WHERE MY CODE ATTEMPT BEGINS
info = regionprops('table', cumulativeBinaryImage, originalImage, 'MeanIntensity', 'Area', 'EquivDiameter')
allAreas = info.Area;
allDiameters = info.EquivDiameter;
allIntensities = info.MeanIntensity;
I drew 2 regions and got this:
info =
2×3 table
Area EquivDiameter MeanIntensity
____ ________________ ________________
994 35.5752738213882 80.1750503018109
4549 76.1049715130375 115.819960430864
Full demo:
% Demo to draw multiple polygons with roipoly() and make a single binary image from them all.
%----- Initializing steps -----
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 20;
hasIPT = license('test', 'image_toolbox');
if ~hasIPT
% User does not have the toolbox installed.
message = sprintf('Sorry, but you do not seem to have the Image Processing Toolbox.\nDo you want to try to continue anyway?');
reply = questdlg(message, 'Toolbox missing', 'Yes', 'No', 'Yes');
if strcmpi(reply, 'No')
% User said No, so exit.
return;
end
end
% Display images to prepare for the demo.
originalImage = imread('coins.png');
[rows, columns, numberOfColorChannels] = size(originalImage);
subplot(2, 2, 1);
imshow(originalImage);
title('Original Image. DRAW POLYGON HERE!!!', 'FontSize', fontSize);
subplot(2, 2, 2);
imshow(originalImage);
subplot(2, 2, 4);
imshow(originalImage);
title('Original Image with regions burned into image', 'FontSize', fontSize);
set(gcf, 'units','normalized','outerposition',[0 0 1 1]); % Maximize figure.
set(gcf,'name','Image Analysis Demo','numbertitle','off')
%----- Ask user to draw polygons ---------------------------------------------------------------------
% Create a binary image for all the regions we will draw.
cumulativeBinaryImage = false(rows, columns);
subplot(2, 2, 4);
imshow(cumulativeBinaryImage);
title('Cumulative Binary Image', 'FontSize', fontSize);
% Create region mask, h, as an ROI object over the second image in the bottom row.
axis on;
again = true;
regionCount = 0;
while again && regionCount < 20
promptMessage = sprintf('Draw region #%d in the upper left image,\nor Quit?', regionCount + 1);
titleBarCaption = 'Continue?';
button = questdlg(promptMessage, titleBarCaption, 'Draw', 'Quit', 'Draw');
if strcmpi(button, 'Quit')
break;
end
regionCount = regionCount + 1;
% Ask user to draw freehand mask.
message = sprintf('Left click vertices in the upper left image.\nRight click the last vertex to finish.\nThen double click in the middle to accept it.');
uiwait(msgbox(message));
subplot(2, 2, 1); % Switch to image axes.
% Ask user to draw a polygon.
% Use roipolyold() if you want to finish at the right click
% and not have the user need to double-click inside the shape to confirm it.
% [thisSinglePolygonImage, xi, yi] = roipolyold();
% Use roipoly() if you want to close the polygon at the right click
% but give the user the opportunity to adjust the positions of the vertices, and then
% the user needs to double-click inside the shape to confirm/accpet it.
[thisSinglePolygonImage, xi, yi] = roipoly();
% Display the last drawn polygon.
subplot(2, 2, 3);
imshow(thisSinglePolygonImage);
caption = sprintf('Binary mask you just drew');
title(caption, 'FontSize', fontSize);
% Draw the polygon over the image in the upper right.
subplot(2, 2, 2); % Switch to upper right image axes.
hold on;
plot(xi, yi, 'r-', 'LineWidth', 2);
caption = sprintf('Original Image with %d regions in overlay.', regionCount);
title(caption, 'FontSize', fontSize);
% OR it in to the "all regions" binary image mask we're building up.
cumulativeBinaryImage = cumulativeBinaryImage | thisSinglePolygonImage;
% Display the regions mask.
subplot(2, 2, 4);
imshow(cumulativeBinaryImage);
caption = sprintf('Binary mask of the %d regions', regionCount);
title(caption, 'FontSize', fontSize);
end
% cumulativeBinaryImage is your final binary image mask that contains all the individual masks you drew.
% WHERE MY CODE ATTEMPT BEGINS
info = regionprops('table', cumulativeBinaryImage, originalImage, 'MeanIntensity', 'Area', 'EquivDiameter')
allAreas = info.Area;
allDiameters = info.EquivDiameter;
allIntensities = info.MeanIntensity;
Neo
2022-12-29
Do you know why when I put in my own image (not demo) it gives me the error:
Error using iptassert
Size of I doesn't match size information found in the first input argument.
Error in regionprops>ParseInputs (line 1411)
iptassert(isequal(sizeImage,size(I)), ...
Error in regionprops (line 248)
[I,requestedStats,officialStats] = ParseInputs(imageSize, argOffset, args{:});
Error in draw_multiple_polygons (line 90)
info = regionprops('table', cumulativeBinaryImage, originalImage, 'MeanIntensity', 'Area', 'EquivDiameter')
Neo
2023-1-6
@Image Analyst is the drawpoint program made to address very small and hard to see regions of interests?
Image Analyst
2023-1-6
No, drawpoints is for situations where you need to indicate single points/pixels on an image. drawrectangle and drawpolygon are for when you need to draw 2-D regions.
更多回答(1 个)
Walter Roberson
2022-12-21
The answer to your question is NO, there is no MATLAB function to analyze the composition of an image as a function of distance.
14 个评论
Neo
2022-12-21
How can I do it on my own then, if you know or can direct me to something that I can use to try to do it on my own.
Walter Roberson
2022-12-21
First you need to figure out where the cell boundaries are. Then you need to "label" the image, producing an array the same size in which each location gives an identifier about which of the cells the pixel belongs to (0 if not part of any cell.) Then you process the grayscale image, converting the intensity into a pixel weight.Then you call regionprops passing in the label image and the weight image, using the syntax that regionprops summarizes as
Ask for the properties Area, Centroid, MeanIntensity
The MeanIntensity will be the (average) density, provided that you supplied a valid weight image.
The conversion from intensity to pixel weight might take a bit of work. Different colors might imply different material compositions. Darker portions in the centre of a cell might relate to the cell nucleus, which would not just be thicker but denser than some of the other parts of the cell. Perhaps you are using a polarized light source, so you might be looking at texture information to get clues about the local density. Perhaps the shape of the nucleus might give information about the kind of cell it is and so influence the interpretation of the intensity conversion to local density.
Neo
2022-12-28
To address your comment, by density I mean g/volume. How do I specify in the code the interpretation of the density of interest? What do you mean by weight image? The colors do imply different material compositions. How can I accurately account for that? Thank you!
Walter Roberson
2022-12-28
If you know the RGB for an isolated pixel, can you figure out its material composition and so the implied density? Or do you need to see the RGB in the context of surrounding pixels in order to figure out the material composition?
For example, is this particular pixel this particular shade of red-ish because it is a dye-injected rubber ball, or because it is dye-injected plastic? Knowing only one isolated pixel might not be enough to say, but seeing a small number of adjacent pixels might potentially give enough information to allow you decide, hypothetically.
You might have to correct for uneven illumination before you analyze color to determine composition.
You might end up using a strategy such as quantizing Hue to guess about composition.
Neo
2022-12-28
I want to see the density values based on the different RGB values so I don’t want to correct for the difference. So if the density is different for red values vs blue I want to measure it. Does that make sense?
Walter Roberson
2022-12-29
Suppose you have a pixel that is (say) [240 27 93] and you have another pixel that is [200 23 78]
plot(1:10, .1*ones(1,10), 'color', [240 27 93]/255);
hold on
plot(1:10, .11*ones(1,10), 'color', [200 23 78]/255);
hold off
ylim([.05 .115])
Are they the same material or different material? If you look at them carefully, you can see that they do not look exactly the same, so you might need to assign them different materials. Rubber versus plastic for example. Different parts of a cell structure maybe.
But are they really different materials? Are are they the same material with slightly different lighting conditions? Is one of them in a little more shadow than the other? Is one of them the same material than the other, but the system is backlit and a part is slightly thicker and so cuts off more backlight? Or has the experiment been set up carefully so that the lighting can be treated as being uniform parallel rays over the entire field so that any variation in color is not due to differences in shadow or thickness ?
If you cannot reasonably model as uniform parallel rays, then you need to be considering doing correction for illumination.
im2uint8(double(img) ./ double(max(img, 3)))
which divides each location by the maximum component at that location. This treats each location as if it is potentially uniform material but subject to different lighting levels -- as opposed to a model where a pixel that is (say) 3/4 of each component of a different pixel, is different because it is inherently a different material. If you need to differentiate pixels in part by brightness instead of just by hue, then illumination correction becomes more difficult.
Walter Roberson
2022-12-29
There is typically no way to look at the pixels of an image and inherently read off density directly from them. Not necessarily impossible -- but it would need a setup such as a thin layer of liquid at each location and a uniform illumination from the top, and somehow the pixel color was tied to the density at the point (for the uniform volume there.) Maybe something like monochrome laser being attenuated differently for different densities. It can happen -- but it is rather unusual.
Instead you typically need to classify a given RGB value somehow as belonging to a given class of materials, and then look in a data table to find out what the density is associated with that class of material. Dull orange is "orange juice with lots of pulp", bright orange is "orange juice with a little pulp", black-ish is Coca-Cola ™ , this shade of red is Mountain Dew ™ and so on, and you have stored information about density of each of those kinds of materials.
Neo
2022-12-29
I have classified the regions in the image based on their RGB values or their physical traits, so are you saying from there that I would write a code that would actively calculate the density based on those physical traits and stored density vlaues?
Walter Roberson
2022-12-29
Yes. It is quite uncommon to be able to read out density of a pixel directly. It is more common that you need to map pixel color or texture information to material and pull out the known density for the kind of material.
Once you have created an array the same size as the image, but containing the per-pixel density associated with the material, you can pass that pixel density as the second parameter to regionprops, with the first parameter being the label image. Ask for mean intensity in order to find the density of the region (as opposed to the density of a point.) This will be equivalent to summing the per-point density information over the region and dividing by the number of pixels in the region. Then you can compare region densities between regions.
Image Analyst
2022-12-29
Why don't we race to the solution and you just show us your image? If you have any more questions, then attach with the paperclip icon, or insert your image with the frame icon, after you read this:
In the meantime, to illustrate what Walter said, assume this is your image:
So we have a white background (countertop), red strawberries, and turquoise stone nuggets. Now all you have is this image. Of course you can do color segmentation and find the mean RGB values of the strawberries and turquoise, but how are you going to know, from only those values, in the range 0-255, that the density of turquoise is 2.7 grams/cc and the density of strawberries is 0.59 grams/cc? Answer: You can't. That is something you'd need to obtain in some other way than analyzing an image.
Neo
2022-12-29
I think I can attain the answer by finding its size and area correct? Also here is an example image it is in tif format in the code but I uploaded it jpg here for formating convenience.
But why did i get the error?
Error in regionprops>ParseInputs (line 1411)
iptassert(isequal(sizeImage,size(I)), ...
Error in regionprops (line 248)
[I,requestedStats,officialStats] = ParseInputs(imageSize, argOffset, args{:});
Error in draw_multiple_polygons (line 90)
info = regionprops('table', cumulativeBinaryImage, originalImage, 'MeanIntensity', 'Area', 'EquivDiameter')
Image Analyst
2022-12-29
编辑:Image Analyst
2022-12-29
originalImage must be a gray scale image. Yours is not. You can do
originalImage = originalImage(:, :, 2); % Take green channel
It looks like you have a fluorescence image so you would not do a background division like usual. For radiography (x-rays) and fluorescence you do background subtraction. For most other situations you do background division. You'd do a background subtraction. But your background looks pretty black and uniform so that is probably not even necessary.
Just a slight correction to what @Walter Roberson said about how I do background correction. I don't divide by the max of any color channel. I divide by a smoothed version of each color channel individually. This is because the lens shading and transverse chromatic aberration of the lens might be wavelength dependent. In other words, it might taper off on the sides of the image more for one color channel than another so I need to correct for each color channel independently. This could be a whole hour long discusson but I won't go into that here. I'll just attach the image of an actual white background image taken from one of our light booths (a small JPG version -- less than 5 MB so I can upload it) and script to take vertical and horizontal profiles so you can see how the shading varies by color channel.
Note the profiles are still very noisy. This is most likely not due to illumination non-uniformities because light wouldn't vary that much on a small scale. The non-uniformities are most likely due to variations in the white substrate itself, and slightly due to optical noise remaining in the image. The overall differences between the different color channels is most likely due to chromatic aberration of the lens. The lens shading is different for optical wavelengths in the red, green, and blue regions of the spectrum. This will affect both the overall intensity level as well as the amount of shading (darkening) across the image.
The spectrum of the white substrate is almost perfectly flat - I checked with a spectrophotometer. The light is "white" light LED so it's possible there could be a difference in the overall levels of the red, green, and blue light due to the particular way the spectrum of the light interacted with the spectral responsivities of the imaging sensor. For example the light is a "warm white" so there would be more red light being emitted. Note the top and right side of the image is more neutral than the bottom or left edge of the image.
If you want, I can upload my background correction, color correction, and color calibration seminar.
Neo
2022-12-29
Yes I think that would be helpful. Just to be safe how would I perform background substraction and also masking to get rid of other specs in the image that I might not be interested in for the future.
Image Analyst
2022-12-29
See attached seminar on background correction, color correction, and color calibration. I've just updated some slides from what I've posted in the past years..
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!发生错误
由于页面发生更改,无法完成操作。请重新加载页面以查看其更新后的状态。
您也可以从以下列表中选择网站:
如何获得最佳网站性能
选择中国网站(中文或英文)以获得最佳网站性能。其他 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 (한국어)