how to find pixel values and intensity of grayscale image and plot them (x-axis as pixel value and y-axis as pixel intensity)

I have an grayscale image with values ranging from -0.86 to 0.53. I want to extract pixel values of whole image and intensity of each pixel and plot them. The x axis should be pixel value and y-axis should be intensity and the x-axis interval is 0.2.
I got some solutions before to store pixel values by impixel but it store values according to row and column. Can anyone help me in this matter.

3 Comments

Define "pixel value" and "intensity". You're clearly making some distinction, but if you just have 2D data, then that's it. You have one metric. If there is some presumed fixed relationship between the two, then that information is unclear from the given information. It's also unclear why you'd want or need to plot it if the relationship were already fixed and known.
(replying to a comment that doesn't exist anymore)
If you want a histogram, then I don't see why the distinction between value and intensity is relevant. It's still not clear that it even exists.
If you want a histogram, just use histogram().
% some arbitrarily-scaled array
A = randn(100) + 4*randi([0 1],100,100);
% displayed with scaled colormapping
imshow(A,[])
% show the histogram
figure
h = histogram(A);
If you want the bin edges and counts, you can either get that information from the histogram object h, or you can use histcounts() instead.
I agree with @DGM - pixel value and pixel intensity are the same thing (to everyone except you). It makes no sense to plot one vs the other. Clarify not only what (you think) you need but why you want it (in other words what will you do with that information once you have it)

Sign in to comment.

 Accepted Answer

I'm going to go out on a limb and guess that this is where it's going. If the relationship is that between the data values and the graylevels used to render the image, then:
% some arbitrarily-scaled array
A = randn(10);
% displayed with scaled colormapping
imshow(A,[])
% input and output ranges
inrange = caxis(gca);
outrange = [0 1];
% some test input in the same range
x = linspace(inrange(1),inrange(2),1000);
% interpolate
grayval = interp1(inrange,outrange,x);
% quantize
nlevels = size(get(gca,'colormap'),1);
grayval = round((grayval*nlevels - 0.5)*(1-eps))/(nlevels-1);
grayval = imclamp(grayval);
% plot
plot(x,grayval)
xlabel('data value')
ylabel('gray level')
It's hard to see with the default map length, but that's not a straight line. It's a simple piecewise-constant approximation of a linear function. The parameters are input extrema and the colormap length. All other properties of the data are irrelevant. This graph tells us about the colormapping functionality. It doesn't tell us anything about the data other than its extrema. I don't know why we'd want to plot it.
Obviously this is not true for colormaps other than gray().
This is also only accurate if the map length is either 16 or 256. The above code associates the input levels with the actual gray value specified in the gray() colormap. What's actually displayed on screen will have been quantized once more to 256 levels as it's rendered on screen, and so the gray levels will no longer match the specified colormap exactly. They will no longer be uniformly distributed, and the result may no longer even represent the specified number of gray levels.
If you were using a map length other than 16 or 256, and you wanted to simulate the degraded ephemeral display copy instead of the ideal colormapped image, you could add one extra step:
% degrade the estimate to match the display
grayval = floor(grayval*255)/255;
I have no idea if this is even an answer to the question.

10 Comments

I have converted my grayscale image to binary image and compute histogram by code
clc;
clear all;
I=imbinarize(imread('E:\waterbody_project\processed_sen\mnwi.tif'));
[counts,binLocations]=imhist(I,2);
figure, histogram(I);
But I want the figure that vary between the range of my raster -0.5 to 0.6 or -0.5 to 1. Moreover the image is a square image (hist1.img). I want a histogram like I attached (hist.img). If thre is any way to get histogram like this?
If you're dealing with arbitrarily-scaled data, don't use imhist().
Without seeing the actual file, I can't know how the data is scaled in the file. Supposedly, the data range is [-0.86 0.53], but I don't know whether that includes or excludes the white background. It seems to me like it would include it, but that's just a guess.
To be clear, there are two things that I don't know. I don't know what image scale is, and I don't know whether to get the histogram of the entire image or just the land region. There are four possible outcomes. Here are two.
If we assume that [-0.86 0.53] are the extrema of the entire image. We can get the histogram for the whole image and/or the land region.
% this is just a partial screenshot,
% so scaling information has been lost
inpict = imread('sc.png');
inpict = im2gray(inpict);
% supposedly, this is what the data scale used to be?
% assume this maps to the extrema of the entire image
% if your TIFF is float, then you don't need to do this
inpict = rescale(inpict,-0.86,0.53);
% histogram of the whole image
histogram(inpict)
% find a mask
% this is going to be crusty, since this is a JPG screenshot
mask = inpict < 0.23; % difficult to exclude the water region due to artifacts
% select land region only
landpix = inpict(mask);
% histogram of the land area only
histogram(landpix)
Again, the issue with not knowing the scale is something I can't know for the purposes of creating an example. If your TIFF is actually floating point data in that specified range (possible, but not common), then you don't need to solve that problem. If your TIFF is integer-class data instead, then you will need to solve that problem, and in order for me to know how to solve it, I'd probably have to see the file.
If we need to cross that bridge, we'll have to find a way to host/transfer the file. Depends how big it actually is. It looks like it could be quite large, especially if it's float. I'm not sure how large of an attachment my mailbox will accept.
https://drive.google.com/file/d/1ww7V4aa4Vfqhw4h3BqlghSE8QAcJ4xHj/view?usp=drive_link is my google drive link for my image. The image is float. (https://drive.google.com/file/d/1ww7V4aa4Vfqhw4h3BqlghSE8QAcJ4xHj/view?usp=sharing)
I am getting this histogram after drawin
(I=imread('E:\waterbody_project\processed_sen\mnwi.tif');histogram(I)
I am using MATLABR2016a
I'm downloading the file. I don't know if I'm going to be able to get to this immediately.
It seems that the image uses very large negative values near -Inf as a mask for water areas. That may complicate display or some other operations, but for getting the histogram, we can just do something like:
inpict = imread('mnwi.tif');
landmask = inpict > -100;
histogram(inpict(landmask))
You may choose to tailor the number of bins, etc as you see fit.
Depending on what other work you choose to do, you might consider replacing those extreme negative values with something else. Many functions will ignore (or can be instructed to ignore) NaN values, so that's one option.
% using NaN as an embedded masking value may cause less headaches than ~-Inf
nanpict = inpict;
nanpict(~landmask) = NaN;
% the image with NaNs can be processed directly by histogram()
histogram(nanpict)
% and it can be displayed without the NaNs messing up
% the displayrange parameter like -Inf would
figure;
imshow(nanpict,[])
Yeah I already suggested taking the histogram of the masked part of the image in my answer. Not sure if @Tanmoyee Bhattacharya didn't want to do that for some reason, or if he just did not see my answer at all, or saw it and totally ignored it.
Thank you very much DGM and Image Analyst sir. I am very much grateful to you for the solution. The code provided by DGM sir is exactly what I want.
@Image Analyst I could see how a majority population of near-Inf values would make display and processing of an image misleading when all the actual content is hidden near zero. In any effort to find a threshold point, it would take some fussing to get histogram() to show anything that wasn't confusing.
Right but he said he believes he has a "grayscale image with values ranging from -0.86 to 0.53". So once this threshold between to get rid (mask out) bogus values less than -0.86, you could take the histogram of the valid remaining values like we both suggested.

Sign in to comment.

More Answers (2)

Thankyou so much for your inconsistent help.
I have little knowledge about this (If anything I asked irrelevant please ignore). My matlab version is R2013a. The image I have used is too large (more than 5mb) so that I cannot attach it. I attached the image screenshot and the histogram which I want to plot.
If you provide any option to attach my file (by mail also if possible) I will attach my image file.
I'm not sure why you're taking a histogram of the binary image. I think what you meant was to take the histogram of the masked part of the image, so why don't you try this:
grayImage = imread('E:\waterbody_project\processed_sen\mnwi.tif');
mask = grayImage < 255; % Non white parts only.
histogram(grayImage(mask));

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!