Chessboard distance in the image matrix - matlab

Given an image matrix, how can I get the locations of the pixels whose chessboard distances from pixel A is less than D. I need to performed this for all pixels.
Using the MATLAB function bwdist I couldn't provide desired result. What's the solution?
[D,idx] = bwdist(Img,'chessboard');

Given an image, pixel and maximum distance:
% Test image
Image = zeros(20,30);
% Maximum chessboard distance from image
maxDist = 7;
% The pixel from which to measure distance
pix = [4,19];
To find the pixels who's chessboard distance from the pix are
less than maxDist and in the image bounds:
Option 1: Using bwdist
% Create a binary image with all pixels zero except 'pix'
bw = zeros(size(Image));
bw(pix(1), pix(2)) = 1;
% Get the chessboard distance transform
[D,idx] = bwdist(bw,'chessboard');
% Get the linear index of 'pix'
pixInd = sub2ind(size(bw), pix(1), pix(2));
% Find linear indices of pixels who's chessboard distance from pixel are
% less than 'maxDist'
pointsInd = find(idx == pixInd & D < maxDist);
% Remove 'pix'
pointsInd(pointsInd == pixInd) = [];
% Get the pairs of (x,y) of the pixels
[pointsX, pointsY] = ind2sub(size(bw), pointsInd);
Option 2: Using meshgrid
% Get the range of x and y indices who's chessboard distance from pixel are
% less than 'maxDist' and in the image bounds
xRange = max((pix(1)-(maxDist-1)),1):min((pix(1)+(maxDist-1)),size(Image,1));
yRange = max((pix(2)-(maxDist-1)),1):min((pix(2)+(maxDist-1)),size(Image,2));
% Create a mesgrid to get the pairs of (x,y) of the pixels
[pointsX, pointsY] = meshgrid(xRange, yRange);
pointsX = pointsX(:);
pointsY = pointsY(:);
% Remove 'pix'
pixIndToRemove = (pointsX == pix(1) & pointsY == pix(2));
pointsX(pixIndToRemove) = [];
pointsY(pixIndToRemove) = [];
Displaying result:
% Get linear indices of pixels
pointsInd = sub2ind(size(Image), pointsX, pointsY);
% To display the result, create a binary image with all found pixels
% colored white
bwPoints = zeros(size(Image));
bwPoints(pointsInd) = 1;
% Show points
imshow(bwPoints, 'InitialMagnification', 2000)
% Show pixel grid lines
hold on
[rows, cols] = size(bwPoints);
for row = 0.5 : 1 : (rows + 0.5)
line([0.5, cols+0.5], [row, row], 'Color', 'r', 'LineWidth', 0.5);
end
for col = 0.5 : 1 : (cols + 0.5)
line([col, col], [0.5, rows+0.5], 'Color', 'r', 'LineWidth', 0.5);
end
Efficiency and running in a loop over all image pixels:
Option 2 is way much faster than Option 1. I wrote first Option 1 because bwdist was mentioned in the question. Running Option 2 in a loop can be improved by calculating the pixels first and than shifting them to the location of each pixel:
% Get the range of x and y indices who's chessboard distance from pixel
% (0,0) are less than 'maxDist'
xRange = (-(maxDist-1)):(maxDist-1);
yRange = (-(maxDist-1)):(maxDist-1);
% Create a mesgrid to get the pairs of (x,y) of the pixels
[pointsX, pointsY] = meshgrid(xRange, yRange);
pointsX = pointsX(:);
pointsY = pointsY(:);
% Remove pixel (0,0)
pixIndToRemove = (pointsX == 0 & pointsY == 0);
pointsX(pixIndToRemove) = [];
pointsY(pixIndToRemove) = [];
for x=1:size(Image, 1)
for y=1:size(Image, 2)
% Get a shifted copy of 'pointsX' and 'pointsY' that is centered
% around (x, y)
pointsX1 = pointsX + x;
pointsY1 = pointsY + y;
% Remove the the pixels that are out of the image bounds
inBounds =...
pointsX1 >= 1 & pointsX1 <= size(Image, 1) &...
pointsY1 >= 1 & pointsY1 <= size(Image, 2);
pointsX1 = pointsX1(inBounds);
pointsY1 = pointsY1(inBounds);
% Do stuff with 'pointsX1' and 'pointsY1'
% ...
end
end

"The aim is to access the location of the pixels whose chessboard distances from pixel A is less than D. The process should be
performed for all pixels..."
Since D is creating a square selection area, just use simple maths..
For example: if D is 3 then from the [x,y] position of pixel A...
//# we minus D by 1 since you want less than D (not equal / higher)
Start-X = pixelA.x - (D-1); //from the left
End-X = pixelA.y + (D-1); //to the right
Start-Y = pixelA.y - (D-1); //from the top
End-Y = pixelA.y + (D-1); //to the bottom
That will give you a square perimeter that represents your required selection area.
Look at this example image below:
Each square is a pixel. If the "crown" icon represents pixel A and D is 3 (where your "less than D" means D has a maximum length of 2 pixels), can you see how the pseudo-code above applies?

Related

Matlab image translation matrix

I'm very new to Matlab. I'm learning some image manipulation basics, and I'm a bit confused on how to write a translation without using imtranslate.
this is my code but it just displays a black background. Thank you.
img = imread('name2.png');
figure(1);
% pixel matrix
[orig_x, orig_y,z] = size(img);
final_x = 600;
final_y = 600;
% define the final array with calculated dimensions and fill the array with zeros ie.,black
final_img = uint8(zeros([final_x final_y 3 ]));
for i = 1 : size(final_img, 1)
for j = 1 : size(final_img, 2)
new_x = img(i) + 5;
new_y = img(j) + 5;
% fprintf('X: %f\n',new_x); % prints 255
final_img(i) = new_x;
final_img(j) = new_y;
end
end
imshow(final_img);
This is one solution for 'translation only' transformation.
I = imread('Lenna.png');
shiftX = 5; % shift columns
shiftY = 5; % shift rows
% Assigning empty matrix for result, expected to be shiftX-1 larger in rows and shiftY-1 larger in columns
nI = uint8( zeros(size(I,1)+shiftY-1, size(I,2)+shiftX-1, size(I,3));
% Translate
nI(shiftY:end, shiftX:end, :) = I;
imshow(nI)
Now the image will start from (x,y) = (5,5) instead of (1,1). Also note that in matlab image coordinate system, x and y axis start from upper left corner (documentation).
final_img:
You've defined "final_img" with new x and new y but you haven't replaced the zeros in the red/green/blue values. It's all black because of your initialisation filling the final_img with all zeros.
Maybe try this instead of what you've written:
%{
[X,map] = imread('name2.png');
figure(1);
% X should be 600 by 600
%Translate X however you wish, e.g.:
X = X +5;
%Verify that the colormap, map, is not empty, and convert
%the data in X to RGB and store as your final_img.
if ~isempty(map)
final_img = ind2rgb(X,map);
end
%}
I am also not sure if you want to be indexing img with just a single i without the the other dimensions like you have:
new_x = img(i) + 5;
?
For the problems in your specific code, I wrote in the comments some of them.
A short way to achieve image translation is by 2D convolution with a filter of zeros and just one 1, that will preserve the values of the image, but relocate them according to the size of the filter and the position of the 1 in it.
That seems you want to move the image but preserve the size of the total image, if I get it right. So:
r=3; c=5; % number of rows and columns to move
filt=zeros(r*2+1, c*2+1); filt(end)=1; % the filetr
img2=conv2(img,filt,'same'); % the translated image
Just for the example, lets translate "cameraman" with 20 rows and columns:
img=imread('cameraman.tif');
imshow(img)
r=20; c=20;
filt=zeros(r*2+1, c*2+1); filt(end)=1;
img2=conv2(img,filt,'same');
figure; imshow(img2,[])

Creat a circular ROI and account for partial pixel values

I have a image of low resolution, 128x128 pixels. I need to obtain the mean value of a circle ROI, in order to do that I use the easy method:
%% Draw circle ROI
t = 0:pi/500:2*pi;
xi = ((R0/pixelSize)*cos(t)+63.5+x0+((Rsphere)/pixelSize)*cos(theta))*4;
yi = ((R0/pixelSize)*sin(t)+63.5+y0+((Rsphere)/pixelSize)*sin(theta))*4;
%% Calculate roi statistics
line(xi,yi,'LineWidth',1,'Color',color);
ROImask = poly2mask(xi,yi, size(im,1),size(im,2));
ptROI = find(ROImask);
ROImean = mean(im(ptROI));
The problem here is that using this method I don't account for the partial value of a pixel in the ROI, as can be seen in the image.
Is there any direct way to obtain the mean of the ROI weighting the value of the pixels?
Thanks
If you really want to do this exactly, you'll need to do some calculus (integral of a circle on a square domain for each pixel). But, this probably overkill for your application. My suggestion is to calculate your circle on a fine grid, then resize it to match the image:
upFactor = 3;
% load built-in example image
x = imread('rice.png');
% convert to double
x = im2double(x);
% define the ROI
center = [68.5, 180]; % [row, column]
radius = 1; % pixels
% do the distance calculation
% (getting the coordinate systems to match is the hardest part, try making
% small examples to see how it works)
iVector = (0:size(x,1)*upFactor-1)/upFactor + .5 + 1/upFactor/2;
jVector = (0:size(x,2)*upFactor-1)/upFactor + .5 + 1/upFactor/2;
[I, J] = ndgrid( iVector - center(1), jVector - center(2));
sqDist = I.^2 + J.^2;
insideBig = double(sqDist <= radius^2); % need this to not be logical type
% this resizes back to the original image size my taking the mean of each
% upFactor by upFactor block
inside = reshape( mean( im2col( insideBig, [upFactor upFactor], 'distinct')), size(x));
% check that we have the values we expect
uniqueVals = unique(inside(:))
% show examples
figure
imagesc(x)
figure
imagesc(inside)
result = sum(sum( x .* inside )) / sum(inside(:))

Code efficiency, Rotating image without imrotate [duplicate]

I am trying to rotate an image with Matlab without using imrotate function. I actually made it by using transformation matrix.But it is not good enough.The problem is, the rotated image is "sliding".Let me tell you with pictures.
This is my image which I want to rotate:
But when I rotate it ,for example 45 degrees, it becomes this:
I am asking why this is happening.Here is my code,is there any mathematical or programming mistakes about it?
image=torso;
%image padding
[Rows, Cols] = size(image);
Diagonal = sqrt(Rows^2 + Cols^2);
RowPad = ceil(Diagonal - Rows) + 2;
ColPad = ceil(Diagonal - Cols) + 2;
imagepad = zeros(Rows+RowPad, Cols+ColPad);
imagepad(ceil(RowPad/2):(ceil(RowPad/2)+Rows-1),ceil(ColPad/2):(ceil(ColPad/2)+Cols-1)) = image;
degree=45;
%midpoints
midx=ceil((size(imagepad,1)+1)/2);
midy=ceil((size(imagepad,2)+1)/2);
imagerot=zeros(size(imagepad));
%rotation
for i=1:size(imagepad,1)
for j=1:size(imagepad,2)
x=(i-midx)*cos(degree)-(j-midy)*sin(degree);
y=(i-midx)*sin(degree)+(j-midy)*cos(degree);
x=round(x)+midx;
y=round(y)+midy;
if (x>=1 && y>=1)
imagerot(x,y)=imagepad(i,j); % k degrees rotated image
end
end
end
figure,imagesc(imagerot);
colormap(gray(256));
The reason you have holes in your image is because you are computing the location in imagerot of each pixel in imagepad. You need to do the computation the other way around. That is, for each pixel in imagerot interpolate in imagepad. To do this, you just need to apply the inverse transform, which in the case of a rotation matrix is just the transpose of the matrix (just change the sign on each sin and translate the other way).
Loop over pixels in imagerot:
imagerot=zeros(size(imagepad)); % midx and midy same for both
for i=1:size(imagerot,1)
for j=1:size(imagerot,2)
x= (i-midx)*cos(rads)+(j-midy)*sin(rads);
y=-(i-midx)*sin(rads)+(j-midy)*cos(rads);
x=round(x)+midx;
y=round(y)+midy;
if (x>=1 && y>=1 && x<=size(imagepad,2) && y<=size(imagepad,1))
imagerot(i,j)=imagepad(x,y); % k degrees rotated image
end
end
end
Also note that your midx and midy need to be calculated with size(imagepad,2) and size(imagepad,1) respectively, since the first dimension refers to the number of rows (height) and the second to width.
NOTE: The same approach applies when you decide to adopt an interpolation scheme other than nearest neighbor, as in Rody's example with linear interpolation.
EDIT: I'm assuming you are using a loop for demonstrative purposes, but in practice there is no need for loops. Here's an example of nearest neighbor interpolation (what you are using), keeping the same size image, but you can modify this to produce a larger image that includes the whole source image:
imagepad = imread('peppers.png');
[nrows ncols nslices] = size(imagepad);
midx=ceil((ncols+1)/2);
midy=ceil((nrows+1)/2);
Mr = [cos(pi/4) sin(pi/4); -sin(pi/4) cos(pi/4)]; % e.g. 45 degree rotation
% rotate about center
[X Y] = meshgrid(1:ncols,1:nrows);
XYt = [X(:)-midx Y(:)-midy]*Mr;
XYt = bsxfun(#plus,XYt,[midx midy]);
xout = round(XYt(:,1)); yout = round(XYt(:,2)); % nearest neighbor!
outbound = yout<1 | yout>nrows | xout<1 | xout>ncols;
zout=repmat(cat(3,1,2,3),nrows,ncols,1); zout=zout(:);
xout(xout<1) = 1; xout(xout>ncols) = ncols;
yout(yout<1) = 1; yout(yout>nrows) = nrows;
xout = repmat(xout,[3 1]); yout = repmat(yout,[3 1]);
imagerot = imagepad(sub2ind(size(imagepad),yout,xout,zout(:))); % lookup
imagerot = reshape(imagerot,size(imagepad));
imagerot(repmat(outbound,[1 1 3])) = 0; % set background value to [0 0 0] (black)
To modify the above to linear interpolation, compute the 4 neighboring pixels to each coordinate in XYt and perform a weighted sum using the fractional components product as the weights. I'll leave that as an exercise, since it would only serve to bloat my answer further beyond the scope of your question. :)
The method you are using (rotate by sampling) is the fastest and simplest, but also the least accurate.
Rotation by area mapping, as given below (this is a good reference), is much better at preserving color.
But: note that this will only work on greyscale/RGB images, but NOT on colormapped images like the one you seem to be using.
image = imread('peppers.png');
figure(1), clf, hold on
subplot(1,2,1)
imshow(image);
degree = 45;
switch mod(degree, 360)
% Special cases
case 0
imagerot = image;
case 90
imagerot = rot90(image);
case 180
imagerot = image(end:-1:1, end:-1:1);
case 270
imagerot = rot90(image(end:-1:1, end:-1:1));
% General rotations
otherwise
% Convert to radians and create transformation matrix
a = degree*pi/180;
R = [+cos(a) +sin(a); -sin(a) +cos(a)];
% Figure out the size of the transformed image
[m,n,p] = size(image);
dest = round( [1 1; 1 n; m 1; m n]*R );
dest = bsxfun(#minus, dest, min(dest)) + 1;
imagerot = zeros([max(dest) p],class(image));
% Map all pixels of the transformed image to the original image
for ii = 1:size(imagerot,1)
for jj = 1:size(imagerot,2)
source = ([ii jj]-dest(1,:))*R.';
if all(source >= 1) && all(source <= [m n])
% Get all 4 surrounding pixels
C = ceil(source);
F = floor(source);
% Compute the relative areas
A = [...
((C(2)-source(2))*(C(1)-source(1))),...
((source(2)-F(2))*(source(1)-F(1)));
((C(2)-source(2))*(source(1)-F(1))),...
((source(2)-F(2))*(C(1)-source(1)))];
% Extract colors and re-scale them relative to area
cols = bsxfun(#times, A, double(image(F(1):C(1),F(2):C(2),:)));
% Assign
imagerot(ii,jj,:) = sum(sum(cols),2);
end
end
end
end
subplot(1,2,2)
imshow(imagerot);
Output:
Rotates colored image according to angle given by user without any cropping of image in matlab.
Output of this program is similar to output of inbuilt command "imrotate" .This program dynamically creates background according to angle input given by user.By using rotation matrix and origin shifting, we get relation between coordinates of initial and final image.Using relation between coordinates of initial and final image, we now map the intensity values for each pixel.
img=imread('img.jpg');
[rowsi,colsi,z]= size(img);
angle=45;
rads=2*pi*angle/360;
%calculating array dimesions such that rotated image gets fit in it exactly.
% we are using absolute so that we get positve value in any case ie.,any quadrant.
rowsf=ceil(rowsi*abs(cos(rads))+colsi*abs(sin(rads)));
colsf=ceil(rowsi*abs(sin(rads))+colsi*abs(cos(rads)));
% define an array withcalculated dimensionsand fill the array with zeros ie.,black
C=uint8(zeros([rowsf colsf 3 ]));
%calculating center of original and final image
xo=ceil(rowsi/2);
yo=ceil(colsi/2);
midx=ceil((size(C,1))/2);
midy=ceil((size(C,2))/2);
% in this loop we calculate corresponding coordinates of pixel of A
% for each pixel of C, and its intensity will be assigned after checking
% weather it lie in the bound of A (original image)
for i=1:size(C,1)
for j=1:size(C,2)
x= (i-midx)*cos(rads)+(j-midy)*sin(rads);
y= -(i-midx)*sin(rads)+(j-midy)*cos(rads);
x=round(x)+xo;
y=round(y)+yo;
if (x>=1 && y>=1 && x<=size(img,1) && y<=size(img,2) )
C(i,j,:)=img(x,y,:);
end
end
end
imshow(C);
Check this out.
this is fastest way that you can do.
img = imread('Koala.jpg');
theta = pi/10;
rmat = [
cos(theta) sin(theta) 0
-sin(theta) cos(theta) 0
0 0 1];
mx = size(img,2);
my = size(img,1);
corners = [
0 0 1
mx 0 1
0 my 1
mx my 1];
new_c = corners*rmat;
T = maketform('affine', rmat); %# represents translation
img2 = imtransform(img, T, ...
'XData',[min(new_c(:,1)) max(new_c(:,1))],...
'YData',[min(new_c(:,2)) max(new_c(:,2))]);
subplot(121), imshow(img);
subplot(122), imshow(img2);

Image rotation by Matlab without using imrotate

I am trying to rotate an image with Matlab without using imrotate function. I actually made it by using transformation matrix.But it is not good enough.The problem is, the rotated image is "sliding".Let me tell you with pictures.
This is my image which I want to rotate:
But when I rotate it ,for example 45 degrees, it becomes this:
I am asking why this is happening.Here is my code,is there any mathematical or programming mistakes about it?
image=torso;
%image padding
[Rows, Cols] = size(image);
Diagonal = sqrt(Rows^2 + Cols^2);
RowPad = ceil(Diagonal - Rows) + 2;
ColPad = ceil(Diagonal - Cols) + 2;
imagepad = zeros(Rows+RowPad, Cols+ColPad);
imagepad(ceil(RowPad/2):(ceil(RowPad/2)+Rows-1),ceil(ColPad/2):(ceil(ColPad/2)+Cols-1)) = image;
degree=45;
%midpoints
midx=ceil((size(imagepad,1)+1)/2);
midy=ceil((size(imagepad,2)+1)/2);
imagerot=zeros(size(imagepad));
%rotation
for i=1:size(imagepad,1)
for j=1:size(imagepad,2)
x=(i-midx)*cos(degree)-(j-midy)*sin(degree);
y=(i-midx)*sin(degree)+(j-midy)*cos(degree);
x=round(x)+midx;
y=round(y)+midy;
if (x>=1 && y>=1)
imagerot(x,y)=imagepad(i,j); % k degrees rotated image
end
end
end
figure,imagesc(imagerot);
colormap(gray(256));
The reason you have holes in your image is because you are computing the location in imagerot of each pixel in imagepad. You need to do the computation the other way around. That is, for each pixel in imagerot interpolate in imagepad. To do this, you just need to apply the inverse transform, which in the case of a rotation matrix is just the transpose of the matrix (just change the sign on each sin and translate the other way).
Loop over pixels in imagerot:
imagerot=zeros(size(imagepad)); % midx and midy same for both
for i=1:size(imagerot,1)
for j=1:size(imagerot,2)
x= (i-midx)*cos(rads)+(j-midy)*sin(rads);
y=-(i-midx)*sin(rads)+(j-midy)*cos(rads);
x=round(x)+midx;
y=round(y)+midy;
if (x>=1 && y>=1 && x<=size(imagepad,2) && y<=size(imagepad,1))
imagerot(i,j)=imagepad(x,y); % k degrees rotated image
end
end
end
Also note that your midx and midy need to be calculated with size(imagepad,2) and size(imagepad,1) respectively, since the first dimension refers to the number of rows (height) and the second to width.
NOTE: The same approach applies when you decide to adopt an interpolation scheme other than nearest neighbor, as in Rody's example with linear interpolation.
EDIT: I'm assuming you are using a loop for demonstrative purposes, but in practice there is no need for loops. Here's an example of nearest neighbor interpolation (what you are using), keeping the same size image, but you can modify this to produce a larger image that includes the whole source image:
imagepad = imread('peppers.png');
[nrows ncols nslices] = size(imagepad);
midx=ceil((ncols+1)/2);
midy=ceil((nrows+1)/2);
Mr = [cos(pi/4) sin(pi/4); -sin(pi/4) cos(pi/4)]; % e.g. 45 degree rotation
% rotate about center
[X Y] = meshgrid(1:ncols,1:nrows);
XYt = [X(:)-midx Y(:)-midy]*Mr;
XYt = bsxfun(#plus,XYt,[midx midy]);
xout = round(XYt(:,1)); yout = round(XYt(:,2)); % nearest neighbor!
outbound = yout<1 | yout>nrows | xout<1 | xout>ncols;
zout=repmat(cat(3,1,2,3),nrows,ncols,1); zout=zout(:);
xout(xout<1) = 1; xout(xout>ncols) = ncols;
yout(yout<1) = 1; yout(yout>nrows) = nrows;
xout = repmat(xout,[3 1]); yout = repmat(yout,[3 1]);
imagerot = imagepad(sub2ind(size(imagepad),yout,xout,zout(:))); % lookup
imagerot = reshape(imagerot,size(imagepad));
imagerot(repmat(outbound,[1 1 3])) = 0; % set background value to [0 0 0] (black)
To modify the above to linear interpolation, compute the 4 neighboring pixels to each coordinate in XYt and perform a weighted sum using the fractional components product as the weights. I'll leave that as an exercise, since it would only serve to bloat my answer further beyond the scope of your question. :)
The method you are using (rotate by sampling) is the fastest and simplest, but also the least accurate.
Rotation by area mapping, as given below (this is a good reference), is much better at preserving color.
But: note that this will only work on greyscale/RGB images, but NOT on colormapped images like the one you seem to be using.
image = imread('peppers.png');
figure(1), clf, hold on
subplot(1,2,1)
imshow(image);
degree = 45;
switch mod(degree, 360)
% Special cases
case 0
imagerot = image;
case 90
imagerot = rot90(image);
case 180
imagerot = image(end:-1:1, end:-1:1);
case 270
imagerot = rot90(image(end:-1:1, end:-1:1));
% General rotations
otherwise
% Convert to radians and create transformation matrix
a = degree*pi/180;
R = [+cos(a) +sin(a); -sin(a) +cos(a)];
% Figure out the size of the transformed image
[m,n,p] = size(image);
dest = round( [1 1; 1 n; m 1; m n]*R );
dest = bsxfun(#minus, dest, min(dest)) + 1;
imagerot = zeros([max(dest) p],class(image));
% Map all pixels of the transformed image to the original image
for ii = 1:size(imagerot,1)
for jj = 1:size(imagerot,2)
source = ([ii jj]-dest(1,:))*R.';
if all(source >= 1) && all(source <= [m n])
% Get all 4 surrounding pixels
C = ceil(source);
F = floor(source);
% Compute the relative areas
A = [...
((C(2)-source(2))*(C(1)-source(1))),...
((source(2)-F(2))*(source(1)-F(1)));
((C(2)-source(2))*(source(1)-F(1))),...
((source(2)-F(2))*(C(1)-source(1)))];
% Extract colors and re-scale them relative to area
cols = bsxfun(#times, A, double(image(F(1):C(1),F(2):C(2),:)));
% Assign
imagerot(ii,jj,:) = sum(sum(cols),2);
end
end
end
end
subplot(1,2,2)
imshow(imagerot);
Output:
Rotates colored image according to angle given by user without any cropping of image in matlab.
Output of this program is similar to output of inbuilt command "imrotate" .This program dynamically creates background according to angle input given by user.By using rotation matrix and origin shifting, we get relation between coordinates of initial and final image.Using relation between coordinates of initial and final image, we now map the intensity values for each pixel.
img=imread('img.jpg');
[rowsi,colsi,z]= size(img);
angle=45;
rads=2*pi*angle/360;
%calculating array dimesions such that rotated image gets fit in it exactly.
% we are using absolute so that we get positve value in any case ie.,any quadrant.
rowsf=ceil(rowsi*abs(cos(rads))+colsi*abs(sin(rads)));
colsf=ceil(rowsi*abs(sin(rads))+colsi*abs(cos(rads)));
% define an array withcalculated dimensionsand fill the array with zeros ie.,black
C=uint8(zeros([rowsf colsf 3 ]));
%calculating center of original and final image
xo=ceil(rowsi/2);
yo=ceil(colsi/2);
midx=ceil((size(C,1))/2);
midy=ceil((size(C,2))/2);
% in this loop we calculate corresponding coordinates of pixel of A
% for each pixel of C, and its intensity will be assigned after checking
% weather it lie in the bound of A (original image)
for i=1:size(C,1)
for j=1:size(C,2)
x= (i-midx)*cos(rads)+(j-midy)*sin(rads);
y= -(i-midx)*sin(rads)+(j-midy)*cos(rads);
x=round(x)+xo;
y=round(y)+yo;
if (x>=1 && y>=1 && x<=size(img,1) && y<=size(img,2) )
C(i,j,:)=img(x,y,:);
end
end
end
imshow(C);
Check this out.
this is fastest way that you can do.
img = imread('Koala.jpg');
theta = pi/10;
rmat = [
cos(theta) sin(theta) 0
-sin(theta) cos(theta) 0
0 0 1];
mx = size(img,2);
my = size(img,1);
corners = [
0 0 1
mx 0 1
0 my 1
mx my 1];
new_c = corners*rmat;
T = maketform('affine', rmat); %# represents translation
img2 = imtransform(img, T, ...
'XData',[min(new_c(:,1)) max(new_c(:,1))],...
'YData',[min(new_c(:,2)) max(new_c(:,2))]);
subplot(121), imshow(img);
subplot(122), imshow(img2);

I want to color code a satellite trajectory plot using Matlab

I am creating a plot in Matlab that maps the azimuth and elevation of several GPS satellites over time. Below is an example of an image of the plotted GPS satellite trajectories.
However, I also want to plot the S_4 index (scintillation effect caused by the ionosphere) on the same plot. I want to color code each of the GPS satellite paths to show a high S_4 index as red, and a low S_4 index as blue. I have data for all of this, but I cannot figure out a way to color code each GPS path.
Currently I know the position of each satellite at every second of a day (this is how I am able to plot the trajectory). I also have S_4 index values at different times and for different satellites (the S_4 index matrix is not the same size as the satellite position matrix).
Any ideas?
This is the function I used. It uses as input a matrix called plotMat:
plotMat=[svID(satellite id number), gpsSec, elevation(radians), azimuth(radians)]
My function:
% find out from 'plotMat' if plotting satellite locations or trajectories in
% addition determine how many satellites are being tracked and how many
% samples for each satellite (# samples / satellite must always be equal)
gpsTime = plotMat(1,2);
i = 1;
t = gpsTime;
while ((i ~= size(plotMat,1)) & (t == gpsTime))
i = i + 1;
t = plotMat(i,2);
end
if (t == gpsTime)
sats = i;
else
sats = i - 1;
end;
samples = size(plotMat,1) / sats;
SVs = plotMat(1:sats,1);
elevation = plotMat(:,3);
azimuth = plotMat(:,4);
% initialize polar - plotting area
figure(10);clf;
axis([-1.4 1.4 -1.1 1.1]);
axis('off');
axis(axis);
hold on;
% plot circular axis and labels
th = 0:pi/50:2*pi;
x = [ cos(th) .67.*cos(th) .33.*cos(th) ];
y = [ sin(th) .67.*sin(th) .33.*sin(th) ];
plot(x,y,'color','w');
text(1.1,0,'90','horizontalalignment','center');
text(0,1.1,'0','horizontalalignment','center');
text(-1.1,0,'270','horizontalalignment','center');
text(0,-1.1,'180','horizontalalignment','center');
% plot spoke axis and labels
th = (1:6)*2*pi/12;
x = [ -cos(th); cos(th) ];
y = [ -sin(th); sin(th) ];
plot(x,y,'color','w');
text(-.46,.93,'0','horizontalalignment','center');
text(-.30,.66,'30','horizontalalignment','center');
text(-.13,.36,'60','horizontalalignment','center');
text(.04,.07,'90','horizontalalignment','center');
% plot titles
if (samples == 1)
title('Satellite Position Plot');
subtitle = sprintf('GPS time : %.2f sec',plotMat(1,2));
else
title('Satellite Trajectory Plot');
subtitle = sprintf('GPS time range : %.2f sec to %.2f sec', ...
plotMat(1,2),plotMat(size(plotMat,1),2));
text(-1.6,1,'SVID/Last Position','color','r');
text(-1.6,.9,'Positive Elevation','color','y');
text(-1.6,.8,'Negative Elevation','color','b');
end
text(0,-1.3,subtitle,'horizontalalignment','center');
% plot trajectories (or positions) and label the last postion with the
% satellite SV id; in addition, last postions are in red, otherwise position
% elevations are yellow and negative elavations are blue
%
% loop through samples
for s = 1:samples
% plot each satellite location for that sample
for sv = 1:sats
% check if positive or negative elevation
if (elevation((s - 1) * sats + sv) < 0)
elNeg = 1;
else
elNeg = 0;
end
% convert to plottable cartesian coordinates
el = elevation((s - 1) * sats + sv);
az = azimuth((s - 1) * sats + sv);
x = (pi/2-abs(el))/(pi/2).*cos(az-pi/2);
y = -1*(pi/2-abs(el))/(pi/2).*sin(az-pi/2);
% check for final sample
if (s == samples)
plot(x,y,'r*');
text(x,y+.07,int2str(SVs(sv)), ...
'horizontalalignment', ...
'center','color','r');
else
% check for +/- elevation
if (elNeg == 0)
plot(x,y,'y.');
else
plot(x,y,'b.');
end
end
end
end
axis equal;
On the previous code I haven't added the S_4 index. The following code compares the GPS seconds on the scintillation (S_4) data with the GPS seconds with the satellite position data. The matrix scint.mat refers to the scintillation data, while txinfo.mat refers to the satellite position data. This code creates a combination code that agrees on the GPS second and satellite identification number.
load('scint_324_first')
scint = scint';
load('txinfo_324_first_wrw')
txinfo = txinfo';
k = 0;
for i = 1:length(scint)
disp(num2str(i))
for j = 1:length(txinfo)
if scint(i,2) == txinfo(j,2) && scint(i,15) == txinfo(j,8)
k = k+1;
combo(k,:) = [scint(i,:) txinfo(j,:)];
end
end
end
If the S_4 values change over time, shall the colour coding change within single lines?
It's maybe not the most efficient way, but you could draw just lines for each piece of the orbits. Like
s4code = [1 0 0; 0 0 1]; % blue & red
for i = time_vector
if s4(i) > something
s = 2
else
s = 1
end
line(x(i:(i+1)), y(i:(i+1)), 'color', s4code(s, :))
end
About orbit data and s4 data not having the same size ... make them have the same size ... interp1, for example ;-)
If you are plotting using a polar plot, try instead 3D Polar Plot (FEX code by Ken Garrard)
If you are using plot, try Colored line or scatter plot or cline.m (again FEX files)
the last plot was done by:
x = 1:300
color_line(x,sin(x/20),sin(x/20))