Given a image canvas I with 2 points (a_x, a_y) and (b_x, b_y). The plotted line on the image has the correct orientation.
However, when I plot the same coordinates (a and b) in a cartesian coordinate system, I get a line with the wrong orientation.
I would like to convert the image coordinates that they match with the cartesian system. Thanks.
% Create image canvas
canvas = zeros(320, 320);
I = uint8(canvas);
imshow(I)
a_x = 122.6544;
a_y = 234.9782;
b_x = 165.9290;
b_y = 126.9200;
hold on
plot([a_x, b_x], [a_y, b_y] )
% Plot cartesian coordinate system
figure()
plot([a_x, b_x], [a_y, b_y])
xlim([0 320])
ylim([0 320])
axis equal
grid on
Images generated by imshow have the (0,0) coordinate at the upper left corner. Normal plots at the lower left corner.
You can see this by switching on the axes of the image:
% Create image canvas
canvas = zeros(320, 320);
I = uint8(canvas);
imshow(I)
a_x = 122.6544;
a_y = 234.9782;
b_x = 165.9290;
b_y = 126.9200;
hold on
plot([a_x, b_x], [a_y, b_y] );
ax = gca;
ax.Visible = 'on';
To change the direction of the plot axes, use the YDir property of the axes:
figure()
plot([a_x, b_x], [a_y, b_y])
xlim([0 320])
ylim([0 320])
grid on
ax=gca;
ax.YDir = 'reverse';
Related
I would like to know how to rotate a 2D image along its Z-axis using Matlab R2016b and to obtain an image after performing this procedure.
For example, let's take this 2D image:
Now, I rotate it of 45° roughly:
And now, of 90°:
Do you know if it is possible to perform the same operation in Matlab R2016b, please ?
Thank you very much for your help
Images Source: https://www.youtube.com/watch?v=m89mVexWQZ4
Yes it's possible. The easiest thing to do would be to map the image on the y = 0 plane in 3D, then rotate the camera to the desired azimuth or the angle with respect to the y axis. Once you do that, you can use the getframe / cdata idiom to actually capture the actual image data in a variable itself. The reason why you do this with respect to the y plane is because the method that I will be using to present the image is through the surf command that plots surface plots in 3D, but the y axis here is the axis that goes into and out of the screen. The x axis is the horizontal and the z axis would be the vertical when displaying data.
First read in your image using something like imread, then you need to define the 4 corners of the image that map to the 3D plane and then rotate the camera. You can use the view function to help you rotate the camera by adjusting the azimuthal angle (first parameter) and leaving the elevation angle as 0.
Something like this could work. I'll be using the peppers image that is part of the image processing toolbox:
im = imread('peppers.png'); % Read in the image
ang = 45; % Rotate clockwise by 45 degrees
% Define 4 corners of the image
X = [-0.5 0.5; -0.5 0.5];
Y = [0 0; 0 0];
Z = [0.5 0.5; -0.5 -0.5];
% Place the image on the y = 0 plane
% Turn off the axis and rotate the camera
figure;
surf(X, Y, Z, 'CData', im, 'FaceColor', 'texturemap');
axis('off');
view(ang, 0);
% Get the image data after rotation
h = getframe;
rot_im = h.cdata;
rot_im contains the rotated image. To appreciate the rotation of the image, we can loop through angles from 0 to 360 in real time. At each angle, we can use view to dynamically rotate the camera and use drawnow to update the figure. I've also updated the title of the figure to show you what the angle is at each update. The code for that is below as well as the output saved as an animated GIF:
for ang = 0 : 360
view(ang, 0);
pause(0.01);
drawnow;
title(sprintf('Angle: %d degrees', ang));
end
I am trying to find a way to crop from a circle object (Image A) the largest square that can fit inside it.
Can someone please explain/show me how to find the biggest square fit parameters of the white space inside the circle (Image I) and based on them crop the square in the original image (Image A).
Script:
A = imread('E:/CirTest/Test.jpg');
%imshow(A)
level = graythresh(A);
BW = im2bw(A,level);
%imshow(BW)
I = imfill(BW, 'holes');
imshow(I)
d = imdistline;
[centers, radii, metric] = imfindcircles(A,[1 500]);
imageCrop=imcrop(A, [BoxBottomX BoxBottomY NewX NewY]);
I have a solution for you but it requires a bit of extra work. What I would do first is use imfill but directly on the grayscale image. This way, noisy pixels in uniform areas get inpainted with the same intensities so that thresholding is easier. You can still use graythresh or Otsu's thresholding and do this on the inpainted image.
Here's some code to get you started:
figure; % Open up a new figure
% Read in image and convert to grayscale
A = rgb2gray(imread('http://i.stack.imgur.com/vNECg.jpg'));
subplot(1,3,1); imshow(A);
title('Original Image');
% Find the optimum threshold via Otsu
level = graythresh(A);
% Inpaint noisy areas
I = imfill(A, 'holes');
subplot(1,3,2); imshow(I);
title('Inpainted image');
% Threshold the image
BW = im2bw(I, level);
subplot(1,3,3); imshow(BW);
title('Thresholded Image');
The above code does the three operations that I mentioned, and we see this figure:
Notice that the thresholded image has border pixels that need to be removed so we can concentrate on the circular object. You can use the imclearborder function to remove the border pixels. When we do that:
% Clear off the border pixels and leave only the circular object
BW2 = imclearborder(BW);
figure; imshow(BW2);
... we now get this image:
Unfortunately, there are some noisy pixels, but we can very easily use morphology, specifically the opening operation with a small circular disk structuring element to remove these noisy pixels. Using strel with the appropriate structuring element in addition to imopen should help do the trick:
% Clear out noisy pixels
SE = strel('disk', 3, 0);
out = imopen(BW2, SE);
figure; imshow(out);
We now get:
This mask contains the locations of the circular object we now need to use to crop our original image. The last part is to determine the row and column locations using this mask to locate the top left and bottom right corner of the original image and we thus crop it:
% Find row and column locations of circular object
[row,col] = find(out);
% Find top left and bottom right corners
top_row = min(row);
top_col = min(col);
bottom_row = max(row);
bottom_col = max(col);
% Crop the image
crop = A(top_row:bottom_row, top_col:bottom_col);
% Show the cropped image
figure; imshow(crop);
We now get:
It's not perfect, but it will of course get you started. If you want to copy and paste this in its entirety and run this on your computer, here we are:
figure; % Open up a new figure
% Read in image and convert to grayscale
A = rgb2gray(imread('http://i.stack.imgur.com/vNECg.jpg'));
subplot(2,3,1); imshow(A);
title('Original Image');
% Find the optimum threshold via Otsu
level = graythresh(A);
% Inpaint noisy areas
I = imfill(A, 'holes');
subplot(2,3,2); imshow(I);
title('Inpainted image');
% Threshold the image
BW = im2bw(I, level);
subplot(2,3,3); imshow(BW);
title('Thresholded Image');
% Clear off the border pixels and leave only the circular object
BW2 = imclearborder(BW);
subplot(2,3,4); imshow(BW2);
title('Cleared Border Pixels');
% Clear out noisy pixels
SE = strel('disk', 3, 0);
out = imopen(BW2, SE);
% Show the final mask
subplot(2,3,5); imshow(out);
title('Final Mask');
% Find row and column locations of circular object
[row,col] = find(out);
% Find top left and bottom right corners
top_row = min(row);
top_col = min(col);
bottom_row = max(row);
bottom_col = max(col);
% Crop the image
crop = A(top_row:bottom_row, top_col:bottom_col);
% Show the cropped image
subplot(2,3,6);
imshow(crop);
title('Cropped Image');
... and our final figure is:
You can use bwdist with L_inf distance (aka 'chessboard') to get the axis-aligned distance to the edges of the region, thus concluding the dimensions of the largest bounded box:
bw = imread('http://i.stack.imgur.com/7yCaD.png');
lb = bwlabel(bw);
reg = lb==2; %// pick largest area
d = bwdist(~reg,'chessboard'); %// compute the axis aligned distance from boundary inward
r = max(d(:)); %// find the largest distance to boundary
[cy cx] = find(d==r,1); %// find the location most distant
boundedBox = [cx-r, cy-r, 2*r, 2*r];
And the result is
figure;
imshow(bw,'border','tight');
hold on;
rectangle('Position', boundedBox, 'EdgeColor','r');
Once you have the bounding box, you can use imcrop to crop the original image
imageCrop = imcrop(A, boundedBox);
Alternatively, you can
imageCrop = A(cy + (-r:r-1), cx + (-r:r-1) );
After applying the following code I get output mapped image started from centre top point. How can I put the starting point to left bottom corner? So, the output image should be stretched from left bottom point(not from top centre as it is now)...
im = imread ('peppers.png');
im = rgb2gray(im);
[nZ,nX] = size(im);
theta = ((0:(nX-1))-nX/2)*(0.1*(pi/180)) - pi/2;
rr = (0:(nZ-1))*0.1e-3;
%% Plot image in rectangular coordinates
figure
imagesc(theta*(180/pi), rr*1e3, im)
xlabel('theta [deg]')
ylabel('r [mm]')
%% Create grids and convert polar coordinates to rectangular
[THETA,RR] = meshgrid(theta,rr);
[XX,YY] = pol2cart(THETA,RR);
%% Plot as surface, viewed from above
figure
surf(XX*1e3,YY*1e3,im,'edgecolor','none')
view(0,90)
xlabel('x [mm]')
ylabel('y [mm]')
I wish to crop this original image
to a new image which will contain only the bag with minimum white pixels (essentially reducing the size image to the bag borders)
.
Therefore I decided to first convert it to a binary image
but I do not know how to find the bag corner coordinates [xmin ymin width height] in order to use them with imcrop(I,rect).
Any help will be great.
The script:
clc;
close all;
url='http://oi65.tinypic.com/i19md1.jpg' ;
rgbImage = imread(url);
grayImage = rgb2gray(rgbImage);
binaryImage = grayImage < 250;
imshow(binaryImage);
That's a very easy task to perform. Since binaryImage contains a mask that you want to use to crop the image, you can find the top-left corner (xmin,ymin) of where you want to crop by finding the smallest column and row coordinate respectively that is non-zero in the mask, then to find width and height, find the bottom-right corner that is non-zero, then subtract the two x coordinates for the width and the two y coordinates for the height. You'll need to add 1 to each difference to account for self-distances (i.e. if you had a width that was 1 pixel wide, you should get a width of 1, not 0). You can use find to help you find the row and column locations that are non-zero. However, imcrop requires that the x coordinates reflect horizontal behaviour and y coordinates reflect vertical behaviour where find returns row and column locations respectively. That's why you'll have to flip them when you call find:
[y,x] = find(binaryImage); %// Find row and column locations that are non-zero
%// Find top left corner
xmin = min(x(:));
ymin = min(y(:));
%// Find bottom right corner
xmax = max(x(:));
ymax = max(y(:));
%// Find width and height
width = xmax - xmin + 1;
height = ymax - ymin + 1;
You can now go ahead and crop the image:
out = imcrop(rgbImage, [xmin ymin width height]);
imshow(out);
I get this for your cropped image:
I would like to get pixels coordinates and RGB Intensity values from points that only lie on the specified circle boundary in a given RGB input image without drawing the circle and considering Its specified color. As far as I did is just draw the circle on a particular point. Any help? Thanks.
yellow = uint8([255 255 0]);
% Create the shape inserter object.
shapeInserter = vision.ShapeInserter('Shape','Circles','BorderColor','Custom','CustomBorderColor',yellow);
% Read RGB input image.
I = imread('3.jpg');
% Define the circle dimensions
x1=80;
y1=80;
circle = int32([x1 y1 3]); % [x1 y1 radius]
% Draw the circle and display the result.
J = step(shapeInserter, I, circle);
imshow(J);
You don't need the Computer Vision toolbox for that. Simply define your centre coordinate of your circle and the specified radius, then use a combination of meshgrid and logical indexing to determine (x,y) coordinates as well as the corresponding RGB values along the perimeter of the circle.
Something like this:
%// Define parameters
x1 = 80; y1 = 80;
radius = 3;
tol = 0.1;
%// Get dimensions of image
rows = size(I,1); cols = size(I,2);
%// Define grid of coordinates
[x,y] = meshgrid(1:cols, 1:rows);
%// Define mask for valid pixels
mask = ((x - x1).^2 + (y - y1).^2) >= (radius - tol)^2;
mask = mask & ((x - x1).^2 + (y - y1).^2) <= (radius + tol)^2;
%// Get row and column locations
col = x(mask); row = y(mask);
%// Get pixel values
R = I(:,:,1); G = I(:,:,2); B = I(:,:,3);
red = R(mask); green = G(mask); blue = B(mask);
These statements:
mask = ((x - x1).^2 + (y - y1).^2) >= (radius - tol)^2;
mask = mask & ((x - x1).^2 + (y - y1).^2) <= (radius + tol)^2;
defines the equation of the circle of the form:
(x - x0)^2 + (y - y0)^2 == r^2
The centre coordinate is defined at (x0, y0) with a radius of r. However, due to discrete coordinates in the image, you'll need to get values within some tolerance of the radius. I set this tolerance to be 0.1. This equation defines the boundary of the circle. Therefore, we want to find those locations in the image that allow the above expression to be true.
Once you're done, we can get the row and column locations of the pixels along the boundary and finally we can use the logical mask itself to index into each channel and grab the corresponding red, green and blue pixels for each of the locations that are defined along the boundary.
Here's an example with a radius of 30, centered at (100,100) with rows and columns set to 300 respectively. We visualize what the mask looks like. White denotes that we sample at this point and black means we don't: