imwrite result of viscircles instead of creategraphic

3 Ansichten (letzte 30 Tage)
Karuna Skipper
Karuna Skipper am 5 Dez. 2023
Kommentiert: Karuna Skipper am 10 Dez. 2023
Hi. I use the following code to identify multiple (5-20) circles in an image, highlight and number the circles, and export the resulting image. This then cycles through a folder full of similar data.
for k = 1:numel(S)
%define image
fFname = fullfile(D,S(k).name);
OGFile = imread(fFname);
[fF_path,fFname,fFext] = fileparts(fFname);
%identify circles
[Ctrs,radii] = imfindcircles(OGFile, [10 20],'ObjectPolarity','bright', 'Sensitivity',0.92,'EdgeThreshold',0.10);
%highlight and label circles
hold on
h = viscircles(Ctrs,radii);
hold off
for c = 1:length(radii)
c_list = num2str(c);
text(Ctrs(c,1),Ctrs(c,2),c_list,'color','r','FontWeight','bold','HorizontalAlignment', 'center','VerticalAlignment', 'middle');
%save graphic
fFnameExt = fullfile(SavePath,[fFname,'_circles',fFext]);
My issue is that I am using exportgraphics, meaning the resolution of the exported image differs from my original.
I would instead like to use imwrite, to save my image instead of effectively screencapping it.
However, this would require me burning or appending the viscircles and text results to my original image, which I am unsure how to do. Any help here would be greatly appreciated.
  1 Kommentar
Constantino Carlos Reyes-Aldasoro
What do you need, an image in which you have all you want, but not able to modify would work with imwrite. You could also save the figure itself with an extension .fig, which you can then manipulate and use handles for each element in the figure.

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

DGM am 6 Dez. 2023
Bearbeitet: DGM am 6 Dez. 2023
Viscircles() does not create raster image data. The only way to capture its output is as you say, a screenshot.
I see three options:
  1. Try to get a better screenshot
  2. Try to combine a screenshot of the annotations alone with an otherwise undamaged copy of the image
  3. Try to construct a raster image with the annotations without using viscircles()
For option one, if you want to get captures such that
  • the image content is the exact same size as before
  • the image does not have added borders of random size
... then you're going to have fun. I don't have exportgraphics(), but getting consistent behavior out of screencaps is ridiculous as far as I can tell. Feel free to try this demo. No point running this on the forum, since your system will be different.
%define image
fFname = 'cameraman.tif'; % this is 256x256
OGFile = imread(fFname);
%identify circles
[Ctrs,radii] = imfindcircles(OGFile, [10 20],'ObjectPolarity','bright', 'Sensitivity',0.92,'EdgeThreshold',0.10);
%highlight and label circles
hold on
h = viscircles(Ctrs,radii);
hold off
for c = 1:length(radii)
c_list = num2str(c);
text(Ctrs(c,1),Ctrs(c,2),c_list,'color','r','FontWeight','bold','HorizontalAlignment', 'center','VerticalAlignment', 'middle');
% truesize() is the canonical solution
% but it seems to never actually work if there are other objects in the axes
% in other words, the only scenario where it seems to work is the trivial case
% where using a screenshot is a completely avoidable in the first place.
sz = [size(OGFile,1) size(OGFile,2)];
truesize(gcf,sz) % doesn't actually do anything
drawnow % pretend this matters
% since truesize() didn't do anything
% the size of this image is effectively out of our control
% depending on the scanario, i get a random size between 400x400 and 900x1200
% may or may not include padding
fFnameExt = 'test.png';
S = imfinfo(fFnameExt); [S.Height S.Width] % the captured size
% you can try to use getframe(), which is more likely to be close
% but there are no assurances it will actually be the expected size.
% depending on the scanario, i get a random size around 255x255 to 260x260
% may or may not include padding
screencap = frame2im(getframe(gca));
% you can jump through a bunch of hoops to try to force the capture to be correct
% in all tests, i get a 256x256 image with no padding
betterscreencap = captureaxes(gca,sz);
clf; close all
For option two:
I suppose if you were worried about any potential damage to the image content by the screencap process, you could create a composition. That way, any degradation will be in the annotations alone, not the underlying image.
% ... load the file, findcircles, etc
%highlight and label circles
imshow(zeros(sz)) % use a dummy black image when plotting
% ... call viscircles, do plot setup, etc
% get a screenshot of the annotations alone
overlay = captureaxes(gca,sz);
% create a mask
mask = im2double(max(overlay,[],3));
% create a composite image
outpict = im2double(overlay).*mask ...
+ im2double(OGFile).*(1 - mask);
outpict = im2uint8(outpict);
There might be other ways to do the composition, but that's probably the simplest. I'm not really sure how well this will turn out in practice. I imagine you might tend to have ragged fringing around the mask edges. The apparent severity depends on the resolution of the underling image.
For option three:
If you have Computer Vision Toolbox, you could probably use insertShape() to draw the circles in a raster image; similarly, CVT has insertText(). I don't have CVT, so I'm not going to demo that.
Drawing circles directly in an image can be done otherwise, but the harder part will be drawing the text. Unless that's the route you want to take, I'll hold off on going further.
In any case, if fidelity (at least within the original image content) is a concern, you might make sure that your output file format is lossless. I slightly suspect you're using TIF, but to the same degree, I have to acknowledge that tons of people love using JPG. Transcoding a JPG really throws fidelity out the window, and your routine would inherit the format from the input. Just a thought.
  3 Kommentare
Karuna Skipper
Karuna Skipper am 10 Dez. 2023
Thank you for such detailed answers! I will try these and let you know which works for me.
Karuna Skipper
Karuna Skipper am 10 Dez. 2023
Option two was perfect, thank you again!
I sometimes had the issue of partial circles being detected on the edges of the image, which led to the mask being of a greater size than the original, but I circumvented that by adding a 10px border to OGFile from the start.
See below, original vs output.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (1)

Image Analyst
Image Analyst am 7 Dez. 2023
Try this if you have the Computer Vision Toolbox.
% Initialization steps.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 18;
inputFolder = pwd;
outputFolder = pwd;
fileList = dir('*.png');
for k = 1:numel(fileList)
% Define image
baseFileName = fileList(k).name;
fullInputFileName = fullfile(inputFolder,baseFileName);
fprintf('Processing image %d of %d : "%s".\n', k, numel(fileList), fullInputFileName);
originalFile = imread(fullInputFileName);
[inputFolder,baseFileNameNoExt, ext] = fileparts(fullInputFileName);
%identify circles
[centers,radii] = imfindcircles(originalFile, [10 20],'ObjectPolarity','bright', 'Sensitivity',0.92,'EdgeThreshold',0.10);
%highlight and label circles
hold on
h = viscircles(centers, radii);
hold off
for c = 1:length(radii)
c_list = num2str(c);
text(centers(c,1),centers(c,2),c_list,'color','r','FontWeight','bold','HorizontalAlignment', 'center','VerticalAlignment', 'middle');
% Insert circles.
xyRadius = [centers, radii];
rgbImageWithAnnotations = insertShape(originalFile,"circle",xyRadius, "LineWidth",2, "ShapeColor","blue");
% Insert text
values = 1:length(radii);
% Insert the numeric values using the bottom-left corner of each text box as its anchor point.
rgbImageWithAnnotations = insertText(rgbImageWithAnnotations,centers,values,...
AnchorPoint="Center", FontSize=18, FontColor="b");
hFig = figure
%save graphic
fullOutputFileName = fullfile(outputFolder, [baseFileNameNoExt, '_circles.png']);
fprintf(' Saving image %d of %d : "%s".\n', k, numel(fileList), fullOutputFileName);
hFig.WindowState = 'maximized';




Community Treasure Hunt

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

Start Hunting!

Translated by