Paint by numbers with Matlab. Imcontour function

10 vues (au cours des 30 derniers jours)
Irina Corbu
Irina Corbu le 2 Juil 2021
Commenté : Irina Corbu le 3 Juil 2021
Hi! I am working for my diploma project and I encounter some difficulties. I am trying to make a paint by number program where you put an image and the program shows the contour of the colors and the colorbar. Also I want to label every area of the contour with the number of the color that is in that area. I have managed to do this but it's not the result I am expecting. As you can see in the image below, the labels of the colors are on the lines and not on the contoured area and the colorbar is a gradient and not separate colors as they are in the colorbar of an indexed image. How can I make more accurate contour regions and to label them in the middle of the region not on the line? How can I make the colorbar to appear as separate colors and not as a gradient?
[IND,map] = rgb2ind(I,10);
imagesc(app.UIAxes, I);
s=colorbar(app.UIAxes);
colormap(app.UIAxes,map);
imshow(I,'Parent',app.UIAxes);
I2=ind2gray(IND,map);
colormap(app.UIAxes, map);
axis image;
%imshow(I2,'Parent',app.UIAxes);
[C,h]=imcontour(I2,'-k');
clabel(C,h)
colorbar;
  1 commentaire
DGM
DGM le 2 Juil 2021
For the colorbar, make sure to assert
colormap(axeshandle,map)
after you run imcontour().
That said, the difficulty of figuring out how to move the labels leaves me thinking that using contour() probably isn't the simplest way to do this. I might think about that one for a bit.

Connectez-vous pour commenter.

Réponse acceptée

DGM
DGM le 2 Juil 2021
Modifié(e) : DGM le 3 Juil 2021
This isn't really complete, but I'm not really sure that the best approach is found down that road. I'm using this as my test image:
inpict = imread('sources/blobs.png');
% convert to indexed image using an appropriate-length map
% don't let it do any dithering
[indpict map] = rgb2ind(inpict,6,'nodither');
nc = size(map,1);
s = size(indpict);
% generate edgemap and mask off edges of indpict
% fattening the edgemap and using it to mask off indpict
% helps deal with how rgb2ind() will poorly handle antialiased edges
edgepict = imdilate(edge(indpict),ones(2));
edgepict = padarray(edgepict,[1 1],1,'both');
indpict = padarray(indpict+1,[1 1],1,'both');;
indpict(edgepict) = 0;
labelpos = cell(nc,1);
for c = 1:nc
tcpict = indpict==c;
% to place the numbers, the easy way is to use the region centroids.
% this isn't perfect and may fail with deeply concave regions, but it's simple.
%S = regionprops(tcpict,'centroid');
%labelpos{c} = vertcat(S.Centroid);
% better would be the centroid of the largest inscribed convex subarea
% but that's complicated. let's just find the centroid of the largest
% near-maximal region of the distance map.
[L N] = bwlabel(tcpict);
dmap = bwdist(~tcpict);
labelpos{c} = [];
for n = 1:N
tdmap = dmap.*(L==n);
tdmap = tdmap>=(0.9*max(tdmap(:)));
S = regionprops(tdmap,'centroid','area');
[~,idx] = max(vertcat(S.Area));
labelpos{c} = [labelpos{c}; S(idx).Centroid];
end
end
imshow(~edgepict); hold on
for c = 1:nc
text(labelpos{c}(:,1),labelpos{c}(:,2), ...
num2str(c),'horizontalalignment','center');
end
Note the fact that the barbell and C-shaped objects centroids are not really in a good place to fit a label. This is a case where the simple positioning method doesn't work well.
Using the preferred method in the example, the labels are placed a bit more usefully.
The numbers in the image should correspond to the appropriate row indices for the colormap. Note the ring object. isolated regions of the same color will each have their own number label.
Trying to use the colorbar with an image display will mess with the displayed colors of the image. In order to have a colorbar without influencing the image, you'll probably need to resort to creating a second hidden axes. It's basically the same problem as having two plots with different colormaps.
That said, I don't really know why you need the colorbar for this task. If you're trying to use it for a color palette in the GUI, there are probably plenty of other ways that would cause fewer headaches than trying to misuse a colorbar. One way might be to create a series of colored blocks using uibutton objects with their background color properties set to match the color table. You could also generate a very simple stripe image from the color table and display it in a second axes alongside the image, sort of like a manual version of a colorbar without all the problematic behaviors caused by unused features. You could then set the axes buttonDownFunction to use ginput or something to get the cursor position and back-calculate the selected color from the colortable image.

Plus de réponses (0)

Produits


Version

R2020a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by