多个可拖动的矩形matlab:额外的矩形

时间:2015-09-07 10:30:38

标签: matlab

我正在编写一个代码来获取用户输入的多个可拖动矩形的位置。代码工作得很好。然而,按下按钮后,代码不会向前移动,直到您再绘制一个矩形。我认为问题是pos = uint32(wait(h));语句无限期地等待另一个位置,并且只有在绘制另一个矩形后才会考虑按钮句柄。我确实需要wait (h)声明,getposition功能对我来说效果不佳。我非常感谢您提供的任何帮助,以下是我的代码的一部分。

代码:

im_des=rgb2gray('image_name.jpg');
ButtonHandle = uicontrol('style','push','String', 'STOP',...
'callback','set(gcbo,''userdata'',1,''string'',''DONE!'')', ...
'userdata',0) ;

while(1)
  if get(ButtonHandle,'userdata')
        break ;
  end

  h = imrect;
  pos = uint32(wait(h));

  if ~isempty(pos)    
      rectangle('Position', pos, 'LineWidth',1, 'EdgeColor','k');
      for i=1:4
      counter=counter+1;
      array (counter) = pos(i); 
      end
      delete(h);
   end
 end

1 个答案:

答案 0 :(得分:1)

我已经找到了在按下“停止”按钮后需要绘制额外矩形的原因,并且我找到了几种可能的解决方案来解决问题。

简而言之,问题是...... MatLab比你快。

更确切地说,这就是一步一步发生的事情:

假设您只想绘制一个矩形,然后按“停止”按钮停止绘制。

if循环开头的while语句中的条件未经验证(您尚未按下按钮),因此循环继续。

if get(ButtonHandle,'userdata')
   break ;
end

然后执行imrect语句

 h = imrect;

它启动矩形绘制过程:你可以绘制矩形,移动矩形,调整大小等等。

一旦开始绘图,就会执行下一个语句

pos = uint32(wait(h));

wait函数阻止MatLab命令行,直到您在矩形上double-click退出绘图模式

如果您绘制了一个有效的矩形,则下一个语句绘制实际的矩形,将矩形的位置存储在“数组”中,并将handle删除到imrect对象

if ~isempty(pos)    
   rectangle('Position', pos, 'LineWidth',1, 'EdgeColor','k');
   for i=1:4
      counter=counter+1;
      array (counter) = pos(i); 
   end
   delete(h);
end

此时您决定“停止”添加矩形并按下“停止”按钮。

这是MatLab比你更快的点。

当您移动muose的光标到达按钮时,脚本的执行将继续,并且while循环的新迭代开始。

再次执行第一个语句

if get(ButtonHandle,'userdata')

如果您没有那么快(并且您不能)到达“停止”按钮并在新迭代开始之前推送它,则if条件未被验证,因此       执行imrect序列

h = imrect;
pos = uint32(wait(h));

因为你打算画另一个矩形。

这是“附加”矩形,在按下“停止”按钮后需要“看到”以实际停止脚本。

虽然wait函数阻止了MatLab命令行,但callback列表器不是,因此您可以按下该按钮,userdata的值设置为{{1 }}  尽管如此,绘图过程已经激活。

因此,您需要绘制“附加”矩形,双击以退出1,以便可以开始“while循环”的另一次迭代。

此时,最终验证wait条件并且if语句停止执行break循环。

这就是发生的事情。

我找到了两种可能的解决方案:第一种解决方案允许保持脚本“几乎”不变,第二种方法意味着改变while概念。

第一种解决方案允许你......比MatLab更快。

如果在调用GUI之后插入pause语句(例如wait),则在新迭代开始之前,您将有3秒钟到达并按“停止”。

这样可以将che pause(3)设置callback设置为1,并在userdata循环的开头验证if条件,停止执行脚本无需绘制任何额外的矩形。

第二个解决方案包括更改while

的行为

您可以删除GUI循环并更改while,以便负责调用pushbutton callback并绘制矩形(实际上,您必须移动 imrectwhile循环内的代码。

这样GUI的行为将是:每当你想要添加一个矩形时,你必须推动pushbutton cllback

此后,您可以找到两种解决方案的脚本。

注意,我对您的其他代码进行了一些额外的修改,以使其运行:

我删除了pushbutton:轴中没有图片,默认uint32 cast限制为[0 1], 如果您将axes转换为pos,则pos将为[0 1 0 0]

此外,我已移除unsigned 32-bit integer循环以在for中存储pos:实际上并不需要。

解决方案#1

array

解决方案#2 主要脚本

% Commented since in the code excerpt is not used
% im_des=rgb2gray('pdb_img_1.jpg');
ButtonHandle = uicontrol('style','push','String', 'STOP',...
   'callback','set(gcbo,''userdata'',1,''string'',''DONE!'')', ...
   'userdata',0) ;

% Added initialization of "array" and array_32" arrays
%    array_32: stores the rectangle pos as uint32
%    array: stores the rectangle pos as double (added to make the script
%    running without an image on the axes)
array=[];
array_32=[];
%
while(1)
   if get(ButtonHandle,'userdata')
      break ;
   end

   % Commented type cast (default axix limit are [0 1] therefore
   %    pos=[ 0 1 0 0]
   h = imrect;
   %    pos = uint32(wait(h));
   pos = wait(h);

   % added message display and "pause" statement to allow pressing "Stop"
   % button before drawing next rectangle
   disp('Press STOP within 3 sec. to stop')
   pause(3)

   if ~isempty(pos)
      rectangle('Position', pos, 'LineWidth',1, 'EdgeColor','k')
      % if needed the edge color of each rectangle can be different
      %       rectangle('Position', pos, 'LineWidth',1,'EdgeColor',[rand(3,1)])
      %
      % Commented "for loop" to store rectangle pos since it is not needed
      %       for i=1:4
      %       counter=counter+1
      % "array" is built as (N x 4) matrix, each row contains the "pos" of
      % a rectangle (remove ";" to store it as a (1 x N) array
      array = [array ; pos]
      array_32 = [array_32 ; uint32(pos)]
      %       end

      delete(h)

   end

end

按钮回拨

array=[];
axes
ButtonHandle = uicontrol('style','push','String', 'Add rect',...
   'callback','tmp=add_rect;array=[array;tmp]');

希望这有帮助。