Hey i am trying to paint the edges of a biograph, i want to paint each time a new edge and keep the previews painted edges.
Here is my code
A = sparse(6,6);
A(Router1,Router2)=bool;
ids = {'A','B','C','D','E','F'};
grp = view(biograph(A,ids));
if bool == 0
[dist,path,pred1] = graphshortestpath(A,Router1,Router2);
edges = getedgesbynodeid(grp,get(grp.Nodes(path),'ID'));
set(edges,'LineColor',[1 0 0])
set(edges,'LineWidth',1.5)
end
Ass you can see i get the wanted edge painted in red.
now i am tring to paint another edge but i cant find a way to save the already painted one.
i want thinking about saving the path but i couldn't find a way to do it.
Related
How to draw a filled polygon in flutter?
Currently I am able to a eyebrow shape with array of point like below.
Path leftEyePath = Path();
leftEyePath.moveTo(leftEye[0].getX(),leftEye[0].getY());//starting point
for(int i=1;i<leftEye.length;i++){
leftEyePath.lineTo(leftEye[i].getX(),leftEye[i].getY());
}
canvas.drawPath(leftEyePath,painter);
The code above will eventually draw a connected polygon with many line , but how do I draw a filled polygon with color I want?
EDIT:
I am currently go through their function and found drawShadow(..)
canvas.drawShadow(leftEyePath, Colors.orange[600],0,true);
Unfortunately it only draw transparent color.
Below is my current output.
You may change your paint style into PaintingStyle.fill. The paint brush will automatically fill up the closing area of your path.
Paint _filledPainter = new Paint()
..style = PaintingStyle.fill
;
How should I change the background image color to black or change the RGB values become black color background. I want to take the original leaf image only.
Leaf image
In order to change the background color to black you'll need the following:
calculate the background mask by using a threshold
The threshold can be either find automatically, by using the function graythresh, or manually, by looking at the image histogram.
perform thresholding by using the value from stage 1 in order to find the foreground mask. Also, pick the largest connected component and perform noise cleaning (imclose operation).
calculate the BG from the FG, and zero out the corresponding locations in the original input image.
Code example:
I = imread('YaEwk.jpg');
%converts to hsv colorspace, and takes the 3rd dimension. normlizes it.
im = rgb2hsv(I);
im = mat2gray(im(:,:,3));
%determines a threshold to distinguish between the leaf and its surroundings.
T = graythresh(im);
%defines FG as all the values below the threshold
%Also, keeps just the biggest connected component and perform noise
%reduction.
FG = im < T;
FG = bwareafilt(FG,1);
FG = imclose(FG,strel('disk',2));
%defines the background as the opposite of the foreground
BG = ~FG;
I(repmat(BG,1,1,3)) = 0;
%smooth the output
I(:,:,1) = medfilt2(I(:,:,1));
I(:,:,2) = medfilt2(I(:,:,2));
I(:,:,3) = medfilt2(I(:,:,3));
Result:
I am writing a GUI in MATLAB (guide) where user will be shown 2 images(both images are positioned side by side in single gui window) from a series of images (but each drifted little bit) and will be allowed to select area of interest.
I want user to select working are in image 1 while simultaneously highlighting the selected area in image 2, so that it is easier to judge whether the feature of interest has drifted out of selected area or not. How to do that?
I am using following answer to select and crop area of interest(just FYI):
crop image with fixed x/y ratio
Here is a way to do it using imrect and its addNewPositionCallback method. Check here for a list of available methods.
In the following figure I create 2 axes. On the left that's the original image and on the right that's the "modified" image. By pressing the pushbutton, imrect is called and the addNewPositionCallback method executes a function, called GetROIPosition that is used to get the position of the rectangle defined by imrect. At the same time, in the 2nd axes, a rectangle is drawn with the same position as that in the 1st axes. To be even more fancy you can use the setConstrainedPosition to force the rectangle to be enclosed in a given axes. I'll let you do it :)
Here is the whole code with 2 screenshots:
function SelectROIs(~)
%clc
clear
close all
%//=========================
%// Create GUI components
hfigure = figure('Position',[300 300 900 600],'Units','Pixels');
handles.axesIm1 = axes('Units','Pixels','Position',[30,100,400 400],'XTick',[],'YTIck',[]);
handles.axesIm2 = axes('Units','Pixels','Position',[460,100,400,400],'XTick',[],'YTIck',[]);
handles.TextaxesIm1 = uicontrol('Style','Text','Position',[190 480 110 20],'String','Original image','FontSize',14);
handles.TextaxesIm2 = uicontrol('Style','Text','Position',[620 480 110 20],'String','Modified image','FontSize',14);
%// Create pushbutton and its callback
handles.SelectROIColoring_pushbutton = uicontrol('Style','pushbutton','Position',[380 500 120 30],'String','Select ROI','FontSize',14,'Callback',#(s,e) SelectROIListCallback);
%// ================================
%/ Read image and create 2nd image by taking median filter
handles.Im = imread('coins.png');
[Height,Width,~] = size(handles.Im);
handles.ModifIm = medfilt2(handles.Im,[3 3]);
imshow(handles.Im,'InitialMagnification','fit','parent',handles.axesIm1);
imshow(handles.ModifIm,'InitialMagnification','fit','parent',handles.axesIm2);
guidata(hfigure,handles);
%%
%// Pushbutton's callback. Create a draggable rectangle in the 1st axes and
%a rectangle in the 2nd axes. Using the addNewPositionCallback method of
%imrect, you can get the position in real time and update that of the
%rectangle.
function SelectROIListCallback(~)
hfindROI = findobj(handles.axesIm1,'Type','imrect');
delete(hfindROI);
hROI = imrect(handles.axesIm1,[Width/4 Height/4 Width/2 Height/2]); % Arbitrary size for initial centered ROI.
axes(handles.axesIm2)
rectangle('Position',[Width/4 Height/4 Width/2 Height/2],'EdgeColor','y','LineWidth',2);
id = addNewPositionCallback(hROI,#(s,e) GetROIPosition(hROI));
end
%// Function to fetch current position of the moving rectangle.
function ROIPos = GetROIPosition(hROI)
ROIPos = round(getPosition(hROI));
axes(handles.axesIm2)
hRect = findobj('Type','rectangle');
delete(hRect)
rectangle('Position',ROIPos,'EdgeColor','y','LineWidth',2);
end
end
The figure after pressing the button:
And after moving the rectangle around:
Yay! Hope that helps! Nota that since you're using GUIDE the syntax of the callbacks will look a bit different but the idea is exactly the same.
I'm working on a gui and using GUIDE. It loads and image and has the user draw an ROI around a point (the particle ROI). I would then like to have two sliders for creating a second ROI (the Scan ROI) where the user can use sliders to set the width and height of the second roi and see it updated on the image. The sliders seem to work ok but my gui keeps drawing a new roi on top of the image so it gets messy looking really fast. I would like to remove the user sizeable roi from the image before redrawing it (while still keeping the original particle ROI on the image. I currently do it the following way :
Inside the callback for the setroi size button (this should be for the particel ROI)
handles=guidata(hObject);
particleroiSize=imrect;% - draw a rectagle around the particle to get a meausr eof ROI size
roiPoints=getPosition(particleroiSize); %-get tha parameters fo the rectanlge
partX1 = round(roiPoints(1));
partY1 = round(roiPoints(2));
partX2 = round(partX1 + roiPoints(3));
partY2 = round(partY1 + roiPoints(4)); % these are the ROi positions in pixels
roiHeight = round(roiPoints(3)); % - these are just the ROI width and height
roiWidth = round(roiPoints(4));
handles=guidata(hObject); %_ update all the handles...
handles.partX1=partX1;
handles.partX2=partX2;
handles.partY1=partY1;
handles.partY2=partY2;
handles.roicenterX = (partX1 + round(roiPoints(3))/2);
handles.roicenterY= (partY1 + round(roiPoints(4))/2);
handles.roiHeight = roiHeight;
handles.roiWidth = roiWidth;
current_slice = round(get(handles.Image_Slider,'Value'));
particleImage=handles.Image_Sequence_Data(partY1:partY2,partX1:partX2,current_slice);
handles.particleImage=particleImage;
set(handles.RoiSizeDisplay,'String',strcat('Particle ROI is ',' ',num2str(roiHeight),' ', ' by ',num2str(roiWidth)) );
guidata(hObject,handles);
And then inside the call back for the sliders that set the Scan ROI size I have (this is inside two different sliders one adjusts the width and one the height :
handles=guidata(hObject);
try
delete(handles.ScanArea);
% plus any cleanup code you want
catch
end
WidthValue = get(handles.ScanAreaSliderWidth,'value');
HeightValue = get(handles.ScanAreaSliderHeight,'value');
set(handles.ScanAreaWidthDisplay,'String',strcat('Scan Area Width is ',' ', num2str(WidthValue))); % sets the display..now to do the drawing...
%h = imrect(hparent, position);
%position = [Xmin Ymin Width Heigth];
position = [ round(handles.roicenterX-WidthValue/2) round(handles.roicenterY-HeightValue/2) WidthValue HeightValue];
handles.ScanArea = imrect(handles.Image_Sequence_Plot,position);
%h = imrect(hparent, position)
handles=guidata(hObject);
guidata(hObject, handles);
But it never deletes the scan area ROI and keeps redrawign over it..I thought the try...catch would work but it doens't seem to. Am I making extra copies of the ROI or something? Please help..
Thanks.
If you need to delete the ROI drawn with imrect, you can use findobj to look for rectangle objects (which are of type "hggroup") and delete them:
hfindROI = findobj(gca,'Type','hggroup');
delete(hfindROI)
and that should do it. Since you first draw particleroiSize, which is of the hggroup type as well, you might not want to delete all the outputs from the call to findobj. If there are multiple rectangles in your current axis, then hfindROI will contain multiple entries. As such you might want to delete all of them but the first one, which corresponds to particleroiSize.
I hope i got your question right. If not please ask for clarifications!
Thanks. This worked perfectly except that I had to use
hfindROI = findobj(handles.Image_Sequence_Plot,'Type','hggroup');
delete(hfindROI(1:end-1))
to get rid of everything but the first ROI, so I guessteh hggoup objects are added at the start ? (I thought I would use deleted(hfindROI(2:end)) to delete all but the first. Also, why does hfindROI return a list of numbers? Do they represent the hggroup objects or something like that?
thanks..
By following this post Using ismember with the output of regionprops I am able to selectively isolate the connected component I want. For example using my code below:
img = rgb2gray(imread('W1\Writer1_01_02.jpg'));
bw_normal2 = im2bw(img, graythresh(img));
bw22 = imcomplement(bw_normal2);
bw3 = bwmorph(bw22, 'dilate');
[label2,n2] = bwlabel(bw3);
stats2 = regionprops(label2, {'Area', 'BoundingBox'});
area2 = [stats2.Area];
idx = find((28 <= area2) & (area2 <= 40));
BW2 = ismember(label2,idx);
figure, imshow(BW2)
I can easily display the output that contains ONLY the connected component whose area is between 28 and 40. As so
But instead can I make a bounding box around this connected component in the original image. I mean if this is the original image:
Can I make a bounding box around my desired component on the original image? I know that this is the code for making a bounding box around all of my connected components
imshow(img);
for j=1:n2
hold on
rectangle('Position',[stats(j).BoundingBox(1),stats(j).BoundingBox(2),stats(j).BoundingBox(3),stats(j).BoundingBox(4)],...
'EdgeColor','r','LineWidth',2 );
end
But how do I only make a bounding box only around the element having area between 28 and 40? Rather than producing a completely different image as shown above.
Keep a if condition in your second half of the code...
imshow(img);
for j=1:n2
hold on
area2 = stats2(j).Area;
if((28 <= area2) & (area2 <= 40))
rectangle('Position',[stats2(j).BoundingBox(1),stats2(j).BoundingBox(2),stats2(j).BoundingBox(3),stats2(j).BoundingBox(4)],...'EdgeColor','r','LineWidth',2 );
end
end