how to extract graph in a hand written word image - matlab

I have taken one hand written word image as input for my program, I want to resize that image into 100x100 after resizing am skeletonised that image and i divide that image into equal segments of 10x10 in that segment i want to find the center of mass for foreground pixels in each segments. in my program i am finding the center of mass for foreground pixel. in my algorithm which am trying to implement they told that use that center of mass as a node add it into resulting graph and add the Add edges based on edge extraction like Minimal Spanning
Tree (MST).my question is i know the center of mass of foreground pixels im my code values of x and y coordinates stored in CXX and CYY matrix using plot(CXX,CYY,'g*'); am plotting on image. but i do not know how to use that center of mass as a node add it into resulting graph and how to add edges using MST.
this is my output image:
I want to use that plotted points as a node to resulting graph, after adding that points as a node i want add the edges based on Minimum Spanning Tree. please help me to how can i add those plotted point as nodes to resulting graph and how can i add edges to those nodes using minimum spanning tree.
clc;
clear all;
close all;
X=imread('math1.jpg');
imfinfo('math1.jpg')
figure,imshow(X)
b = imresize(X,[100,100]);
si = size(b,1);
sj = size(b,2);
%figure;imshow(b);
% Binarization
th = graythresh(b);
I = im2bw(b,th);
% w = 5;
% h = 5;
% c=si/w;
% r=sj/h;
kl=bwmorph(~I,'thin',inf);
%figure,imshow(kl)
R(:,:)=kl(:,:);
%grid size
t1=5;
D=100;
I=1;
U1=t1;
J=1;
U2=t1;
E=1;
t2=D/t1;
%Z=1;
for i=1:t2
for j=1:t2
B(I:U1,J:U2)=R(I:U1,J:U2);
[x,y]=find(B==1);
CX=mean(x);
CY=mean(y);
CXXX(E)=CX;
CYYY(E)=CY;
CXX(i,j)=CX;
CYY(i,j)=CY;
T(I:U1,J:U2)=B(I:U1,J:U2);
J=J+t1;
U2=U2+t1;
E=E+1;
clear B x y
end
I=I+t1;
U1=U1+t1;
J=1;
U2=t1;
end
%plot and grid
figure,imshow(R)
hold on
M = size(R,1);
N = size(R,2);
a=t1;
b=t1;
for k = 1:a:M
x = [1 N];
y = [k k];
plot(x,y,'Color','white');
set(findobj('Tag','MyGrid'),'Visible','on')
end
for k = 1:b:N
x = [k k];
y = [1 M];
plot(x,y,'Color','white');
set(findobj('Tag','MyGrid'),'Visible','on')
end
plot(CYY,CXX,'c*')
this is my input image please try to run this code.
my input image
input image

Related

Plotting circles in a Hadamard matrix pattern

I want to plot circles in Hadamard matrix pattern of order 8,16, and 32. So far, I have a code for plotting 2D arrays of circles.
%Plotting an N by N arrays of circles
clc; clear;
n_circles = 8; % Define the number of circles to be plotted
R = 40; % Define the radius of the basic circle
Len=1024;
M=zeros(Len); % Create the hole mask
% Get the indices of the points inside the basic circle
M0 = zeros(2*R+1); % Initialize the basic mask
I = 1:(2*R+1); % Define the x and y coordinates of the basic mask
x = (I - R)-1;
y = (R - I)+1;
[X,Y] = meshgrid(x,y); % Create the mask
A = (X.^2 + Y.^2 <= R^2);
[xx,yy]=ind2sub(size(M0),find(A == true));
%plot
for ii=1:n_circles
for jj=1:n_circles
MidX=Len/2+(ii-n_circles/2-0.5)*(2*R);
MidY=Len/2+(jj-n_circles/2-0.5)*(2*R);
% [MidX MidY]
M(sub2ind(size(M),MidX+xx-R-1,MidY+yy-R-1))=1;
end
end
figure(1)
imshow(M)
I searched on how to plot a Hadamard matrix, and from the Mathworks documentation, the hadamard matrix function
H = hadamard(n)
returns the Hadamard matrix of order n. How do I incorporate this in my original code so that the final result will generate an image of circles plotted in a Hadamard pattern, where the value of 1 indicates a circle while -1 is null (absence of circle)?
Thanks,
add in th begining
H = hadamard(n_circles);
and inside the loops change to:
M(sub2ind(size(M),MidX+xx-R-1,MidY+yy-R-1))=H(ii,jj);

how to connect edges to nodes in a image using minimum spanning tree approach

I am doing my project on graph matching in hand written image, i want to represent a given word image in graph, am using the below algorithm
Algorithm:
input: Binary image B, Grid width w, Grid height h
Output: Graph g = (V, E) with nodes V and edges E
1: function Grid(B,w,h)
2: for i ← 1 to number of columns C = Width of B/w do
3: for j ← 1 to number of rows R = Height of B/h do
4: V = V ∪ {(xm, ym) | (xm, ym) is the centre of mass of segment sij}
5: for Each pair of nodes (u, v) ∈ V × V do
6: E = E ∪ (u, v) if associated segments are connected by NNA, MST, or DEL
7: return g
am already find the center of mass using this am plotting the points after plotting the points i do not know how to add the edges to using minimum spanning tree approch
this my code
clc;
clear all;
close all;
X=imread('i2.jpg');
imfinfo('i2.jpg')
figure,imshow(X)
b = imresize(X,[100,100]);
si = size(b,1);
sj = size(b,2);
figure;imshow(b);
% Binarization
th = graythresh(b);
I = im2bw(b,th);
w = 10;
h = 10;
c=si/w;
r=sj/h;
kl=bwmorph(~I,'thin',inf);
figure,imshow(kl)
R(:,:)=kl(:,:);
I=1;
U1=w;
J=1;
U2=h;
E=1;
for i=1:r
for j=1:c
B(I:U1,J:U2)=R(I:U1,J:U2);
[x,y]=find(B==1);
CX=mean(x);
CY=mean(y);
CXX(E)=CX
CYY(E)=CY
T(I:U1,J:U2)=B(I:U1,J:U2);
J=J+w;
U2=U2+h;
E=E+1;
clear B x y
end
I=I+w;
U1=U1+h;
J=1;
U2=h;
end
imshow(R)
hold on
hold on
plot(CYY,CXX,'.c')
hold off
% CXX(isnan(CXX)) = [];
% CYY(isnan(CYY)) = [];
r = imread('empty.jpg');
n = imresize(r,[100,100]);
figure,imshow(n);
hold on
hold on
plot(CYY,CXX,'.k')
hold off
input image
expected output
am plotting using the CXX and CYY values i do not know how to add the edges to plotted points using minimum spanning tree approach please give me some code it will help me to complete my project
Hard to tell from your question, but I'm assuming you want to represent a graph where all nodes are at coordinates [CXX,CYY] and the weight matrix is the distance between node i and node j
You can generate an adjacency matrix with pdist2()
A = pdist2([CXX,CYY],[CXX,CYY]);
Build a graph based A (note that this graph carries no information about original location, only distances)
G = graph(A,...);
Determine the MST for G
T = minspantree(G);
T.Edges will be a table of nodes i and k that are included in the MST, as well as their distance weight. You can use graph functions to visualize this, although it will only factor distance vectors, not original coordinate locations

How to find the area of an arbitrary shape contained within a circle using MATLAB

I have an arbitrary shape, of which the exterior boundary has been traced in MATLAB using bwboundaries. Using regionprops, I can calculate the total area enclosed by this shape.
However, I want to know the area for only the parts of the shape that fall within a circle of known radius R centered at coordinates [x1, y1]. What is the best way to accomplish this?
There are a few ways to approach this. One way you could alter the mask before performing bwboundaries (or regionprops) so that it only includes pixels which are within the given circle.
This example assumes that you already have a logical matrix M that you pass to bwboundaries.
function [A, boundaries] = traceWithinCircle(M, x1, y1, R);
%// Get pixel centers
[x,y] = meshgrid(1:size(M, 1), 1:size(M, 2));
%// Compute their distance from x1, y1
distances = sqrt(sum(bsxfun(#minus, [x(:), y(:)], [x1, y1]).^2, 2));
%// Determine which are inside of the circle with radius R
isInside = distances <= R;
%// Set the values outside of this circle in M to zero
%// This will ensure that they are not detected in bwboundaries
M(~isInside) = 0;
%// Now perform bwboundaries on things that are
%// inside the circle AND were 1 in M
boundaries = bwboundaries(M);
%// You can, however, get the area by simply counting the number of 1s in M
A = sum(M(:));
%// Of if you really want to use regionprops on M
%// props = regionprops(M);
%// otherArea = sum([props.Area]);
end
And as an example
%// Load some example data
data = load('mri');
M = data.D(:,:,12) > 60;
%// Trace the boundaries using the method described above
B = traceWithinCircle(M, 70, 90, 50);
%// Display the results
figure;
hax = axes();
him = imagesc(M, 'Parent', hax);
hold(hax, 'on');
colormap gray
axis(hax, 'image');
%// Plot the reference circle
t = linspace(0, 2*pi, 100);
plot(x1 + cos(t)*R, y1 + sin(t)*R);
%// Plot the segmented boundaries
B = bwboundaries(M);
for k = 1:numel(B)
plot(B{k}(:,2), B{k}(:,1), 'r');
end

Convert Matlab code into Simulink

I would like to convert a image processing program(part of the program below) from Matlab to Simulink and possibly convert the simulink diagram into C code later on. I have 0 experience in Simulink and was wondering if there's any limitations on the types of matlab program/functions that can be converted and how I would go about doing this. Thanks.
clear all
clc
% Read in an image 1
C1 = imread('cloud1.jpg');
Cloud1 = C1(:,:,1); % use only one color
%Cloud1 = Cloud1'; % transpose to get (x,y) instead of (y,x)
Cloud1_xsize = size(Cloud1,2); % get x size of image
Cloud1_ysize = size(Cloud1,1); % get y size of image
%figure(3), imshow(Cloud1) % to plot you need to transpose back to their coordinate system
%hold on
% Read in an image 2
C2 = imread('cloud2.jpg');
Cloud2 = C2(:,:,1); % use only one color
%Cloud2 = Cloud2'; % transpose to get (x,y) instead of (y,x)
Cloud2_xsize = size(Cloud2,2); % get x size of image
Cloud2_ysize = size(Cloud2,1); % get y size of image
%figure(2), imshow(Cloud2)
%hold on
% show the shift in the initial images several times
num = 0;
for k = 1:4
num=num+1;
pause(.5)
figure(1), h1=imshow(C1)
xlabel('FIGURE 1')
F(num) = getframe(gcf);
%image(F.cdata)
%colormap(F.colormap)
pause(0.25)
figure(1), h2=imshow(C2)
xlabel('FIGURE 2')
num=num+1;
F(num) = getframe(gcf);
%image(F.cdata)
%colormap(F.colormap)
end
% Play the movie twenty times
%movie(F,20)
%%%% Set the template size %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% First calc the number of pixels in the shortest direction of the image (usually y direction)
MinSize = min(Cloud1_xsize, Cloud1_ysize); % number of pixels in shortest direction
%%% N is the minimum number of boxes in the shorter direction (usually y direction).
%%% In the shorter axis (usually y)there will be N-2 boxes analyzed.
%%% This is because the top and bottom boxes are considered too close to the edge to use.
%%% In the larger direction (usually x) there may be more boxes.
N = 6;
EdgeBoxSize = 1; % the number of edge boxes along each edge
TempWidth = floor(MinSize / N); % the pixel width of each template box
TempHeight = TempWidth; % make the template height and width the same size so corr part works good
%%% Now calculate the exact number of boxes in x and y directions
%%% This depends on the number of x versus y pixels.
Nx = floor(Cloud1_xsize/TempWidth);
Ny = floor(Cloud1_ysize/TempWidth);

How can i render lineseries/contour/etc objects to array of pixel data?

I have an array of pixel data frames for use with VideoWriter. I want to overlay lineseries/contour objects into each frame. I don't want to make the movie by iteratively drawing each frame to a figure and capturing it with getframe, because that gives poor resolution and is slow. I tried using getframe on a plot of just the contour, but that returns images scaled to the wrong size with weird margins, especially when using 'axis equal,' which I need.
Updated to accommodate feedback from OP
Getting the contour data as pixel data is not trivial (if possible at all) since using getframe doesn't yield predictable results
What we can do is to extract the contour data and then overlay it on the pixel data frames, forcing them to be to the same scale and then do a getframe on the resultant merged image. This will at least ensure that they two data sets area aligned.
The following code shows the principle though you'd need to modify it for your own needs:
%% Generate some random contours to use
x = linspace(-2*pi,2*pi);
y = linspace(0,4*pi);
[X,Y] = meshgrid(x,y);
Z = sin(X)+cos(Y);
[~,h] = contour(X,Y,Z);
This yields the following contours
Now we get the handles of the children of this image. These will all be 'patch' type objects
patches = get(h,'Children');
Also get the axis limits for the contours
lims = axis;
Next, create a new figure and render the pixel frame data into it
In this example I'm just loading an image but you get the idea.
%% Render frame data
figure
i = imread( some_image_file_png );
This image is actually 194 x 259 x 3. I can display it and rescale the X and Y axes using
%% Set image axes
image(flipdim(i,1),'XData',[lims(1) lims(2)],'YData',[lims(4) lims(3)]);
Note the use of flipdim() to vertically flip the image since the image Y-axis runs in the opposite sense to the contour Y axis. This gives me:
Now I can plot the contours (patches) form the contour plot over the top of the image in the same coordinate space
%% Plot patches
for p =1:length(patches)
xd = get( patches(p), 'XData' );
yd = get( patches(p), 'YData' );
% This causes all contours to be rendered in white. You may
% want to play with this a little
cd = zeros(size(xd));
patch( xd, yd, cd, 'EdgeColor', 'w');
end
This yields
You can now use getframe to extract the frame. If it's important to have coloured contours, you will need to extract colour data from the original contour map and use it to apply an appropriate colouring in the overlaid image.
As a short cut, it's also possible to compile all patch data into a single MxN matrix and render with a single call to patch but I wrote it this way to demonstrate the process.
Well, here's a Bresenham-esque solution based on the ContourMatrix. Not ideal cuz doesn't handle line width, antialiasing, or any more than a single color. But it's pretty efficient (not quite Bham efficient).
function renderContour
clc
close all
x = randn(100,70);
[c,h] = contour(x,[0 0],'LineColor','r');
axis equal
if ~isnumeric(h.LineColor)
error('not handled')
end
cs = nan(size(c,2),4);
k = 0;
ci = 1;
for i = 1:size(c,2)
if k <= 0
k = c(2,i);
else
if k > 1
cs(ci,:) = reshape(c(:,i+[0 1]),[1 4]);
ci = ci + 1;
end
k = k - 1;
end
end
pix = renderLines(cs(1:ci-1,:),[1 1;fliplr(size(x))],10,h.LineColor);
figure
image(pix)
axis equal
end
function out = renderLines(cs,rect,res,color)
% cs = [x1(:) y1(:) x2(:) y2(:)]
% rect = [x(1) y(1);x(2) y(2)]
% doesnt handle line width, antialiasing, etc
% could do those with imdilate, imfilter, etc.
test = false;
if test
if false
cs = [0 0 5 5; 0 5 2.5 2.5];
rect = [0 0; 10 10];
else
cs = 100 * randn(1000,4);
rect = 200 * randn(2);
end
res = 10;
color = [1 .5 0];
end
out = nan(abs(res * round(diff(fliplr(rect)))));
cs = cs - repmat(min(rect),[size(cs,1) 2]);
d = [cs(:,1) - cs(:,3) cs(:,2) - cs(:,4)];
lens = sqrt(sum(d.^2,2));
for i = 1:size(cs,1)
n = ceil(sqrt(2) * res * lens(i));
if false % equivalent but probably less efficient
pts = linspace(0,1,n);
pts = round(res * (repmat(cs(i,1:2),[length(pts) 1]) - pts' * d(i,:)));
else
pts = round(res * [linspace(cs(i,1),cs(i,3),n);linspace(cs(i,2),cs(i,4),n)]');
end
pts = pts(all(pts > 0 & pts <= repmat(fliplr(size(out)),[size(pts,1) 1]),2),:);
out(sub2ind(size(out),pts(:,2),pts(:,1))) = 1;
end
out = repmat(flipud(out),[1 1 3]) .* repmat(permute(color,[3 1 2]),size(out));
if test
image(out)
axis equal
end
end