I am experiencing an error in Matlab.
Maximum recursion limit of 500 reached. Use set(0,'RecursionLimit',N) to change the limit.
Be aware that exceeding your available stack space can crash MATLAB and/or your computer.
The algorithm I am using is the one downloaded from:
http://www.mathworks.com/matlabcentral/fileexchange/19084-region-growing
Here is the code:
function J=regiongrowing(I,x,y,reg_maxdist)
% This function performs "region growing" in an image from a specified
% seedpoint (x,y)
%
% J = regiongrowing(I,x,y,t)
%
% I : input image
% J : logical output image of region
% x,y : the position of the seedpoint (if not given uses function getpts)
% t : maximum intensity distance (defaults to 0.2)
%
% The region is iteratively grown by comparing all unallocated neighbouring pixels to the region.
% The difference between a pixel's intensity value and the region's mean,
% is used as a measure of similarity. The pixel with the smallest difference
% measured this way is allocated to the respective region.
% This process stops when the intensity difference between region mean and
% new pixel become larger than a certain threshold (t)
%
%
% Author: D. Kroon, University of Twente
I = im2double(imread('ship.jpg'));
x=150; y=150;
J = regiongrowing(I,x,y,0.2);
figure, imshow(I+J);
if(exist('reg_maxdist','var')==0), reg_maxdist=0.2; end
if(exist('y','var')==0), figure, imshow(I,[]); [y,x]=getpts; y=round(y(1)); x=round(x(1)); end
J = zeros(size(I)); % Output
Isizes = size(I); % Dimensions of input image
reg_mean = I(x,y); % The mean of the segmented region
reg_size = 1; % Number of pixels in region
% Free memory to store neighbours of the (segmented) region
neg_free = 10000; neg_pos=0;
neg_list = zeros(neg_free,3);
pixdist=0; % Distance of the region newest pixel to the regio mean
% Neighbour locations (footprint)
neigb=[-1 0; 1 0; 0 -1;0 1];
% Start regiongrowing until distance between region and possible new pixels become
% higher than a certain threshold
while(pixdist<reg_maxdist&®_size<numel(I))
% Add new neighbours pixels
for j=1:4,
% Calculate the neighbour coordinate
xn = x +neigb(j,1); yn = y +neigb(j,2);
% Check if neighbour is inside or outside the image
ins=(xn>=1)&&(yn>=1)&&(xn<=Isizes(1))&&(yn<=Isizes(2));
% Add neighbour if inside and not already part of the segmented area
if(ins&&(J(xn,yn)==0))
neg_pos = neg_pos+1;
neg_list(neg_pos,:) = [xn yn I(xn,yn)]; J(xn,yn)=1;
end
end
% Add a new block of free memory
if(neg_pos+10>neg_free), neg_free=neg_free+10000; neg_list((neg_pos+1):neg_free,:)=0; end
% Add pixel with intensity nearest to the mean of the region, to the region
dist = abs(neg_list(1:neg_pos,3)-reg_mean);
[pixdist, index] = min(dist);
J(x,y)=2; reg_size=reg_size+1;
% Calculate the new mean of the region
reg_mean= (reg_mean*reg_size + neg_list(index,3))/(reg_size+1);
% Save the x and y coordinates of the pixel (for the neighbour add proccess)
x = neg_list(index,1); y = neg_list(index,2);
% Remove the pixel from the neighbour (check) list
neg_list(index,:)=neg_list(neg_pos,:); neg_pos=neg_pos-1;
end
% Return the segmented area as logical matrix
J=J>1;
I have attempted to change the value as suggested by set(0,'RecursionLimit',N) but this just crashes Matlab if it goes over 1000.
The error message makes sense since you've added the following lines to the function
I = im2double(imread('ship.jpg'));
x=150; y=150;
J = regiongrowing(I,x,y,0.2);
figure, imshow(I+J);
and so it will call itself (recurse) repeatedly. These four lines need to be removed from regiongrowing and should only be used from the Command Line (or another script/function).
Related
In order to avoid oversegmentation by the watershed algorithm in Matlab, I would like to force the algorithm to segment into a specific number of segments (in the example here, the algorithm segments automatically into 4, and I would like it to segment into 2). Is there a general way to define the allowed number of output segments?
The code that I am currently using:
% Load the image
grayscaleImg = imread('https://i.stack.imgur.com/KyatF.png');
white_in_current_bits = 65535;
% Display the original image
figure;
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
hold on;
imshow(grayscaleImg);
title('The origianl image');
% Binarize the image.
binaryImageElement = grayscaleImg < white_in_current_bits;
% Calculate the distance transform
D = -bwdist(~binaryImageElement);
% Find the regional minima of the distance matrix:
mask = imextendedmin(D,2);
%Display the mask on top of the binary image:
figure;
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
imshowpair(binaryImageElement,mask,'blend');
title('Blend of binary image and the regional minima mask');
%Impose the regional minima on the distance transform:
D2 = imimposemin(D,mask);
%Watershed the distance transform after imposing the regional minima:
Ld2 = watershed(D2);
%Display the binary image with the watershed segmentation lines:
bw3 = binaryImageElement;
bw3(Ld2 == 0) = 0;
figure;
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
imshow(bw3);
title('Binary image after watershedding');
There is no direct way to specify the number of regions that the watershed will produce. The watershed will always produce one region per local minimum. But you can modify the image to reduce the number of local minima. One approach is the H-minima transform. This function removes all local minima that are less deep than a threshold.
The idea would be to iterate (this might not be fast...) over thresholds until you get the desired number of regions.
% iterate over h, starting at 0
tmp = imhmin(D2,h);
Ld2 = watershed(tmp);
% count regions in Ld2, increase h and repeat
I just noticed that you impose minima in D2. You determine these minima using imextendedmin. This means you apply the H minima, find the resulting local minima, then impose those again. You might as well skip this step, and directly apply the H minima transform.
So, as a part of an experiment I need a function that could use the projector to project something on the floor. The projector is angled so the Keystone effect comes in to play and I'd like to correct it.
I try to do that by calculating the homography matrix H. I project a square at the bottom of the projected area, measure its properties (it is shown as a trapezoid on the ground) and calculate the matrix. And then I reverse the process with the idea to use the homography matrix H (it's inverse) to calculate and project a shape on the ground that would look like the original square and not a trapezoid.
But I'm not successful. I calculate a shorter quadrangle and still get a trapeze on the ground. I'm pretty sure I'm doing something wrong with the calculations but I'm not sure. I am new to Matlab :) Thx for the help. The code, with a lot of comments, is bellow.
function keystoning()
projArea = 100; % 100%
testSquare = 20; % test square dimension
%% Drawing a "what's supposed to be a square" on the floor
% black background, red "sqare" dimensions 20x20, attached to the base
% of the projection area so the base dimension of the "sqare" don't change
% and minimal measuring is required
testX=[40 40+testSquare 40+testSquare 40];
testY=[0 0 testSquare testSquare];
scrsz = get(groot,'screensize');
f = figure('position',[0 0 scrsz(3) scrsz(4)],...
'OuterPosition',[0 0 scrsz(3) scrsz(4)],...
'toolbar','none','menubar','none','name','none',...
'units','normalized',...
'Color','black','Resize','Off'...
);
figure(f); % focus window
fill(testX, testY,'r');
axis ([0 projArea 0 projArea])
pbaspect([1 1 1])
drawnow
disp('*** PLACE THE NEAR PART OF THE ELEMENT AT THE END OF THE TREADMILL ***');
%% Measuring of the shape in order to calculate the homography matrix H
disp('*** Measure the width of the base of the projection area in centimeters. ***');
prompt = 'Enter the measured distance: ';
projAreaM = input(prompt);
projAreaCoef=projAreaM/projArea; % coefficient between the axes scale and the projection area
disp('*** Measure the distance between the paralel lines of the trapezoid in centimeters. ***');
prompt = 'Enter the measured distance: ';
trapYm = input(prompt)/projAreaCoef
disp('*** Measure the length of the longer paralel line of the trapezoid in centimeters. ***');
prompt = 'Enter the measured length: ';
trapXm = input(prompt)/projAreaCoef
%% Calculating the homography matrix H
% trapezoid definition
% coordinates of the first two points for the trapezoid and the square
% are the same since its at the start of the projection area
difX=(trapXm-testSquare)/2; % length of the "pertrusions"
trapX=[testX(1) testX(2) testX(3)+difX testX(4)-difX];
trapY=[testY(1) testY(2) trapYm trapYm];
% variable definition
P=[testX;testY;ones(size(testX))]; % test rectangle
Q=[trapX;trapY;ones(size(trapX))]; % shown trapezoid
% homography matrix H calculation
H=Q/P; % solution to the equation HP = Q
%% Testing the homography matrix H
% we want to show the rectangle on the ground
Pnew=inv(H)*P;
fill(Pnew(1,:),Pnew(2,:),'r');
axis ([0 projArea 0 projArea])
pbaspect([1 1 1])
drawnow
I have a paired matrix with pixels equal 0 or 255 and when it's 255 it makes disk shape.
I would like to labelize the differents disks and get in a tab for each label : their radius and their central point. How can I do for this last two points?
Below an exemple with a small matrix
Mat=zeros(12,12);
Mat(2,6:7)=255; Mat(3,5)=255; Mat(3,8)=255; Mat(4,5)=255
Mat(4,8)=255; Mat(5,6:7)=255;
Mat(10,10)=255; Mat(11,9)=255; Mat(12,10)=255; Mat(11,11)=255;
CC=bwconncomp(Mat,8);
MatL=labelmatrix(CC);
figure, imagesc(Mat)
you can use regionprops to compute centroid and area, and then use area to compute approximate radius:
% generate matrix
Mat=zeros(12,12);
Mat(2,6:7)=255; Mat(3,5)=255; Mat(3,8)=255; Mat(4,5)=255;
Mat(4,8)=255; Mat(5,6:7)=255;
Mat(10,10)=255; Mat(11,9)=255; Mat(12,10)=255; Mat(11,11)=255;
% convert to binary
MatBin = Mat > 0;
% fill circles
MatFull = imfill(MatBin,4,'holes');
% get centroids and areas
props = regionprops(MatFull,{'Area','Centroid'});
Area = [props(:).Area];
Centroid = reshape([props(:).Centroid],[],2)';
% compute radius
Radius = sqrt(Area ./ pi);
% plotting
imshow(MatFull,[],'InitialMagnification','fit')
hold on
for ii = 1:numel(Radius)
text(Centroid(ii,1),Centroid(ii,2),['r = ' num2str(Radius(ii))],...
'VerticalAlignment','middle','HorizontalAlignment',...
'center','FontSize',12,'Color','b');
end
hold off
I am using MATLAB R2015a. I have defined a grid which is basically a matrix that stores the latitudes of the grid points in the first column and the longitudes of the grid points in the second column I have some data for energy of an earthquake for a region stored in a column vector where each element corresponds to the energy at the corresponding grid point. I have done a surface plot using this code (here e_lat and e_long are the first and second columns of the grid matrix respectively):-
function [b] = cumulative_plot( beam, e_lat,e_long, t_start, t_end)
%CUMULATIVE_PLOT Plots the cumulative energy of the earthquake
%% Input Arguments
% *beam* - Energy for each time increment (columns) for each grid point (rows)
%
% *e_lat* - Vector containing Latitudes of the grid points
%
% *e_long* - Vector containing Longitudes of the grid points
%
% *t_start* - starting time
%
% *t_end* - ending time
%
% *t_start* and *t_end* define the time window within which the energy is
% to be considered
%% Code
b = [];
b = sum(beam(:,t_start:t_end)')'; % Adding the energy within the time window
b = b./max(b); % Normalising
fn = 'cumulative_energy.txt';
f = fopen(fn,'w');
for i=1:length(e_lat)
fprintf(f,'%f %f %f \n',e_long(i),e_lat(i),b(i));
end
fclose(f);
energy_surf = fit([e_long,e_lat],b, 'loess');
plot(energy_surf,'style','contour');
hold on;
plot3(73.6400 ,34.5239 ,20,'s','MarkerSize',20,'MarkerEdgeColor','k','MarkerFaceColor','k')
hold on;
plot3(94.709,23.03,20,'s','MarkerSize',20,'MarkerEdgeColor','b','MarkerFaceColor','b')
shading interp
alpha(1)
view(0,90)
box off
colorbar
title(['Cumu Energy(0.05 - 0.2 Hz) at seconds = ' num2str(t_start )],'FontWeight','bold','FontSize',15,'FontName','Times');
xlabel('Long/degree','FontWeight','bold','FontSize',13,'FontName','Times');
ylabel('Lat/degree','FontWeight','bold','FontSize',13,'FontName','Times');
end
This is an example (the actual data that I am processing):-
cumulative_plot(b_corr,e_lat,e_long,1,20);
I want to make a contour plot of this energy data on a geographic map of the region specified. Is this possible?
To give a better idea, this is what I have right now :-
And this is kind of what I want to achieve (without the purple circular markers and other things. Just the base energy) :-
If you have the bmp image of the mountain details, save the data in RGB format, and mix it with the data of the cumulative energy scale by its intensity. Intensity provide the alpha blending value.
I am using DemoDrift2 from Psychtool box to create a moving grating. The grating moves perfectly and works great. However, i need to use it with some other devices connected and working with other softwares. In these situations the grating is displayed slower and jiggles. How can i pre-render the frames before the grating is displayed?
function DriftDemo2(angle, cyclespersecond, f, drawmask, gratingsize)
% function DriftDemo2([angle=30][, cyclespersecond=1][, f=0.05][, drawmask=1],[gratingsize=400])
if nargin < 5
gratingsize = [];
end
if isempty(gratingsize)
% By default the visible grating is 400 pixels by 400 pixels in size:
gratingsize = 400;
end
if nargin < 4
drawmask = [];
end
if isempty(drawmask)
% By default, we mask the grating by a gaussian transparency mask:
drawmask=1;
end;
if nargin < 3
f = [];
end
if isempty(f)
% Grating cycles/pixel: By default 0.05 cycles per pixel.
f=0.05;
end;
if nargin < 2
cyclespersecond = [];
end
if isempty(cyclespersecond)
% Speed of grating in cycles per second: 1 cycle per second by default.
cyclespersecond=1;
end;
if nargin < 1
angle = [];
end
if isempty(angle)
% Angle of the grating: We default to 30 degrees.
angle=30;
end;
movieDurationSecs=20; % Abort demo after 20 seconds.
% Define Half-Size of the grating image.
texsize=gratingsize / 2;
% Screen('Preference', 'SkipSyncTests', 1);
try
% This script calls Psychtoolbox commands available only in OpenGL-based
% versions of the Psychtoolbox.
AssertOpenGL;
% Get the list of screens and choose the one with the highest screen number.
screens=Screen('Screens');
screenNumber=max(screens);
% Find the color values which correspond to white and black:
% functions WhiteIndex and BlackIndex:
white=WhiteIndex(screenNumber);
black=BlackIndex(screenNumber);
% Round gray to integral number, to avoid roundoff artifacts with some
% graphics cards:
gray=round((white+black)/2);
% This makes sure that on floating point framebuffers we still get a
% well defined gray:
if gray == white
gray=white / 2;
end
% Contrast 'inc'rement range for given white and gray values:
inc=white-gray;
% Open a double buffered fullscreen window and set default background
% color to gray:
[w screenRect]=Screen('OpenWindow',screenNumber, gray);
if drawmask
% Enable alpha blending for proper combination of the gaussian aperture
% with the drifting sine grating:
Screen('BlendFunction', w, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
end
% Calculate parameters of the grating:
p=ceil(1/f);
% frequency in radians:
fr=f*2*pi;
% This is the visible size of the grating. It is twice the half-width
% of the texture plus one pixel to make sure it has an odd number of
% pixels and is therefore symmetric around the center of the texture:
visiblesize=2*texsize+1;
% Create one single static grating image:
%
% We only need a texture with a single row of pixels(i.e. 1 pixel in height) to
% define the whole grating! If the 'srcRect' in the 'Drawtexture' call
% below is "higher" than that (i.e. visibleSize >> 1), the GPU will
% automatically replicate pixel rows. This 1 pixel height saves memory
% and memory bandwith, ie. it is potentially faster on some GPUs.
%
% However it does need 2 * texsize + p columns, i.e. the visible size
% of the grating extended by the length of 1 period (repetition) of the
% sine-wave in pixels 'p':
x = meshgrid(-texsize:texsize + p, 1);
% Compute actual cosine grating:
grating=gray + inc*cos(fr*x);
% Store 1-D single row grating in texture:
gratingtex=Screen('MakeTexture', w, grating);
% Create a single gaussian transparency mask and store it to a texture:
% The mask must have the same size as the visible size of the grating
% to fully cover it. Here we must define it in 2 dimensions and can't
% get easily away with one single row of pixels.
%
% We create a two-layer texture: One unused luminance channel which we
% just fill with the same color as the background color of the screen
% 'gray'. The transparency (aka alpha) channel is filled with a
% gaussian (exp()) aperture mask:
mask=ones(2*texsize+1, 2*texsize+1, 2) * gray;
[x,y]=meshgrid(-1*texsize:1*texsize,-1*texsize:1*texsize);
mask(:, :, 2)=white * (1 - exp(-((x/90).^2)-((y/90).^2)));
masktex=Screen('MakeTexture', w, mask);
% Query maximum useable priorityLevel on this system:
priorityLevel=MaxPriority(w); %#ok<NASGU>
% We don't use Priority() in order to not accidentally overload older
% machines that can't handle a redraw every 40 ms. If your machine is
% fast enough, uncomment this to get more accurate timing.
%Priority(priorityLevel);
% Definition of the drawn rectangle on the screen:
% Compute it to be the visible size of the grating, centered on the
% screen:
dstRect=[0 0 visiblesize visiblesize];
dstRect=CenterRect(dstRect, screenRect);
% Query duration of one monitor refresh interval:
ifi=Screen('GetFlipInterval', w);
% Translate that into the amount of seconds to wait between screen
% redraws/updates:
% waitframes = 1 means: Redraw every monitor refresh. If your GPU is
% not fast enough to do this, you can increment this to only redraw
% every n'th refresh. All animation paramters will adapt to still
% provide the proper grating. However, if you have a fine grating
% drifting at a high speed, the refresh rate must exceed that
% "effective" grating speed to avoid aliasing artifacts in time, i.e.,
% to make sure to satisfy the constraints of the sampling theorem
% (See Wikipedia: "Nyquist?Shannon sampling theorem" for a starter, if
% you don't know what this means):
waitframes = 1;
% Translate frames into seconds for screen update interval:
waitduration = waitframes * ifi;
% Recompute p, this time without the ceil() operation from above.
% Otherwise we will get wrong drift speed due to rounding errors!
p=1/f; % pixels/cycle
% Translate requested speed of the grating (in cycles per second) into
% a shift value in "pixels per frame", for given waitduration: This is
% the amount of pixels to shift our srcRect "aperture" in horizontal
% directionat each redraw:
shiftperframe= cyclespersecond * p * waitduration;
% Perform initial Flip to sync us to the VBL and for getting an initial
% VBL-Timestamp as timing baseline for our redraw loop:
vbl=Screen('Flip', w);
% We run at most 'movieDurationSecs' seconds if user doesn't abort via keypress.
vblendtime = vbl + movieDurationSecs;
i=0;
% Animationloop:
while(vbl < vblendtime)
% Shift the grating by "shiftperframe" pixels per frame:
% the mod'ulo operation makes sure that our "aperture" will snap
% back to the beginning of the grating, once the border is reached.
% Fractional values of 'xoffset' are fine here. The GPU will
% perform proper interpolation of color values in the grating
% texture image to draw a grating that corresponds as closely as
% technical possible to that fractional 'xoffset'. GPU's use
% bilinear interpolation whose accuracy depends on the GPU at hand.
% Consumer ATI hardware usually resolves 1/64 of a pixel, whereas
% consumer NVidia hardware usually resolves 1/256 of a pixel. You
% can run the script "DriftTexturePrecisionTest" to test your
% hardware...
xoffset = mod(i*shiftperframe,p);
i=i+1;
% Define shifted srcRect that cuts out the properly shifted rectangular
% area from the texture: We cut out the range 0 to visiblesize in
% the vertical direction although the texture is only 1 pixel in
% height! This works because the hardware will automatically
% replicate pixels in one dimension if we exceed the real borders
% of the stored texture. This allows us to save storage space here,
% as our 2-D grating is essentially only defined in 1-D:
srcRect=[xoffset 0 xoffset + visiblesize visiblesize];
% Draw grating texture, rotated by "angle":
Screen('DrawTexture', w, gratingtex, srcRect, dstRect, angle);
if drawmask==1
% Draw gaussian mask over grating:
Screen('DrawTexture', w, masktex, [0 0 visiblesize visiblesize], dstRect, angle);
end;
% Flip 'waitframes' monitor refresh intervals after last redraw.
% Providing this 'when' timestamp allows for optimal timing
% precision in stimulus onset, a stable animation framerate and at
% the same time allows the built-in "skipped frames" detector to
% work optimally and report skipped frames due to hardware
% overload:
vbl = Screen('Flip', w, vbl + (waitframes - 0.5) * ifi);
% Abort demo if any key is pressed:
if KbCheck
break;
end;
end;
% Restore normal priority scheduling in case something else was set
% before:
Priority(0);
%The same commands wich close onscreen and offscreen windows also close
%textures.
Screen('CloseAll');
catch
%this "catch" section executes in case of an error in the "try" section
%above. Importantly, it closes the onscreen window if its open.
Screen('CloseAll');
Priority(0);
psychrethrow(psychlasterror);
end %try..catch..enter code here
Any help is appreciated!
Pre-rendering is done by calling owpnt = Screen('OpenOffscreenWindow',...) and then issuing your regular drawing commands, but passing owpnt as the destination. These are then written to a texture, which you can display with Screen('DrawTexture').
You'd need one offscreen window per frame. This will quickly exhaust your video card's memory. So:
Make sure to keep the dimensions of the offscreen window as small as possible: make it just fit your grating
Screen('Close') unneeded offscreen windows asap