surface feature detection on image processing - image

An example of detectSURFFeatures in comparison of 2 image is in below. I couldn't make detectSURFFeatures function work in my MATLAB. no help or doc detectSURFFeatures gives any clue. the error says " > UncalibratedSterio
Undefined function 'detectSURFFeatures' for input arguments of type 'uint8'." but the function itself can cover uint8 as i know. what should i do?
%Rectified Sterio Image Uncalibrated
% There is no calibration of cameras
I1 = rgb2gray(imread('right_me.jpg'));
I2 = rgb2gray(imread('left_me.jpg'));
Value = 2000.0;
blobs1 = detectSURFFeatures(I1, 'MetricThreshold', Value);
blobs2 = detectSURFFeatures(I2, 'MetricThreshold', Value);
figure;
imshow(I1);
hold on;
plot(selectStrongest(blobs1, 30));
title('Thirty strongest SURF features in I1');
figure;
imshow(I2);
hold on;
plot(selectStrongest(blobs2, 30));
title('Thirty strongest SURF features in I2');

You are getting that error because detectSURFFeatures does not exist in your MATLAB distribution. You must have at least R2011b, as that was when detectSURFFeatures was available: http://www.mathworks.com/help/vision/release-notes.html#R2011b
I suspect you have an older version of MATLAB than R2011b and so if you want to make it easy on yourself, you need to upgrade your version of MATLAB. However, if I may make a suggestion, I suggest the mexopencv project by Kota Yamaguchi: http://kyamagu.github.io/mexopencv/
He wrote OpenCV wrappers that can directly interface with MATLAB and so you can actually call OpenCV's SURF feature detection and matching methods from MATLAB but you will need to install OpenCV to do that. It will be a bit of work to get it working, but this is one solution I can provide if you don't want to upgrade your version of MATLAB.
Good luck!

Related

Parameters for dlib::find_min_bobyqa

I'm working on the C++ version of Matt Zucker's Page dewarping. So far everything works fine, but I have a problem with optimization. In line 748 of Github repo Matt uses optimize function from Scipy. My C++ equivalent is find_min_bobyqa from dlib.net. The code is:
auto f = [&](const column_vector& ppts) { return objective( dstpoints, ppts, keypoint_index); };
dlib::find_min_bobyqa(f,
params,
2 * params.nr() + 1, // npt - number of interpolation points: x.size() + 2 <= npt && npt <= (x.size()+1)*(x.size()+2)/2
dlib::uniform_matrix<double>(params.nr(), 1, -2), // lower bound constraint
dlib::uniform_matrix<double>(params.nr(), 1, 2), // upper bound constraint
1, // initial trust region radius
1e-5, // stopping trust region radius
4000 // max number of objective function evaluations
);
In my concrete example params is a dlib::column_vector with double values and length = 189. Every element of params is less than 2.0 and greater than -2.0. Function objective() returns double value and "alone" it works properly because I get the same value as in the Python version. But after running fin_min_bobyqa function I usually get the message:
Terminate called after throwing an instance of 'dlib:bobyqa_failure', return from BOBYQA because the objective function has been called max_f_evals times.
I set max_f_evals to quite big value to see if it optimizes at all, but it doesn't. I did some tweaking with parameters but without good results. How should I set the parameters of find_min_bobyqa to get the right solution?
I am very interested in this issue as well. Zucker's work, with very minor tweaks, is ideal for straightening sheet music images, and I was looking for ways to implement it in a mobile platform when I came across your question.
My research so far suggests that BOBYQA is not the equivalent of Powell's method in scipy. BOBYQA is constrained, and the one in scipy is not.
See these links for more information, and a possible way to compile the right supporting library - I would try UOBYQA or NEWUOA.
https://github.com/jacobwilliams/PowellOpt
https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html#rdd2e1855725e-3
(See the Notes section)
EDIT: see C version here:
https://github.com/emmt/Algorithms/tree/master/newuoa
I wanted to post this as a comment, but I don't have enough points for that.
I am very interested in your progress. If you're willing, please keep me posted.
I finally solved this problem. I used PRAXIS library, because it doesn't need derivative information and is fast.
I modified the code a little to my needs and now it is faster around few seconds than original version written in Python.

Save a figure to file with specific resolution

In an old version of my code, I used to do a hardcopy() with a given resolution, ie:
frame = hardcopy(figHandle, ['-d' renderer], ['-r' num2str(round(pixelsperinch))]);
For reference, hardcopy saves a figure window to file.
Then I would typically perform:
ZZ = rgb2gray(frame) < 255/2;
se = strel('disk',diskSize);
ZZ2 = imdilate(ZZ,se); %perform dilation.
Surface = bwarea(ZZ2); %get estimated surface (in pixels)
This worked until I switched to Matlab 2017, in which the hardcopy() function is deprecated and we are left with the print() function instead.
I am unable to extract the data from figure handler at a specific resolution using print. I've tried many things, including:
frame = print(figHandle, '-opengl', strcat('-r',num2str(round(pixelsperinch))));
But it doesn't work. How can I overcome this?
EDIT
I don't want to 'save' nor create a figure file, my aim is to extract the data from the figure in order to mesure a surface after a dilation process. I just want to keep this information and since 'im processing a LOT of different trajectories (total is approx. 1e7 trajectories), i don't want to save each file to disk (this is costly, time execution speaking). I'm running this code on a remote server (without a graphic card).
The issue I'm struggling with is: "One or more output arguments not assigned during call to "varargout"."
getframe() does not allow for setting a specific resolution (it uses current resolution instead as far as I know)
EDIT2
Ok, figured out how to do, you need to pass the '-RGBImage' argument like this:
frame = print(figHandle, ['-' renderer], ['-r' num2str(round(pixelsperinch))], '-RGBImage');
it also accept custom resolution and renderer as specified in the documentation.
I think you must specify formattype too (-dtiff in my case). I've tried this in Matlab 2016b with no problem:
print(figHandle,'-dtiff', '-opengl', '-r600', 'nameofmyfig');
EDIT:
If you need the CData just find the handle of the corresponding axes and get its CData
f = findobj('Tag','mytag')
Then depending on your matlab version use:
mycdata = get(f,'CData');
or directly
mycdta = f.CData;
EDIT 2:
You can set the tag of your image programatically and then do what I said previously:
a = imshow('peppers.png');
set(a,'Tag','mytag');

Creating animation with multiple plots in Octave

I'm using Octave to write a script that plots a function at different time periods. I was hoping to create an animation of the plots in order to see the changes through time.
Is there a way to save each plot for each time point, so that all plots can be combined to create this animation?
It's a bit of kludge, but you can do the following (works here with octave 4.0.0-rc2):
x = (-5:.1:5);
for p = 1:5
plot (x, x.^p)
print animation.pdf -append
endfor
im = imread ("animation.pdf", "Index", "all");
imwrite (im, "animation.gif", "DelayTime", .5)
Basically, print all your plots into a pdf, one per page. Then read the pdf's as images and print them back as gifs. This will not work on Matlab (its imread implementation can't handle pdf).
This creates an animated gif
data=rand(100,100,20); %100 by 100 and 20 frames
%data go from 0 to 1, so lets convert to 8 bit unsigned integers for saving
data=data*2^8;
data=uint8(data);
%Write the first frame to a file named animGif.gif
imwrite(data(:,:,1),'/tmp/animGif.gif','gif','writemode','overwrite',...
'LoopCount',inf,'DelayTime',0);
%Loop through and write the rest of the frames
for ii=2:size(data,3)
imwrite(data(:,:,ii),'/tmp/animGif.gif','gif','writemode','append','DelayTime',0)
end
Had to come chime in here because this was the top Google result for me when I was looking for help with this. I had issues with both answers, and some other issues, too. Notably:
For Rick T's answer, the code snippet doesn't write a plot figure, it just writes matrix data. Getting the plot window was a pain.
For carandraug's answer, writing to a PDF took a very long time and made a gigantic PDF.
On my own machine, I'm pretty sure I used apt-install to get Octave, but the getframe function I found referenced in other answers wasn't found. Turns out I had installed version 4.4, which was from 2018 (>3 years old).
I removed the old version of Octave sudo apt remove octave, then installed the new version with snap. If you try octave from a terminal without it installed it should prompt you to the snap install - be sure to include the # 6.4.0 or whatever is included in the command.
Once I had the current version installed, I got access to the getframe command, which is what lets you convert directly from a figure handle to image data - this bypasses the hackey (but previously necessary step) in #carandraug's answer where you had to write to PDF or some other image as a placeholder.
I used #RickT's answer to make my own MakeGif function, which I will share with you all here. Note that MakeGif stores the filename in a persistent variable, meaning it is retained across calls. If you change the filename it will make (or overwrite!!) the new file. If you need to overwrite the current file (i.e., running the same script multiple times and want new results) then you can use clear MakeGif between calls and that will reset the persistentFilename.
Here is the code for the MakeGif function; code to test it with is provided after this:
function MakeGif(figHandle, filename)
persistent persistentFilename = [];
if isempty(filename)
error('Can''t have an empty filename!');
endif
if ~ishandle(figHandle)
error('Call MakeGif(figHandle, filename); no valid figHandle was passed!');
endif
writeMode = 'Append';
if isempty(persistentFilename)|(filename!=persistentFilename)
persistentFilename = filename;
writeMode = 'Overwrite';
endif
imstruct = getframe(figHandle);
imwrite(imstruct.cdata, filename, 'gif', 'WriteMode',writeMode,'DelayTime',0);
endfunction
And here is the code to test the function. There's a commented-out call to clear MakeGif between the blue and green colors. If you leave it commented out it will append the green sine wave to the blue sine wave, resulting in alternating colors after every cycle - again the filename is persistent in the function. If you uncomment that call then the MakeGif function will treat the green's call as "new" and trigger the overwrite of the blue sine wave and all you'll see is green.
clear all;
time = 0:0.1:2*pi;
nSamples = numel(time);
figHandle = figure(1);
for i=1:nSamples
plot(time,sin(time + time(i)),'Color','blue');
drawnow;
MakeGif(figHandle, 'test.gif');
endfor
% Uncomment the 'clear' command below to clear the MakeGif persistent
% memory, which will trigger the green sine wave to overwrite the blue.
% Default behavior is to APPEND a green sine wave because the filename
% is the same.
%clear MakeGif;
for i=1:nSamples
plot(time,sin(time + time(i)),'Color','green');
drawnow;
MakeGif(figHandle, 'test.gif');
endfor
I spent several hours on this after being super dissatisfied with laggy screen captures so I really hope this helps someone in the future! Good luck and best wishes from the Age of Covid lol.
#Chuck thanks for that code; I've been using it to save 1500-frame GIFs of simulation output, and I find that after maybe ~500 frames the time to save the next frame to the output during the call to MakeGif starts to become ... unnerving. I guess imwrite reads and writes the entirety of the output file at each call that includes the 'WriteMode','Append' pair. At frame 1500 my output is 480Mb so that becomes untenable.
An apparent rescue for this is hinted at in the doc for Octave 7.1.0's imwrite, with the suggestion that you can pass it a 4-dimensional array and write the entire image sequence with one call. I haven't been able to make this work, though: Calling imwrite that way seems to simply write the very first image in the sequence into every frame in the output file.

Cannot use scatterplot in Octave

I was learning how to do machine learning on mldata.org and I was watching a video on Youtube on how to use the data (https://www.youtube.com/watch?v=zY0UhXPy8fM) (2:50). Using the same data, I tried to follow exactly what he did and create a scatterplot of the dataset. However when he used the scatterplot command, it worked perfectly on his side, but I cannot do it on myside.
Can anyone explain what's wrong and what I should do?
octave:2> load banana_data.octave
octave:3> pkg load communications
octave:4> whos
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
data 2x5300 84800 double
label 1x5300 42400 double
Total is 15900 elements using 127200 bytes
octave:5> scatterplot(data, label)
error: scatterplot: real X must be a vector or a 2-column matrix
error: called from:
error: /home/anthony/octave/communications-1.2.0/scatterplot.m at line 69, column 7
The error message says it all. Your data is a 2-row matrix, and not a 2-column matrix as it should be. Just transpose it with .'.
scatterplot(data.')
I dropped the label argument since it is not compatible with the communications toolbox, either in matlab or in octave.
Update:
According to news('communications'),
The plotting functions eyediagram' andscatterplot' have improved Matlab compatibility
This may be why the behaviour is different. Be ready to find other glitches, as the octave 3.2.4 used in this course is about 5 years old.
In order to use the label, you should rather use the standard octave scatter function.
Colors could be changed by choosing another colormap.
colormap(cool(256))
scatter(data(1,:), data(2,:), 6, label, "filled")

Is there histo function in MATLAB?

histo function in MATLAB, does anyone knows what it does? histo(image) what does this return?
I found in google but there I couldnt find any predefined function in MATLAB. Is there some new includes in Latest MATLAB. If anyone knows please explain what is happening below.
hist=histo(image);
pdf=hist/sum(hist);
t_new=round(sum(pdf.*[0:255]));
histo() is probably a user-defined function that counts image historgram. You can use built-in Matlab function hist() instead:
n = hist(image)
Read more:
http://en.wikipedia.org/wiki/Histogram
http://en.wikipedia.org/wiki/Histogram_equalization
The MATLAB command for calculating image histogram is imhist
It is used as
hist = imhist(image);

Resources