Create a diamond in the picture - image

I'm going to write a program that does a diamond within a specific image
i wrote this code
Img=zeros(256,256);
for x=1:256
for y=1:256
if(y-x==128)||(y-x==-128)||(y+x==128)
Img(x,y)=1;
end
end
end
imshow(Img);
I could draw three sides diamond.
How do I draw a fourth side؟

Luis Mendo nailed the last condition in the if statement of your loop to draw the last line. His solution is what you are looking for should you want a for loop solution.
However, if you want something more vectorized, a more efficient way to do this would be to define a grid of co-ordinates using meshgrid then simply apply a chain of logical operations to get your diamond. In other words:
[x,y] = meshgrid(1:256, 1:256);
Img = abs(x-y) == 128 | x+y == 384 | x+y == 128;
imshow(Img);
We thus get:
In general, for a given size image that is square, you can adapt this to any size image by:
N = 256; %// Change here - width/height of your image
[x,y] = meshgrid(1:N, 1:N);
Img = abs(x-y) == floor(N/2) | x+y == floor(3*N/2) | x+y == floor(N/2);
imshow(Img);
I've placed a floor operation in case you want to specify an image size that is not evenly divisible by 2. However, the symmetry of the diamond may not look correct, but the code will work regardless.

The condition you are missing is y+x==384. So, replace the if line by
if (y-x==128)||(y-x==-128)||(y+x==128)||(y+x==384)
The condition would look more symmetric if your coordinates were centered around 0, say -128:128:
Img=zeros(257,257);
for x=-128:128
for y=-128:128
if(y-x==128)||(y-x==-128)||(y+x==128)||(y+x==-128)
Img(129+x,129+y)=1;
end
end
end
imshow(Img);
As noted by #kkuilla, this can be easily vectorized. See #rayryeng's answer.

Related

How to flip image in matlab without using built in functions?

Write a MATLAB code that reads a gray scale image and generates the flipped image of original image.enter image description here
i am trying this code but is not giving me correct flipped image.Help will be much appreciated.Thankyou
clear all
clc
a=imread('pout.tif');
[r,c]=size(a);
for i=r:-1:1
k=1;
for j=1:1:c
temp=a(k,j);
result(k,j)=a(i,j);
result(i,j)=temp;
k=k+1;
end
end
subplot(1,2,1), imshow(a)
subplot(1,2,2),imshow(result)
What you're doing with indices is kind of unclear. You should also pre-allocate memory for the result.
clear all
clc
a=imread('pout.tif');
[r,c]=size(a);
result = a; % preallocate memory for result
for i=1:r
for j=1:c
result(r-i+1,j)=a(i,j);
end
end
subplot(1,2,1), imshow(a)
subplot(1,2,2),imshow(result)
You can use basic indexing to flip a matrix. 2D case (gray-scale image):
a = a(:,end:-1:1); % horizontal flip
a = a(end:-1:1,:); % vertical flip
a = a(end:-1:1,end:-1:1); % flip both: 180 degree rotation
For the 3D case (color image) add a 3rd index ::
a = a(:,end:-1:1,:); % horizontal flip

How to create a mask or detect image section based on the intensity value?

I have a matrix named figmat from which I obtain the following pcolor plot (Matlab-Version R 2016b).
Basically I only want to extract the bottom red high intensity line from this plot.
I thought of doing it in some way of extracting the maximum values from the matrix and creating some sort of mask on the main matrix. But I'm not understanding a possible way to achieve this. Can it be accomplished with the help of any edge/image detection algorithms?
I was trying something like this with the following code to create a mask
A=max(figmat);
figmat(figmat~=A)=0;
imagesc(figmat);
But this gives only the boundary of maximum values. I also need the entire red color band.
Okay, I assume that the red line is linear and its values can uniquely be separated from the rest of the picture. Let's generate some test data...
[x,y] = meshgrid(-5:.2:5, -5:.2:5);
n = size(x,1)*size(x,2);
z = -0.2*(y-(0.2*x+1)).^2 + 5 + randn(size(x))*0.1;
figure
surf(x,y,z);
This script generates a surface function. Its set of maximum values (x,y) can be described by a linear function y = 0.2*x+1. I added a bit of noise to it to make it a bit more realistic.
We now select all points where z is smaller than, let's say, 95 % of the maximum value. Therefore find can be used. Later, we want to use one-dimensional data, so we reshape everything.
thresh = min(min(z)) + (max(max(z))-min(min(z)))*0.95;
mask = reshape(z > thresh,1,n);
idx = find(mask>0);
xvec = reshape(x,1,n);
yvec = reshape(y,1,n);
xvec and yvec now contain the coordinates of all values > thresh.
The last step is to do some linear polynomial over all points.
pp = polyfit(xvec(idx),yvec(idx),1)
pp =
0.1946 1.0134
Obviously these are roughly the coefficients of y = 0.2*x+1 as it should be.
I do not know, if this also works with your data, since I made some assumptions. The threshold level must be chosen carefully. Maybe some preprocessing must be done to dynamically detect this level if you really want to process your images automatically. There might also be a simpler way to do it... but for me this one was straight forward without the need of any toolboxes.
By assuming:
There is only one band to extract.
It always has the maximum values.
It is linear.
I can adopt my previous answer to this case as well, with few minor changes:
First, we get the distribution of the values in the matrix and look for a population in the top values, that can be distinguished from the smaller values. This is done by finding the maximum value x(i) on the histogram that:
Is a local maximum (its bin is higher than that of x(i+1) and x(i-1))
Has more values above it than within it (the sum of the height of bins x(i+1) to x(end) < the height of bin x):
This is how it is done:
[h,x] = histcounts(figmat); % get the distribution of intesities
d = diff(fliplr(h)); % The diffrence in bin height from large x to small x
band_min_ind = find(cumsum(d)>size(figmat,2) & d<0, 1); % 1st bin that fit the conditions
flp_val = fliplr(x); % the value of x from large to small
band_min = flp_val(band_min_ind); % the value of x that fit the conditions
Now we continue as before. Mask all the unwanted values, interpolate the linear line:
mA = figmat>band_min; % mask all values below the top value mode
[y1,x1] = find(mA,1); % find the first nonzero row
[y2,x2] = find(mA,1,'last'); % find the last nonzero row
m = (y1-y2)/(x1-x2); % the line slope
n = y1-m*x1; % the intercept
f_line = #(x) m.*x+n; % the line function
And if we plot it we can see the red line where the band for detection was:
Next, we can make this line thicker for a better representation of this line:
thick = max(sum(mA)); % mode thickness of the line
tmp = (1:thick)-ceil(thick/2); % helper vector for expanding
rows = bsxfun(#plus,tmp.',floor(f_line(1:size(A,2)))); % all the rows for each column
rows(rows<1) = 1; % make sure to not get out of range
rows(rows>size(A,1)) = size(A,1); % make sure to not get out of range
inds = sub2ind(size(A),rows,repmat(1:size(A,2),thick,1)); % convert to linear indecies
mA(inds) = true; % add the interpolation to the mask
result = figmat.*mA; % apply the mask on figmat
Finally, we can plot that result after masking, excluding the unwanted areas:
imagesc(result(any(result,2),:))

Histogram of an image but without considering the first k pixels

I would like to create a histogram of an image but without considering the first k pixels.
Eg: 50x70 image and k = 40, the histogram is calculated on the last 3460 pixels. The first 40 pixels of the image are ignored.
The order to scan the k pixels is a raster scan order (starting from the top left and proceeds by lines).
Another example is this, where k=3:
Obviously I can't assign a value to those k pixels otherwise the histogram would be incorrect.
Honestly I have no idea how to start.
How can I do that?
Thanks so much
The vectorized solution to your problem would be
function [trimmedHist]=histKtoEnd(image,k)
imageVec=reshape(image.',[],1); % Transform the image into a vector. Note that the image has to be transposed in order to achieve the correct order for your counting
imageWithoutKPixels=imageVec(k+1:end); % Create vector without first k pixels
trimmedHist=accumarray(imageWithoutKPixels,1); % Create the histogram using accumarray
If you got that function on your workingdirectory you can use
image=randi(4,4,4)
k=6;
trimmedHistogram=histKtoEnd(image,k)
to try it.
EDIT: If you just need the plot you can also use histogram(imageWithoutKPixels) in the 4th row of the function I wrote
One of the way can be this:
histogram = zeros(1,256);
skipcount = 0;
for i = 1:size(image,1)
for j = 1:size(image,2)
skipcount = skipcount + 1;
if (skipcount > 40)
histogram(1,image(i,j)+1) = histogram(1,image(i,j)+1) + 1;
end
end
end
If you need to skip some exact number of top lines, then you can skip the costly conditional check and just start the outer loop from appropriate index.
Vec = image(:).';
Vec = Vec(k+1:end);
Hist = zeros(1, 256);
for i=0:255
grayI = (Vec == i);
Hist(1, i+1) = sum(grayI(:));
end
First two lines drop the first k pixels so they are not considered in the computation.
Then you check how many 0's you have and save it in the array. The same for all gray levels.
In the hist vector, in the i-th cell you will have the number of occurance of gray level (i-1).

Image manipulation code in MATLAB (corner detection)

I'd like to know exactly how this line of code works
corners = (m==n)&(n>threshold);
It's in a piece of code I'm using and I want to understand it. Basically, m and n are both equal-sized images, and "threshold" is a decimal value.
To understand the context, a segment of the code is below.
% compute the m cornerness measure
m = (ix2s.*iy2s - ixys.^2) - 0.04*(ix2s+iy2s).^2;
% perform non-maximal suppression using ordfilt2
n = ordfilt2(m, radius^2, ones([radius radius]));
% display corner spots
corners = (m==n)&(n>threshold);
% superimpose corners
Q = corners+im;
Q(Q>1) = 1;
C = repmat(im,[1 1 3]);
C(:,:,1) = Q;
If I understand correctly, n is the max of m ("cornerness measure") for the vicinity, so the line means - "if m is the local maximum and large enough(larger than threshold), then this is probably a corner", it could have arguably been more readable as:
corners = (m==n)&(m>threshold);
You should read more about Harris corner detector. Taken from Wikipedia:
This line is implementation of the function mentioned above. It is used to detect corners.

Matlab: how to avoid ellipses overlapping in image?

I've been using a function file [ret]=drawellipse(x,y,a,b,angle,steps,color,img). Calling the function through a script file to draw random ellipses in image. But once i set the random center point(x,y), and random a, b, there is high possibility that the ellipses intersection would occur. How can i prevent the intersection? (I'm supposed to draw the ellipses that are all separate from each other)
Well, over here i have a function file which is to check whether the ellipses got overlap or not,overlap = overlap_ellipses(x0,y0,a0,b0,angle0,x1,y1,a1,b1,angle1). If the two ellipses are overlap, then the 'overlap=1', otherwise 'overlap=0'.
Based on all these, i tested in the command window:
x=rand(4,1)*400; % x and y are the random coodinates for the center of ellipses
y=rand(4,1)*400;
a=[50 69 30 60]; % major axis for a and b, i intend to use random also in the future
b=[20 40 10 40]; % minor axis
angle=[30 90 45 0]; % angle of ellipse
steps=10000;
color=[255 0 0]; % inputs for another function file to draw the ellipse
img=zeros(500,500,3);
The following i want to dispaly the ellipses if overlap==0, and 'if overlap==1', decrease the a and b, till there is no intersection. Lastly, to imshow the img.
for i=1:length(x)
img=drawellipse(x(i),y(i),a(i),b(i),angle(i),steps,color,img);
end
For me now, i have difficulty in coding the middle part. How can i use the if statement to get the value of overlap and how to make the index corresponding to the ellipse i need to draw.
i tested a bit like
for k=1:(length(x)-1)
overlap = overlap_ellipses(x(1),y(1),a(1),b(1),angle(1),x(1+k),y(1+k),a(1+k),b(1+k),angle(1+k))
end
it returns
overlap=0
overlap=0
overlap=1
it is not [0 0 1]. I can't figure it out, thus stuck in the process.
The final image shoule look like the picture in this voronoi diagram of ellipses.
(There is no intersection between any two ellipses)
Assuming you are drawing the ellipses into a raster graphics image, you could calculate the pixels you would have to draw for an ellipse, check whether these pixels in the image are still of the background color, and draw the ellipse only if the answer is yes, otherwise reject it (because something else, i.e. another ellipse, is in the way) and try other x,y,a and b.
Alternatively, you could split your image into rectangles (not neccessarily of equal size) and place one ellipse in each of those, picking x,y,a,b such that no ellipse exceeds its rectangle - then the ellipses cannot overlap either, but it depends on how much "randomness" your ellipse placing should have whether this suffices.
The mathematically rigorous way would be to store x,y,a,b of each drawn ellipse and for each new ellipse, do pairwise checks with each of those whether they have common points by solving a system of two quadratic equations. However, this might be a bit complicated, especially once the angle is not 0.
Edit in response to the added code: Instead of fixing all x's and y's before the loop, you can determine them inside the loop. Since you know how many ellipses you want, but not how many you have to sample, you need a while loop. The test loop you give may come in handy, but you need to compare all previous ellipses to the one created in the loop iteration, not the first one.
i=1;
while (i<=4) %# or length(a), or, more elegantly, some pre-defined max
x(i) = rand*400; y(i) = rand*400; %# or take x and y as givren and decrease a and b
%# now, check overlap for given center
overlap = false;
for k=1:(i-1)
overlap = overlap || overlap_ellipses(x(i),y(i),a(i),b(i),angle(i),x(k),y(k),a(k),b(k),angle(k))
end
if (~overlap)
img = drawellipse(x(i),y(i),a(i),b(i),angle(i),steps,color,img);
i = i+1; %# determine next ellipse
end %# else x(i) and y(i) will be overwritten in next while loop iteration
end
Of course, if a and b are fixed, it may happen that no ellipse fits the image dimensions if the already present ones are unfortunately placed, resulting in an infinite loop.
Regarding your plan of leaving the center fixed and decreasing the ellipse's size until it fits: where does your overlap_ellipses method come from? Maybe itcan be adapted to return a factor by which one ellipse needs to be shrinked to fit next to the other (and 1 if it fits already)?
The solution proposed by #arne.b (the first one) is a good way to rasterize non-overlapping ellipses.
Let me illustrate that idea with an example. I will be extending my previous answer:
%# color image
I = imread('pears.png');
sz = size(I);
%# parameters of ellipses
num = 7;
h = zeros(1,num);
clr = lines(num); %# color of each ellipse
x = rand(num,1) .* sz(2); %# center x-coords
y = rand(num,1) .* sz(1); %# center y-coords
a = rand(num,1) .* 200; %# major axis length
b = rand(num,1) .* 200; %# minor axis length
angle = rand(num,1) .* 360; %# angle of rotation
%# label image, used to hold rasterized ellipses
BW = zeros(sz(1),sz(2));
%# randomly place ellipses one-at-a-time, skip if overlaps previous ones
figure, imshow(I)
axis on, hold on
for i=1:num
%# ellipse we would like to draw directly on image matrix
[ex,ey] = calculateEllipse(x(i),y(i), a(i),b(i), angle(i), 100);
%# lets plot the ellipse (overlayed)
h(i) = plot(ex,ey, 'LineWidth',2, 'Color',clr(i,:));
%# create mask for image pixels inside the ellipse polygon
mask = poly2mask(ex,ey,sz(1),sz(2));
%# get the perimter of this mask
mask = bwperim(mask,8);
%# skip if there is an existing overlapping ellipse
if any( BW(mask)~=0 ), continue, end
%# use the mask to place the ellipse in the label image
BW(mask) = i;
end
hold off
legend(h, cellstr(num2str((1:num)','Line%d')), 'Location','BestOutside') %'
%# set pixels corresponding to ellipses using specified colors
clr = im2uint8(clr);
II = I;
for i=1:num
BW_ind = bsxfun(#plus, find(BW==i), prod(sz(1:2)).*(0:2));
II(BW_ind) = repmat(clr(i,:), [size(BW_ind,1) 1]);
end
figure, imshow(II, 'InitialMagnification',100, 'Border','tight')
Note how the overlap test is performed in the order the ellipses are added, thus after Line1 (blue) and Line2 (green) are drawn, Line3 (red) will be skipped because it overlaps one of the previous ones, and so on for the rest...
One option is to keep track of all the ellipses already drawn, and to make sure the next set of [x,y,a,b] does not produce a new ellipse which intersects with the existing ones. You can either invoke random numbers until you come up with a set that fulfills the condition, or once you have a set which violates the condition, decrease the values of a and/or b until no intersection occurs.

Resources