You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
Segment extraction from an image in any direction
2 views (last 30 days)
Show older comments
Hi, i'm trying to extract a segment from an image in any direction. Suppose i have an 800X600 image (RGB) and i want to read a segment from point A(500,200) to point B(300,600). Is there any way i can get a column vector which contains the pixels values in that "diagonal"? i think it has to be some sort of interpolation between the nearest pixels. I don´t want to rotate the image, i need the values as they are. Regards.
Accepted Answer
Image Analyst
on 4 Jul 2014
Yes. You can use improfile()
x = [200, 600];
y = [500, 300];
values = improfile(grayImage, x, y);
33 Comments
Alejandro
on 4 Jul 2014
That seems to work, thanks!!!! but there is a way to display that array (i have an rgb image) as an image? right now i'm getting a black line. I need to apply this to a number of images and create a matrix which contains all the vectors from those images, and display the "new" image with all the previous segments. Sorry for "segmentation"
Image Analyst
on 4 Jul 2014
It's just a line so you can plot it with plot(). If you really want an image of an all black rectangle except for one gray level line, then you'll have to use imline and create a mask that you can multiply by your image. See attached demo.
Alejandro
on 4 Jul 2014
I'm going to check that. What i need to do is displayed in the attached image.
Image Analyst
on 4 Jul 2014
Just do
x = [200, 600];
y = [500, 300];
values = improfile(grayImage, x, y);
bar(values);
Alejandro
on 4 Jul 2014
sorry for not explaining myself well. The attached image is an image created with 1920 vectors concatenated into a matrix. Each vector belongs to a certain image. It is done by selecting two points from an image (two points in the same horizontal coordinate) and reading the pixels between those points. As the two points were in the same horizontal coordinate, i had no problems. But now i have to do it in any direction (from A to B as i explained before). I thought improfile would solve the problem, but as i explained to you before, when i use imshow() on the generated vector "values" it displays a black image. I need it to be a "color" segment or image. Hope it make sense now.
Alejandro
on 4 Jul 2014
i couldn't do it with the explame you send me. I was trying to use Bresenham's line algorithm, but that only gave me the coordinates, i need the values aswell and the plot.
Image Analyst
on 4 Jul 2014
You can do it with improfile. It interpolates a straight line which is better than the jagged one you get from Bresenham. You just need to pass in a constant number of samples to improfile and then tack them on to an array:
x = [200, 600];
y = [500, 300];
values = improfile(grayImage, x, y, 300);
% Stitch this profile on to the rest of them.
theImage = [theImage, values];
You might have to transpose values if it's a row vector instead of a column vector.
Alejandro
on 4 Jul 2014
Edited: Alejandro
on 4 Jul 2014
i get this error: Error using horzcat Dimensions of matrices being concatenated are not consistent. Error in pruebayborra (line 9) A=[A,values];
values is a column vector 1301x1x3 double and A is my RGB image 1080x1920x3 uint8
I think i have to initialize a matrix of the size of values.
Image Analyst
on 4 Jul 2014
It's more complicated for a color image. You might have to do it on each color channel one at a time.
Alejandro
on 4 Jul 2014
i keep getting the same error, even when i do it on each color.
what is this:
theImage = [theImage, values];
in my code grayImage,theImage = A (RGB)
Image Analyst
on 4 Jul 2014
If you extracted each color channel into it's own grayscale image, then why does improfile give you a 1301x1x3 array? It won't. It will give you a 1D array. You'll have to share more of your code.
Alejandro
on 4 Jul 2014
sorry, that was before i did it with each color.
A=imread('img_calib.png');
x = [100, 1400];
y = [700, 200];
values=improfile(A(:,:,1),x,y,'bicubic');
A=[A,values];
Error using horzcat
Dimensions of matrices being concatenated are not consistent.
Error in pruebayborra (line 9)
A=[A,values];
Alejandro
on 4 Jul 2014
Edited: Alejandro
on 4 Jul 2014
i tried with a random vector:
b=zeros(1080,300);
A=[A(:,:,1),b];
imshow(A);
and this displays the image with a black rectangle on the side. It is not quite i have to do but still, i need to display as an image the "values" vector. Any way i can do that?
Image Analyst
on 4 Jul 2014
Well you need to put some thought into this. You're taking a profile from two points somewhere in the image, right? Now the number of samples taken along that line would not necessarily be the same as the number of rows in the image, would it? Of course not, so you don't want to append the line to the entire original RGB image (the poorly-named "A") like you tried to do. That makes no sense.
You said you need to do lots of these lines: "I need to apply this to a number of images and create a matrix which contains all the vectors from those images" So how can we do that? Well how about we loop over all the images and in the loop we have a call to improfile. On the first image, there is nothing to append to so the first one we just take the profile itself to get started. Only if the loop index if >=2 do we append. So don't you think you'll need to do something like this inside your loop
rgbImage = imread(filenames(k).name); % read kth image.
% Extract the individual red, green, and blue color channels.
redChannel = rgbImage(:, :, 1);
greenChannel = rgbImage(:, :, 2);
blueChannel = rgbImage(:, :, 3);
x = [100, 1400];
y = [700, 200];
redValues=improfile(redChannel,x,y,'bicubic');
if k == 1
redProfiles = redValues;
else
redProfiles = [redProfiles, redValues];
end
Do the same for the green and blue channels. Then make an RGB image from them like
rgbProfiles = cat(3, redProfiles, greenProfiles, blueProfiles);
If you don't know how to loop over the filenames, see the FAQ: http://matlab.wikia.com/wiki/FAQ#How_can_I_process_a_sequence_of_files.3F
Alejandro
on 4 Jul 2014
ok, let me check. Actually i have the loop code. I need to display improfile as an image. Let me check.
Alejandro
on 4 Jul 2014
i still get a black line.
rgbImage=imread('img_calib.png');
redChannel = rgbImage(:, :, 1);
greenChannel = rgbImage(:, :, 2);
blueChannel = rgbImage(:, :, 3);
x = [100, 1400];
y = [700, 200];
redValues=improfile(redChannel,x,y,'bicubic');
greenValues=improfile(greenChannel,x,y,'bicubic');
blueValues=improfile(blueChannel,x,y,'bicubic');
redProfiles = uint8(redValues);
greenProfiles = uint8(greenValues);
blueProfiles = uint8(blueValues);
%Do the same for the green and blue channels. Then make an RGB image from them like
rgbProfiles = cat(3, redProfiles, greenProfiles, blueProfiles);
imshow(rgbProfiles);
This is for one image. I tried changing to uint8 and still get the black line.
Image Analyst
on 4 Jul 2014
That's not what I showed you. Where is the "if k==1" stuff????? Well that's my last post for the day most likely. I'll be out until almost midnight. Good luck.
Alejandro
on 4 Jul 2014
i was testing with one image. I can't do it for all the images if the code is not working.
Alejandro
on 4 Jul 2014
correction, that seems to work. Let me do it with all the images (2000). i'm trying to initialize a matrix because "redProfiles" is changing size in every loop.
Alejandro
on 4 Jul 2014
Edited: Alejandro
on 4 Jul 2014
ok, i did it, but i couldn't initialize an array and display it as the final image. I'm trying to do that because i think the process would be faster. Is that correct?
weel, here's the array %vect_foto = zeros(abs(x(2)-x(1))+1,n2,3); and here is the code.
lee_archivos2 = dir('*.jpg');
dimension2 = length(lee_archivos2);
n2 = dimension2;
B2 = 1:n2; %B2 es un vector fila
for k=1:n2
ttt=sscanf(lee_archivos2(k).name(7:end),'%ld');
B2(k)=ttt;
end
%disp(B2);
[sorted_array2,orden2] = sort(B2);%B = sort(A) sorts the elements along different dimensions of an array,
%and arranges those elements in ascending order. a can be a cell array of strings
x = [100, 1400];
y = [700, 200];
%vect_foto = zeros(abs(x(2)-x(1))+1,n2,3);
wbr = waitbar(0,'1','Name','Espere Por Favor',...
'CreateCancelBtn',...
'setappdata(gcbf,''canceling'',1)');
setappdata(wbr,'canceling',0)
for j = 1:n2 %recorre número de archivos guardados en el directorio
ima_read = imread(lee_archivos2(orden2(j)).name); %se lee cada imagen ascendentemente
redChannel = ima_read(:, :, 1);
greenChannel = ima_read(:, :, 2);
blueChannel = ima_read(:, :, 3);
redValues=improfile(redChannel,x,y,'bicubic');
greenValues=improfile(greenChannel,x,y,'bicubic');
blueValues=improfile(blueChannel,x,y,'bicubic');
if j == 1
redProfiles = uint8(redValues);
greenProfiles = uint8(greenValues);
blueProfiles = uint8(blueValues);
else
redProfiles = [redProfiles, redValues];
greenProfiles = [greenProfiles, greenValues];
blueProfiles = [blueProfiles, blueValues];
end
%Do the same for the green and blue channels. Then make an RGB image from them like
rgbProfiles = cat(3, redProfiles, greenProfiles, blueProfiles);
if getappdata(wbr,'canceling')
break
end
waitbar(j/n2,wbr,{sprintf('%g%%Completado',...
fix(100*(j/(n2))))});
fclose('all');
clear ima_read rotate_ima vect1 ttt B2 sorted_array2
end
delete(wbr);
%size(rgbProfiles)
imshow(rgbProfiles);
Alejandro
on 4 Jul 2014
i have another question regarding the pixel coordinate of "redvalue" in the original image. i'll ask when you respond. Regards.
Image Analyst
on 5 Jul 2014
You can pass in a size for the profile so that it will be the same length for every profile it extracts. That way you can stitch the current image's profile onto the growing image of all profiles.
Alejandro
on 5 Jul 2014
it seems it doesn't affect the computation time when i initialize the vectors. it should, shouldn't it? (this is my final qustion, i already solved the problem of the coordinates)
Image Analyst
on 5 Jul 2014
I don't know since you're not showing the code. It may or may not make a noticeable difference in run time.
Alejandro
on 5 Jul 2014
lee_archivos2 = dir('*.jpg');
dimension2 = length(lee_archivos2);
n2 = dimension2;
B2 = 1:dimension2; %B2 es un vector fila
for k=1:n2
ttt=sscanf(lee_archivos2(k).name(7:end),'%ld');
B2(k)=ttt;
end
%disp(B2);
[sorted_array2,orden2] = sort(B2);%B = sort(A) sorts the elements along different dimensions of an array,
%and arranges those elements in ascending order. a can be a cell array of strings
x = [100, 1400];
y = [700, 200];
wbr = waitbar(0,'1','Name','Espere Por Favor',...
'CreateCancelBtn',...
'setappdata(gcbf,''canceling'',1)');
setappdata(wbr,'canceling',0)
cx = zeros(abs(x(2)-x(1))+1,n2);
cy = zeros(abs(x(2)-x(1))+1,n2);
cx2 = zeros(abs(x(2)-x(1))+1,n2);
cy2 = zeros(abs(x(2)-x(1))+1,n2);
cx3 = zeros(abs(x(2)-x(1))+1,n2);
cy3 = zeros(abs(x(2)-x(1))+1,n2);
redValues = zeros(abs(x(2)-x(1))+1,n2);
greenValues = zeros(abs(x(2)-x(1))+1,n2);
blueValues = zeros(abs(x(2)-x(1))+1,n2);
for j = 1:n2 %recorre número de archivos guardados en el directorio
ima_read = imread(lee_archivos2(orden2(j)).name); %se lee cada imagen ascendentemente
redChannel = ima_read(:, :, 1);
greenChannel = ima_read(:, :, 2);
blueChannel = ima_read(:, :, 3);
[cx(:,j),cy(:,j),redValues(:,j)]=improfile(redChannel,x,y,'bicubic');
[cx2(:,j),cy2(:,j),greenValues(:,j)]=improfile(greenChannel,x,y,'bicubic');
[cx3(:,j),cy3(:,j),blueValues(:,j)]=improfile(blueChannel,x,y,'bicubic');
%if j == 1
% redProfiles = uint8(redValues);
% greenProfiles = uint8(greenValues);
% blueProfiles = uint8(blueValues);
%else
% redProfiles = [redProfiles, redValues];
% greenProfiles = [greenProfiles, greenValues];
%blueProfiles = [blueProfiles, blueValues];
%end
redProfiles = uint8(redValues);
greenProfiles = uint8(greenValues);
blueProfiles = uint8(blueValues);
%Do the same for the green and blue channels. Then make an RGB image from them like
rgbProfiles = cat(3, redProfiles, greenProfiles, blueProfiles);
if getappdata(wbr,'canceling')
break
end
waitbar(j/n2,wbr,{sprintf('%g%%Completado',...
fix(100*(j/(n2))))});
fclose('all');
clear ima_read rotate_ima vect1 ttt B2 sorted_array2
end
delete(wbr);
imshow(rgbProfiles);
Image Analyst
on 5 Jul 2014
You are still not passing in a number to improfile to tell it how many elements to take, though it will probably be the same number every time since x and y are the same every time.
Alejandro
on 5 Jul 2014
yes. x and y are the same for every loop. I change the values before the loop just for test the code. How can ia pass in the number to improfile?
Image Analyst
on 5 Jul 2014
numberOfSamplesToTake = round(sqrt((x(1)-x(2))^2+(y(1)-(2))^2));
[cx(:,j),cy(:,j),redValues(:,j)] = improfile(redChannel,x,y, ...
numberOfSamplesToTake, 'bicubic');
Alejandro
on 5 Jul 2014
oh, ok. That is the distance between the points, but it increases the size of the vector. Is there any advantage regarding the precision of the pixel values in the final image (rgbProfiles)? Because the run time is the same, a little longer i would say.
Image Analyst
on 5 Jul 2014
That's using the same spacing as the original sampling. You can go higher for more "resolution" though it's just giving you more samples, not necessarily giving more information, or you can use a smaller number if you want a sampling less frequent than you have in the image. It's your choice. Do whatever you want considering the time to process and what you want to do with the final image you're building up.
More Answers (0)
See Also
Tags
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- 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)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)