- Avoid global variables, because they impede the debugging massively. If a code grows (e.g. over 20'000 lines of code) you will hate it to started with globals, because it is nearly impossible to find out, which code is responsible for the current value of a variable.
- Do not use indices in the names of variables: "Image1", "Image2", ... Much neater: "Image{1}", "Image{2}", ... Then you can use an index to access an image. See your ListeImages, which is the nive solution already.
Is it possible to improve the performance of my script?
3 ビュー (過去 30 日間)
古いコメントを表示
i'm still very new to Matlab and probably go wrong about a lot of things. I needed to add a popupmenu to my figure, to let the students select different images for viewing. I used nested functions and some globals. I suspect I could have structured the code differently but it's doing what I need it to do without crashing or errors, which is a great way to 'start the day' -- ha! ha! I have attached a copy of my script.
The "problem" is a "flickering" of the figure window? When you execute the code, you'll see what I mean. I wonder whether there is a "better" way than deleting the existing figure every time a new picture is selected in the popupmenu? I'm aware axes need to be readrawn and the figure window itself need to be adapted to the new picture size but... I have a hunch that this could be done "better"?
Any suggestions is appreciated!
0 件のコメント
回答 (2 件)
Jan
2022 年 2 月 8 日
編集済み: Jan
2022 年 2 月 8 日
Some hints:
Now the actual problem:
Instead of closing the former figure and creating a new one, reuse the current figure and axes to avoid the flickering:
% Replace
fig = get(groot,'CurrentFigure');
if ~isempty(fig)
close(fig);
end
f = figure('color', 'w', 'MenuBar', 'none', 'Position', [500 500 800 600], 'Name', 'Roger');
set(f, 'Name', 'AfficheImage_2022_02_03.m');
ax1 = axes;
% by:
f = findobj(groot, 'Type', 'Figure', 'Name', 'AfficheImage_2022_02_03.m');
if isempty(fig)
f = figure('color', 'w', 'MenuBar', 'none', 'Position', [500 500 800 600], ...
'Name', 'AfficheImage_2022_02_03.m');
ax1 = axes('Parent', f);
else
ax1 = findobj(f.Children, 'flat', 'Type', 'axes');
end
Now do not recreate the image object with imshow to save time, but create the image once using image() and update the XData, YData and CData only.
The re-creation takes much longer than redefining the properties of existing objects.
3 件のコメント
Stephen23
2022 年 2 月 8 日
編集済み: Stephen23
2022 年 2 月 8 日
Call IMAGE just once and make sure that you obtain a handle to the image object:
imh = image(...)
And then after that do NOT call IMAGE again, simply update the CData, XData, and YData properties https://www.mathworks.com/help/matlab/ref/matlab.graphics.primitive.image-properties.html
or any others as required either using
SET(imh,'XData',...)
or the newer dot syntax:
imh.XData = ...
The documentation also explains how:
Image Analyst
2022 年 2 月 8 日
You can use squeeze to turn your 3-D array of colors into a 1-D vector:
RGB = squeeze(img(IntY,IntX, :))
Also I, like many others, find it convenient to use camelCase. So save yourself holding down the shift key and use intY for IntY.
I'd put in a lot more comments, like for instance:
% Convert the RGB values of the point the user clicked on into CIE LAB color values.
My code typically has about 37% comments when I run it through my comment counter utility (attached).
You might try impixel() instead of getting control points and then checking if they're inside the axes. impixel() gives you the pixel value directly and no checking of where it is is needed.
Personally I like using sprintf() rather than calling all to conversion functions, like instead of
Titre = 'Image RGB = ' + string(Hauteur) + ' x ' + string(Largeur) + ' pxels';
you can do
Titre = sprintf('Image RGB = %d rows by %d columns', Hauteur, Largeur);
but that's a style question and I'm used to that sprintf() since I originally learned it when I learned C.
I think it's simpler to use the more modern OOP way of assigning properties rather than the old set() way, so instead of
set(ax1, 'InnerPosition', [70 150 TailleImg(2) TailleImg(1)]);
use
ax1.InnerPosition = [70, 150, TailleImg(2), TailleImg(1)];
And notice I use commas between the vector values. MATLAB's code review should have also pointed that out.
You might want to clear out your global workspace before you start
clear global
I've had a problem in the past where I (unwittingly) was trying to use a global before I assigned it and got weird values because I didn't realize that I had been using a value from a prior run and had never actually assigned the value in the current run.
Finally you might try using AppDesigner to build your GUI. It does a lot of the grunt work for you so you don't have to clutter up your code with setting properties. It will still put that stuff in the code but it's grayed out and you can't edit it so you just learn to ignore the auto-generated, grayed out code and just work in the white background code that you are supposed to work in. So you can set up the way the GUI looks visually. However AppDesigner is still not perfect yet. I just reviewed it the the App Designer development team yesterday and I discovered a bug (impixelinfo may not work in app designer).
3 件のコメント
Image Analyst
2022 年 2 月 8 日
I use GUIDE for all my apps. It's a dialog box editor. It's not perfect but for me it's better than doing all the tedous gruntwork of setting up controls on my own with my own custom code. impixelinfo() does work with GUIDE.
参考
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!