Как рисовать круг на изображении в MATLAB?
У меня есть изображение в MATLAB:
im = rgb2gray(imread('some_image.jpg');
% normalize the image to be between 0 and 1
im = im/max(max(im));
И я сделал некоторую обработку, которая привела к ряду пунктов, которые я хочу выделить:
points = some_processing(im);
Где points
- матрица того же размера, что и im
с единицами в интересных точках.
Теперь я хочу нарисовать круг на изображении во всех местах, где points
равно 1.
Есть ли какая-нибудь функция в MATLAB, которая делает это? Лучшее, что я могу придумать, это:
[x_p, y_p] = find (points);
[x, y] = meshgrid(1:size(im,1), 1:size(im,2))
r = 5;
circles = zeros(size(im));
for k = 1:length(x_p)
circles = circles + (floor((x - x_p(k)).^2 + (y - y_p(k)).^2) == r);
end
% normalize circles
circles = circles/max(max(circles));
output = im + circles;
imshow(output)
Это кажется более чем несколько неэлегантным. Есть ли способ рисовать круги, подобные функции line
?
Ответы
Ответ 1
Вы можете использовать обычную команду PLOT с круглая точка маркера:
[x_p,y_p] = find(points);
imshow(im); %# Display your image
hold on; %# Add subsequent plots to the image
plot(y_p,x_p,'o'); %# NOTE: x_p and y_p are switched (see note below)!
hold off; %# Any subsequent plotting will overwrite the image!
Вы также можете настроить эти другие свойства маркера графика: MarkerEdgeColor
, MarkerFaceColor
, MarkerSize
.
Если вы хотите сохранить новое изображение с нанесенными на него маркерами, вы можете посмотреть этот ответ, который я дал, на вопрос о сохранении размеров изображения при сохранении изображения с рисунков.
ПРИМЕЧАНИЕ: При построении данных изображения с IMSHOW (или IMAGE и т.д.), нормальная интерпретация строк и столбцов существенно перевернута. Обычно первое измерение данных (то есть строк) рассматривается как данные, которые лежат на оси х, и, вероятно, поэтому вы используете x_p
как первый набор значений, возвращаемых FIND. Однако IMSHOW отображает первое измерение данных изображения вдоль оси y, поэтому первое значение, возвращаемое FIND, в этом случае становится значением y-координаты.
Ответ 2
Этот файл от Zhenhai Wang от Matlab Central File Exchange делает трюк.
%----------------------------------------------------------------
% H=CIRCLE(CENTER,RADIUS,NOP,STYLE)
% This routine draws a circle with center defined as
% a vector CENTER, radius as a scaler RADIS. NOP is
% the number of points on the circle. As to STYLE,
% use it the same way as you use the rountine PLOT.
% Since the handle of the object is returned, you
% use routine SET to get the best result.
%
% Usage Examples,
%
% circle([1,3],3,1000,':');
% circle([2,4],2,1000,'--');
%
% Zhenhai Wang <[email protected]>
% Version 1.00
% December, 2002
%----------------------------------------------------------------
Ответ 3
Забавно! Здесь есть 6 ответов, ни одно из них не дает очевидного решения: функция rectangle
.
Из документация:
Нарисуйте круг, установив свойство кривизны в [1 1]. Нарисуйте круг так, чтобы он заполнил прямоугольную область между точками (2,4) и (4,6). Свойство Position определяет наименьший прямоугольник, содержащий круг.
pos = [2 4 2 2];
rectangle('Position',pos,'Curvature',[1 1])
axis equal
Итак, в вашем случае:
imshow(im)
hold on
[y, x] = find(points);
for ii=1:length(x)
pos = [x(ii),y(ii)];
pos = [pos-0.5,1,1];
rectangle('position',pos,'curvature',[1 1])
end
В отличие от принятого ответа, эти круги будут масштабироваться с изображением, вы можете увеличить масштаб, они всегда будут отмечать весь пиксель.
Ответ 4
Хмм мне пришлось повторно переключить их в этом вызове:
k = convhull(x,y);
figure;
imshow(image); %# Display your image
hold on; %# Add subsequent plots to the image
plot(x,y,'o'); %# NOTE: x_p and y_p are switched (see note below)!
hold off; %# Any subsequent plotting will overwrite the image!
В ответ на комментарии:
x и y создаются с использованием следующего кода:
temp_hull = stats_single_object(k).ConvexHull;
for k2 = 1:length(temp_hull)
i = i+1;
[x(i,1)] = temp_hull(k2,1);
[y(i,1)] = temp_hull(k2,2);
end;
возможно, что ConvexHull - это наоборот, и поэтому сюжет другой. Или что я допустил ошибку, и это должно быть
[x(i,1)] = temp_hull(k2,2);
[y(i,1)] = temp_hull(k2,1);
Однако в документации не ясно, какой colum = x OR y:
Цитата: "Каждая строка матрицы содержит x- и y-координаты одной вершины многоугольника".
Я прочитал это как x - первый столбец, а y - второй.
Ответ 5
В новых версиях MATLAB (я имею 2013b) система System Vision System Tool содержит vision.ShapeInserter
Системный объект, который можно использовать для рисования формы на изображениях. Вот пример рисования желтых кругов из документации:
yellow = uint8([255 255 0]); %// [R G B]; class of yellow must match class of I
shapeInserter = vision.ShapeInserter('Shape','Circles','BorderColor','Custom','CustomBorderColor',yellow);
I = imread('cameraman.tif');
circles = int32([30 30 20; 80 80 25]); %// [x1 y1 radius1;x2 y2 radius2]
RGB = repmat(I,[1,1,3]); %// convert I to an RGB image
J = step(shapeInserter, RGB, circles);
imshow(J);
Ответ 6
С помощью MATLAB и Image Processing Toolbox R2012a или новее вы можете использовать функцию viscircles
, чтобы легко накладывать круги на изображение. Вот пример:
% Plot 5 circles at random locations
X = rand(5,1);
Y = rand(5,1);
% Keep the radius 0.1 for all of them
R = 0.1*ones(5,1);
% Make them blue
viscircles([X,Y],R,'EdgeColor','b');
Кроме того, проверьте imfindcircles
, которая реализует круговое преобразование Hough. В онлайн-документации для обеих функций (ссылки выше) есть примеры, показывающие, как находить круги в изображении и как отображать обнаруженные круги над изображением.
Например:
% Read the image into the workspace and display it.
A = imread('coins.png');
imshow(A)
% Find all the circles with radius r such that 15 ≤ r ≤ 30.
[centers, radii, metric] = imfindcircles(A,[15 30]);
% Retain the five strongest circles according to the metric values.
centersStrong5 = centers(1:5,:);
radiiStrong5 = radii(1:5);
metricStrong5 = metric(1:5);
% Draw the five strongest circle perimeters.
viscircles(centersStrong5, radiiStrong5,'EdgeColor','b');
Ответ 7
Здесь, как мне кажется, вам нужен способ:
[x_p, y_p] = find (points);
% convert the subscripts to indicies, but transposed into a row vector
a = sub2ind(size(im), x_p, y_p)';
% assign all the values in the image that correspond to the points to a value of zero
im([a]) = 0;
% show the new image
imshow(im)