Interactive pixel extraction from an image along custom line

28 views (last 30 days)
The following code extracts pixel values for the first column of an image.
IMt = imread('test.jpg');
% convert to double format
IMtd=double(IMt);
% isolate first trace
trace=(IMtd(:,1));
What I need to do instead is extract the pixel values along an arbitrary line (see red lines in below image). In other words, along a direction which is diagonal to rows and columns.
Is there a tool in Matlab available where one can plot an image and then interactively draw a line along which the values will be extracted?
If I use...
imshow(IMt)
datacursormode on
...the pixel values are interactively displayed when I hove over the image. There just needs to be a way to write them into an array at the same time.

Accepted Answer

Image Analyst
Image Analyst on 6 Jun 2020
Try improfile()
or drawline() with a callback function
  5 Comments
Image Analyst
Image Analyst on 7 Jun 2020
You never know before you draw the line but once you draw it, you know, and that's what I computed and passed in.
You can rate it one star in the help and it will bring up a form that you can put your comment.
Z.S.
Z.S. on 2 Jul 2021
I think the variables linestart and lineend are miss-positioning the x and y coordinates of the end points for using improfile. According to the help page of improfile, the format should be improfile(I,x,y). Then the code should be something like:
I = imread('liftingbody.png');
imshow(I);
roi = drawline('Color','r');
% now draw line interactively
%
% Read out the X and Y coordinates of the start and end points
line_xs = [roi.Position(1,1), roi.Position(2,1)]
line_ys = [roi.Position(1,2), roi.Position(2,2)];
% extract pixel values along line
pixvals = improfile(I,line_xs,line_ys);
figure
plot(pixvals,1:length(pixvals),'k'), axis tight, title('pixel values')
xlabel('pixel greyscale values')
ylabel('relative position from linestart (0) to lineend')

Sign in to comment.

More Answers (1)

Julianna Mather
Julianna Mather on 8 Jun 2020
I've been thinking about how to frame the enhancement request for the functionality you requested, and I have some questions.
I'm curious to know what your ultimate goal is and what exactly you want to happen along the diagonals.
Suppose you have a diagonal line that crosses through a pixel just a tiny, tiny bit, should it get counted? Or perhaps it would be appropriate to determine the number of rows and columns the diagnol spans and then use hypot to figure out the number of pixels to sample uniformly along the line. (You can do that right now with improfile now, of course, for non-interactive syntaxes.)
So all of this gets me to the first question: What is your ultimate goal of having improfile return more pixel sites? How will you use that increased resolution?
(BTW, I'm not critiquing your request, I just want to make sure that we get a solution that will satisfy your use case.)
  1 Comment
Florian
Florian on 8 Jun 2020
Edited: Florian on 8 Jun 2020
Hi Jeff,
thanks for getting in touch. Let's go back to my first comment dated 7 Jun 2020 at 7:20. My point here was to try first if improfile reads the pixels along a drawn line as one would expect from the image data.
In the example I showed (see my attached file in the first comment by scrolling all the way to the right), I drew a straight line from the top to the bottom of the liftingbody.png image whose size is 512 x 512 pixels. As you can see from the workspace variables on the left of the attached file, the drawn line start and end point both coincided with column 249 of the image. In this case I would thus expect that improfile returns 512 values which is the length of each column. Instead, improfile only returned 265 values (pixvals variable in the workspace). So this first example tells me that there is a problem reading out the pixel values along a straight line. When you then go to the right of my attached file then Matlab Figure 2 shows the greyscale values which were extracted along the drawn line. The first 100 values or so correspond to the greyish interval on top of the flying object, while the ones after correspond to the object itself (values in the 200s matching the whitish color of the flying object). Please note that there are NO greyscale values which belong to the grey interval below the flying object. So that is the other point which concerns me: the capture of pixel values just stops somewhere along the drawn line and doesn't continue to the end of the image in accordance with the drawn line.
Maybe there is something wrong in my assessment here, but to me it seems the function improfile does not return the right values along the drawn line. So the first thing would just be to verify if my two observations explained above are correct and as a result there needs to be an improvement made to the improfile function.
The second step would then be to look at diagonal lines, and if I say diagonal then I would like improfile to retun a number of pixels which is close to the actual number of pixels, as defined by Image Analyst in this code
numSamples = round(sqrt((linestart(1) - lineend(1)).^2 + (linestart(2) - lineend(2)).^2))
pixvals = improfile(I,linestart,lineend, numSamples);
So using a full diagonal in a 512 x 512 pixel image, this would amount to 724 pixel values. And the pixels which are sampled are equally sampled along the drawn line, not ending 1/2 or 2/3 down the line.
Kind regards,
Florian

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!