Segment extraction from an image in any direction
1 次查看(过去 30 天)
显示 更早的评论
Alejandro
2014-7-4
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.
采纳的回答
Image Analyst
2014-7-4
Yes. You can use improfile()
x = [200, 600];
y = [500, 300];
values = improfile(grayImage, x, y);
33 个评论
Alejandro
2014-7-4
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
2014-7-4
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.
Image Analyst
2014-7-4
Just do
x = [200, 600];
y = [500, 300];
values = improfile(grayImage, x, y);
bar(values);
Alejandro
2014-7-4
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
2014-7-4
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
2014-7-4
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
2014-7-4
编辑:Alejandro
2014-7-4
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
2014-7-4
It's more complicated for a color image. You might have to do it on each color channel one at a time.
Alejandro
2014-7-4
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
2014-7-4
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
2014-7-4
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];
Image Analyst
2014-7-4
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
2014-7-4
ok, let me check. Actually i have the loop code. I need to display improfile as an image. Let me check.
Alejandro
2014-7-4
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
2014-7-4
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
2014-7-4
i was testing with one image. I can't do it for all the images if the code is not working.
Alejandro
2014-7-4
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
2014-7-4
编辑:Alejandro
2014-7-4
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
2014-7-4
i have another question regarding the pixel coordinate of "redvalue" in the original image. i'll ask when you respond. Regards.
Image Analyst
2014-7-5
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
2014-7-5
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
2014-7-5
I don't know since you're not showing the code. It may or may not make a noticeable difference in run time.
Alejandro
2014-7-5
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
2014-7-5
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
2014-7-5
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
2014-7-5
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
2014-7-5
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
2014-7-5
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.
更多回答(0 个)
另请参阅
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 (한국어)