2D Image transformations by pixel - image

I am trying to do a translation, euclidian, similarity, affine and projective transformation on an image pixel by pixel. the input for my program is the image name and the transformation matrix.
This is my code
function imagetrans(name, m)
Image = imread(name);
[rows, cols] = size(Image);
newImage(1:rows,1:cols) = 1;
for row = 1 : rows
for col = 1 : cols
if(Image(row,col) == 0)
point = [row;col;1];
answer = m * point;
answer = int8(answer);
newx = answer(1,1);
newy = answer(2,1);
newImage(newx,newy) = 0;
end
end
end
imshow(newImage);
end
This is the image
Right now I am testing just a translation matrix.
matrix =
1 0 7
0 1 2
0 0 1
when I pass the image and matrix through the function my result is just a little black line
What am I doing wrong?

Using the matlab debugger, I noticed that that you are casting to int8, which is too small too represent all indices. So, you should use int32/int64 or uint32/uint64 instead, i.e.
answer = uint8(answer);
should be
answer = uint32(answer);
Please try to use the Matlab debugger before asking the question: why does it not work?

Related

Interp2 of image with transformed coordinates

I have 2 greyscale images that i am trying to align using scalar scaling 1 , rotation matrix [2,2] and translation vector [2,1]. I can calculate image1's transformed coordinates as
y = s*R*x + t;
Below the resulting images are shown.
The first image is image1 before transformation,
the second image is image1 (red) with attempted interpolation using interp2 shown on top of image2 (green)
The third image is when i manually insert the pixel values from image1 into an empty array (that has the same size as image2) using the transformed coordinates.
From this we can see that the coordinate transformation must have been successful, as the images are aligned although not perfectly (which is to be expected since only 2 coordinates were used in calculating s, R and t) .
How come interp2 is not producing a result more similar to when i manually insert pixel values?
Below the code for doing this is included:
Interpolation code
function [transformed_image] = interpolate_image(im_r,im_t,s,R,t)
[m,n] = size(im_t);
% doesn't help if i use get_grid that the other function is using here
[~, grid_xr, grid_yr] = get_ipgrid(im_r);
[x_t, grid_xt, grid_yt] = get_ipgrid(im_t);
y = s*R*x_t + t;
yx = reshape(y(1,:), m,n);
yy = reshape(y(2,:), m,n);
transformed_image = interp2(grid_xr, grid_yr, im_r, yx, yy, 'nearest');
end
function [x, grid_x, grid_y] = get_ipgrid(image)
[m,n] = size(image);
[grid_x,grid_y] = meshgrid(1:n,1:m);
x = [reshape(grid_x, 1, []); reshape(grid_y, 1, [])]; % X is [2xM*N] coordinate pairs
end
The manual code
function [transformed_image] = transform_image(im_r,im_t,s,R,t)
[m,n] = size(im_t);
[x_t, grid_xt, grid_yt] = get_grid(im_t);
y = s*R*x_t + t;
ymat = reshape(y',m,n,2);
yx = ymat(:,:,1);
yy = ymat(:,:,2);
transformed_image = zeros(m,n);
for i = 1:m
for j = 1:n
% make sure coordinates are inside
if (yx(i,j) < m & yy(i,j) < n & yx(i,j) > 0.5 & yy(i,j) > 0.5)
transformed_image(round(yx(i,j)),round(yy(i,j))) = im_r(i,j);
end
end
end
end
function [x, grid_x, grid_y] = get_grid(image)
[m,n] = size(image);
[grid_y,grid_x] = meshgrid(1:n,1:m);
x = [grid_x(:) grid_y(:)]'; % X is [2xM*N] coordinate pairs
end
Can anyone see what i'm doing wrong with interp2? I feel like i have tried everything
Turns out i got interpolation all wrong.
In my question i calculate the coordinates of im1 in im2.
However the way interpolation works is that i need to calculate the coordinates of im2 in im1 such that i can map the image as shown below.
This means that i also calculated the wrong s,R and t since they were used to transform im1 -> im2, where as i needed im2 -> im1. (this is also called the inverse transform). Below is the manual code, that is basically the same as interp2 with nearest neighbour interpolation
function [transformed_image] = transform_image(im_r,im_t,s,R,t)
[m,n] = size(im_t);
[x_t, grid_xt, grid_yt] = get_grid(im_t);
y = s*R*x_t + t;
ymat = reshape(y',m,n,2);
yx = ymat(:,:,1);
yy = ymat(:,:,2);
transformed_image = zeros(m,n);
for i = 1:m
for j = 1:n
% make sure coordinates are inside
if (yx(i,j) < m & yy(i,j) < n & yx(i,j) > 0.5 & yy(i,j) > 0.5)
transformed_image(i,j) = im_r(round(yx(i,j)),round(yy(i,j)));
end
end
end
end

Rotating image without custom functions

Already checked This SO Question , but my question is how to make changes appear to image after the calculation , and code will explain better , i have marked the line where is am confused:
% code written by Zulqurnain Jutt
img1 = imread('rotme.jpg');
img = img1;
[r,m] = size(img);
promt = 'Enter Angle to Rotate an image:=:';
x = input(promt);
% making antirotate matrix
coss = cos(x);
sinn = sin(x);
antirotate = floor( [coss -sinn 0;sinn coss 0; 0 0 1] );
for i=1:r
for j=1:m
%forming point matrix
pointMat = [i-1;j-1;1];
%multiplying both matrix
mul = floor(antirotate*pointMat);
% swapping points
if mul(1)<0
mul(1) = abs(mul(1));
end
if mul(2)<0
mul(2) = abs(mul(2));
end
img( (mul(1)+1) , (mul(2)+1) ) = img(i,j); % Here Lies my problem
end
end
imshow(img);
Problem 1: "Why the output in imshow after assigning the new pixel values giving me three different images as output red , green , blue. is there any way to fix it and get one image as output?"
Problem 2: "i am converting negative coordinates to positive is this okay?"
Note: it is homework question, and i am not hidding it. but is need help

MATLAB finding average RGB value across all pixels in image

Code is below. I'm looping through an input image 1 pixel at a time and determining its RGB value. Afterwards i'm trying to find the average RGB value for the image overall. For some reason the averaging portion of my code isnt working though.
im = imread(filename);
[width, height, depth] = size(im);
count = 0;
r=0;
g=0;
b=0;
for x = 1 : width
for y = 1: height
r = r + im(x,y,1);
g = g + im(x,y,2);
b = b + im(x,y,3);
count = count + 1;
end
end
%find averages of each RGB value.
r2 = r/count;
g2 = g/count;
b2 = b/count;
Why not vectorizing and using mean?
mean( reshape( im, [], 3 ), 1 )
The following code would work as well;
pep = imread('peppers.png');
mean(mean(pep))
This will return a 1x1x3 vector which will be the mean values of R, G, and B respectively.

How does this MATLAB code make an image into a binary image?

v = videoinput('winvideo', 1, 'YUY2_320x240');
s = serial('COM1', 'BaudRate', 9600);
fopen(s);
while(1)
h = getsnapshot(v);
rgb = ycbcr2rgb(h);
for i = 1:240
for j = 1:320
if rgb(i,j,1) > 140 && rgb(i,j,2) < 100 % use ur own conditions
bm(i, j) = 1;
else
bm(i, j) = 0;
end
end
end
This is the code i got from my senior regarding image processing using MATLAB. The above code is to convert the image to binary image, But in the code rgb(i, j, 1) > 140 I didn't understand that command. How to select that 140 and what does that rgb(i, j, 1) mean?
You have an RGB image rgb where the third dimension are the RGB color planes. Thus, rgb(i,j,1) is the red value at row i, column j.
By doing rgb(i,j,1)>140 it tests if this red value is greater than 140. The value 140 appears to be ad hoc, picked for a specific task.
The code is extremely inefficient as there is no need for a loop:
bm = rgb(:,:,1)>140 & rgb(:,:,2)<100;
Note the change from && to the element-wise operator &. Here I'm assuming that the size of rgb is 240x320x3.
Edit: The threshold values you choose completely depend on the task, but a common approach to automatic thresholding is is Otsu's method, graythresh. You can apply it to a single color plane to get a threshold:
redThresh = graythresh(rgb(:,:,1)) * 255;
Note that graythresh returns a value on [0,1], so you have to scale that by the data range.

Ellipse Detection using Hough Transform

using Hough Transform, how can I detect and get coordinates of (x0,y0) and "a" and "b" of an ellipse in 2D space?
This is ellipse01.bmp:
I = imread('ellipse01.bmp');
[m n] = size(I);
c=0;
for i=1:m
for j=1:n
if I(i,j)==1
c=c+1;
p(c,1)=i;
p(c,2)=j;
end
end
end
Edges=transpose(p);
Size_Ellipse = size(Edges);
B = 1:ceil(Size_Ellipse(1)/2);
Acc = zeros(length(B),1);
a1=0;a2=0;b1=0;b2=0;
Ellipse_Minor=[];Ellipse_Major=[];Ellipse_X0 = [];Ellipse_Y0 = [];
Global_Threshold = ceil(Size_Ellipse(2)/6);%Used for Major Axis Comparison
Local_Threshold = ceil(Size_Ellipse(1)/25);%Used for Minor Axis Comparison
[Y,X]=find(Edges);
Limit=numel(Y);
Thresh = 150;
Para=[];
for Count_01 =1:(Limit-1)
for Count_02 =(Count_01+1):Limit
if ((Count_02>Limit) || (Count_01>Limit))
continue
end
a1=Y(Count_01);b1=X(Count_01);
a2=Y(Count_02);b2=X(Count_02);
Dist_01 = (sqrt((a1-a2)^2+(b1-b2)^2));
if (Dist_01 >Global_Threshold)
Center_X0 = (b1+b2)/2;Center_Y0 = (a1+a2)/2;
Major = Dist_01/2.0;Alpha = atan((a2-a1)/(b2-b1));
if(Alpha == 0)
for Count_03 = 1:Limit
if( (Count_03 ~= Count_01) || (Count_03 ~= Count_02))
a3=Y(Count_03);b3=X(Count_03);
Dist_02 = (sqrt((a3 - Center_Y0)^2+(b3 - Center_X0)^2));
if(Dist_02 > Local_Threshold)
Cos_Tau = ((Major)^2 + (Dist_02)^2 - (a3-a2)^2 - (b3-b2)^2)/(2*Major*Dist_02);
Sin_Tau = 1 - (Cos_Tau)^2;
Minor_Temp = ((Major*Dist_02*Sin_Tau)^2)/(Major^2 - ((Dist_02*Cos_Tau)^2));
if((Minor_Temp>1) && (Minor_Temp<B(end)))
Acc(round(Minor_Temp)) = Acc(round(Minor_Temp))+1;
end
end
end
end
end
Minor = find(Acc == max(Acc(:)));
if(Acc(Minor)>Thresh)
Ellipse_Minor(end+1)=Minor(1);Ellipse_Major(end+1)=Major;
Ellipse_X0(end+1) = Center_X0;Ellipse_Y0(end+1) = Center_Y0;
for Count = 1:numel(X)
Para_X = ((X(Count)-Ellipse_X0(end))^2)/(Ellipse_Major(end)^2);
Para_Y = ((Y(Count)-Ellipse_Y0(end))^2)/(Ellipse_Minor(end)^2);
if (((Para_X + Para_Y)>=-2)&&((Para_X + Para_Y)<=2))
Edges(X(Count),Y(Count))=0;
end
end
end
Acc = zeros(size(Acc));
end
end
end
Although this is an old question, perhaps what I found can help someone.
The main problem of using the normal Hough Transform to detect ellipses is the dimension of the accumulator, since we would need to vote for 5 variables (the equation is explained here):
There is a very nice algorithm where the accumulator can be a simple 1D array, for example, and that runs in . If you wanna see code, you can look at here (the image used to test was that posted above).
If you use circle for rough transform is given as rho = xcos(theta) + ysin(theta)
For ellipse since it is
You could transform the equation as
rho = axcos(theta) + bysin(theta)
Although I am not sure if you use standard Hough Transform, for ellipse-like transforms, you could manipulate the first given function.
If your ellipse is as provided, being a true ellipse and not a noisy sample of points;
the search for the two furthest points gives the ends of the major axis,
the search for the two nearest points gives the ends of the minor axis,
the intersection of these lines (you can check it's a right angle) occurs at the centre.
If you know the 'a' and 'b' of an ellipse then you can rescale the image by factor of a/b in one direction and look for circle. I am still thinking about what to do when a and b are unknown.
If you know that it is circle then use Hough transform for circles. Here is a sample code:
int accomulatorResolution = 1; // for each pixel
int minDistBetweenCircles = 10; // In pixels
int cannyThresh = 20;
int accomulatorThresh = 5*_accT+1;
int minCircleRadius = 0;
int maxCircleRadius = _maxR*10;
cvClearMemStorage(storage);
circles = cvHoughCircles( gryImage, storage,
CV_HOUGH_GRADIENT, accomulatorResolution,
minDistBetweenCircles,
cannyThresh , accomulatorThresh,
minCircleRadius,maxCircleRadius );
// Draw circles
for (int i = 0; i < circles->total; i++){
float* p = (float*)cvGetSeqElem(circles,i);
// Draw center
cvCircle(dstImage, cvPoint(cvRound(p[0]),cvRound(p[1])),
1, CV_RGB(0,255,0), -1, 8, 0 );
// Draw circle
cvCircle(dstImage, cvPoint(cvRound(p[0]),cvRound(p[1])),
cvRound(p[2]),CV_RGB(255,0,0), 1, 8, 0 );
}

Resources