0

I have a set of points that I want to connect sequentially. Suppose the points are (A1,A2,A3,...A9); I want to connect A1 to A2, A2 to A3 and so on and finally connect A9 to A1.

All I need is to know a function that would help me connect A1 to A2, I could do the rest using for loops.

I know connecting two points is a question that has been asked here several times before but I couldn't find the answer I required. Several of the solutions suggest using "plot" and "line" but these functions overlay the results on the image and don't actually make any changes to the original image.

I did try them out and managed to save the resulting figure using the "saveas" and "print" functions but the image doesn't get saved in the proper format and there are a lot of problems using the parameters for these functions. Besides, I don't really want to save the image, it's just an unnecessary overhead I was willing to add if I could get the desired image with the lines. I've also tried "imline" to draw lines but it seems to be interactive.

This particular question reflects my problem perfectly but when I ran the code snippets given as solutions, all of them gave a set of dots in the resulting image.

I tried the above mentioned codes in the link with this image that I found here.

A dotted line was an output for all three code snippets in the link above. For example, I ran the first code like this:

I = imread('berries_copy.png'); 
grayImage=rgb2gray(I); 
img =false(size(grayImage,1), size(grayImage,2)); 

I wrote the above piece of code just to get a black image for the following operations:

x = [500 470];        % x coordinates 
y = [300 310];        % y coordinates
nPoints = max(abs(diff(x)), abs(diff(y)))+1;    % Number of points in line
rIndex = round(linspace(y(1), y(2), nPoints));  % Row indices
cIndex = round(linspace(x(1), x(2), nPoints));  % Column indices
index = sub2ind(size(img), rIndex, cIndex);     % Linear indices
img(index) = 255;  % Set the line points to white
imshow(img);       % Display the image

This is the resulting image for the above code as well as the other two, which as you can see, is just a few points on a black background which isn't the desired output.

I changed the code and used the "plot" function for the same to get this output which is what I want. Is there anyway I can change the dotted output into a solid line?

Or if could anyone suggest a simple function or a method that would draw a line from A1 to A2 and would actually make a change in the input image, I'd be grateful. (I really hope this is just me being a novice rather than Matlab not having a simple function to draw a line in an image.)

P.S. I don't have the Computer Vision toolbox and if possible, I'd like to find a solution that doesn't involve it.

Matte
  • 339
  • 2
  • 19
  • 1
    " when I ran the code snippets given as solutions, all of them gave some random points in the resulting image" My guess is you ran them wrong. – Ander Biguri May 16 '18 at 08:37
  • @Ander Biguri No. I created new programs just for them and except for changing the coordinates(which are valid), I didn't do anything else. The comments under the code snippets seem to indicate certain problems. Also, the interpolation function seems to give dotted lines which I assumed were random points, any idea how to make it a solid line? – Matte May 16 '18 at 08:58
  • 1
    The code in the linked answer works. You say it doesnt for you. Unless your show a [mcve], there is no other conclusion than "you did it wrong", no further we can help. – Ander Biguri May 16 '18 at 08:59
  • @ander Biguri I will edit my code, thank you. But is there really no inbuilt function for drawing a line? – Matte May 16 '18 at 09:12
  • Yes, in the Computer Vision toolbox. Also you do not want to draw a line right? you want to modify the image so it contains a line. Its different. else just use `plot` – Ander Biguri May 16 '18 at 09:21
  • @ander biguri Well I would like to draw a line that is burnt onto the image. Btw, I edited my post to include the results of the code. – Matte May 16 '18 at 16:16
  • "The line is actually connected if I zoom in the image a lot but that's not the desired output." ??? Explain yourself, else we can not help – Ander Biguri May 16 '18 at 16:24
  • @ander biguri The output I got from the result of running the codes in that link give a dotted line and I have posted an image link above. If I zoom in the image multiple times, the dots seem to be connected to each other. I don't know if that means the program is running correctly but the output is invisible and it definitely is not the output I want because what is visible is just a set of dots. Is there a way I can thicken the dots to make it appear as a line? – Matte May 16 '18 at 16:43
  • The line looks dotted because of the way it is displayed. If you zoom in you see a continuous line. When zoomed out, MATLAB is removing rows and columns from the image to make it smaller so it fits on your display. The solution would be to display your image correctly or to draw a thicker line, not a 1-pixel thick one like you’re doing here. – Cris Luengo May 16 '18 at 17:09
  • @Matte It means that the resolution of your screen is not enough to show the resolution of the image. – Ander Biguri May 16 '18 at 17:31
  • @Cris Luengo My sincere apologies, that was indeed the problem. – Matte May 17 '18 at 18:42
  • @Ander Biguri Thanks, I could see the results after certain modifications to the image. I don't want to delete this question in spite of its duplicity because I found the solutions useful, is it possible to let it be? – Matte May 17 '18 at 18:42
  • Matte, you wouldn't be able to delete the question because there are upvoted answers. It's here for the long run. :) – Cris Luengo May 17 '18 at 18:45
  • @Cris Luengo Thank you, the suggestions and answers helped a lot :) – Matte May 17 '18 at 18:55

3 Answers3

3

Your first problem is that you are creating a blank image the same size as the image you load with this line:

img =false(size(grayImage,1), size(grayImage,2));

When you add the line to it, you get a black image with a white line on it, as expected.

Your second problem is that you are trying to apply a solution for grayscale intensity images to an RGB (Truecolor) image, which requires you to modify the data at the given indices for all three color planes (red, green, and blue). Here's how you can modify the grayscale solution from my other answer:

img = imread('berries_copy.png');  % Load image
[R, C, D] = size(img);             % Get dimension sizes, D should be 3
x = [500 470];                     % x coordinates
y = [300 310];                     % y coordinates
nPoints = max(abs(diff(x)), abs(diff(y)))+1;    % Number of points in line
rIndex = round(linspace(y(1), y(2), nPoints));  % Row indices
cIndex = round(linspace(x(1), x(2), nPoints));  % Column indices
index = sub2ind([R C], rIndex, cIndex);         % Linear indices
img(index) = 255;                  % Modify red plane
img(index+R*C) = 255;              % Modify green plane
img(index+2*R*C) = 255;            % Modify blue plane
imshow(img);                       % Display image
imwrite(img, 'berries_line.png');  % Save image, if desired

And the resulting image (note the white line above the berry in the bottom right corner):

enter image description here

gnovice
  • 125,304
  • 15
  • 256
  • 359
  • Thank you. Running the code on "img =false(size(grayImage,1), size(grayImage,2));" isn't giving a solid line though. It's giving [this](https://ibb.co/c7Oo6J) output. – Matte May 16 '18 at 16:47
  • I'm sorry, I think you've got my question confused. I don't want the line to appear on the color image. That was just an example image I took. I want the line to appear on the binary image but when I run the code, all that appears is a dotted line while I want a solid line. – Matte May 16 '18 at 16:51
  • @Matte: There's no need for a color image then. That's just confusing. You can just create the blank image like `img = zeros(424, 640, 'uint8');`. Also, the issue isn't the algorithm, it's the display. As you mention, zooming shows that the image data is being modified correctly. You appear to be trying to display it at a much lower resolution, leading to a dotted appearance. What is the size (in pixels) that the image takes up on your screen? – gnovice May 16 '18 at 17:06
  • I'm sorry, you're right, the image was being displayed at a lower resolution. – Matte May 17 '18 at 18:36
  • I had chosen Zep's as the answer because I'd used it first but your [answer](https://stackoverflow.com/a/2465015/52738) had already worked for me so I upvoted that and went with Zep's answer here. Thank you for your help. – Matte May 17 '18 at 18:54
2

You can use the Bresenham Algorithm. Of course it has been implemented and you can find it here: Bresenham optimized for Matlab. This algorithm selects the pixels approximating a line.

A simple example, using your variable name could be:

I = rgb2gray(imread('peppers.png'));
A1 = [1 1];
A2 = [40 40];
[x y] = bresenham(A1(1),A1(2),A2(1),A2(2));
ind = sub2ind(size(I),x,y);
I(ind) = 255;
imshow(I) 
Zep
  • 1,541
  • 13
  • 21
  • Thank you, I ran it but it just gives x and y coordinates that are plotted on the image using the "plot" function. – Matte May 16 '18 at 16:44
  • No as you can see I do not use the plot function. I modify the pixels in the image. the Bresenham algorithm tells you which pixels to modify! – Zep May 17 '18 at 08:15
1

You can use imshow to display a image and then use plot to plot lines and save the figure. Check the below code:

I = imread('peppers.png') ;
imshow(I)
hold on
[m,n,p] = size(I) ;
%% Get random points A1, A2,..A10
N = 9 ;
x = (n-1)*rand(1,N)+1 ;
y = (m-1)*rand(1,N)+1 ;
P = [x; y]; % coordinates / points 
c = mean(P,2); % mean/ central point 
d = P-c ; % vectors connecting the central point and the given points 
th = atan2(d(2,:),d(1,:)); % angle above x axis
[th, idx] = sort(th);   % sorting the angles 
P = P(:,idx); % sorting the given points
P = [P P(:,1)]; % add the first at the end to close the polygon 
plot( P(1,:), P(2,:), 'k');
saveas(gcf,'image.png')
Siva Srinivas Kolukula
  • 1,251
  • 1
  • 7
  • 14
  • Thank you. This was my initial solution and this works as a standalone program but when I integrate it into a bigger one where I have a lot of images to display, the saved image is not the one I want. I don't know if the gcf handle needs to modified to reflect the current figure, I looked into it and drew a blank. – Matte May 16 '18 at 09:19
  • Before saving it into a image....are you able to see the lines you wanted on the image? – Siva Srinivas Kolukula May 16 '18 at 09:40
  • Yes, I can see the changes in the image when I use the "plot" function but the results disappear when I save it. – Matte May 16 '18 at 09:46
  • How did you save it? Attach your image as a .fig image here.... – Siva Srinivas Kolukula May 16 '18 at 10:41
  • I saved it as a .png file as follows: saveas(gcf,'file','png'); – Matte May 16 '18 at 16:17
  • My image is actually a totally black image. I drew a couple of lines on that. But when I save the plot, the black image without any changes is getting saved. It's not saving the changes I made to it. – Matte May 16 '18 at 16:19
  • I noticed that....when you switch on the axis ..it is working..... – Siva Srinivas Kolukula May 17 '18 at 06:21
  • Thanks. Seems like I already had the desired output but it was being displayed at a lower resolution. – Matte May 17 '18 at 18:32