В этом примере показано, как измерить угол и точку пересечения между двумя балками с помощью bwtraceboundary, которая является подпрограммой трассировки границ. Обычной задачей в приложениях машинного зрения является измерение без помощи рук с использованием методов получения изображения и обработки изображения.
Чтение в gantrycrane.png и нарисуют стрелки, указывающие на два представляющих интерес луча. Представляет собой изображение козлового крана, используемого для сборки моста.
RGB = imread('gantrycrane.png'); imshow(RGB); text(size(RGB,2),size(RGB,1)+15,'Image courtesy of Jeff Mather',... 'FontSize',7,'HorizontalAlignment','right'); line([300 328],[85 103],'color',[1 1 0]); line([268 255],[85 140],'color',[1 1 0]); text(150,72,'Measure the angle between these beams','Color','y',... 'FontWeight', 'bold');

Обрезать изображение, чтобы получить только балки портального крана, выбранного ранее. Этот шаг облегчит извлечение кромок двух металлических балок.
% you can obtain the coordinates of the rectangular region using % pixel information displayed by imtool start_row = 34; start_col = 208; cropRGB = RGB(start_row:163, start_col:400, :); imshow(cropRGB)

% Store (X,Y) offsets for later use; subtract 1 so that each offset will % correspond to the last pixel before the region of interest offsetX = start_col-1; offsetY = start_row-1;
Преобразование изображения в черно-белое для последующего извлечения координат кромки с помощью bwtraceboundary рутина.
I = rgb2gray(cropRGB);
BW = imbinarize(I);
BW = ~BW; % complement the image (objects of interest must be white)
imshow(BW)
bwtraceboundary для выполнения подпрограммы необходимо указать одну точку на границе. Эта точка используется в качестве начального местоположения для процесса трассировки границ.
Чтобы извлечь край нижнего луча, выберите столбец на изображении и проверьте его до тех пор, пока не произойдет переход от фонового пикселя к объектному пикселю. Сохранить это расположение для последующего использования в bwtraceboundary рутина. Повторите эту процедуру для другой балки, но на этот раз трассировку по горизонтали.
dim = size(BW); % horizontal beam col1 = 4; row1 = find(BW(:,col1), 1); % angled beam row2 = 12; col2 = find(BW(row2,:), 1);
bwtraceboundary используется для извлечения (X, Y) местоположений граничных точек. Чтобы максимизировать точность расчетов угла и точки пересечения, важно извлечь как можно больше точек, принадлежащих кромкам балки. Количество точек следует определить экспериментально. Поскольку исходная точка для горизонтальной полосы была получена сканированием с севера на юг, наиболее безопасно установить начальную стадию поиска так, чтобы она указывала на внешнюю сторону объекта, т.е. «Север».
boundary1 = bwtraceboundary(BW, [row1, col1], 'N', 8, 70); % set the search direction to counterclockwise, in order to trace downward. boundary2 = bwtraceboundary(BW, [row2, col2], 'E', 8, 90,'counter'); imshow(RGB); hold on; % apply offsets in order to draw in the original image plot(offsetX+boundary1(:,2),offsetY+boundary1(:,1),'g','LineWidth',2); plot(offsetX+boundary2(:,2),offsetY+boundary2(:,1),'g','LineWidth',2);

Хотя (X, Y) пары координат были получены на предыдущем шаге, не все точки лежат точно на прямой. Какие из них следует использовать для вычисления угла и точки пересечения? Предполагая, что все полученные точки одинаково важны, подгоняйте линии к местоположениям граничных пикселей.
Уравнение для прямой y = [x 1] * [a; b]. Вы можете решить для параметров «a» и «b» в смысле наименьших квадратов, используяpolyfit.
ab1 = polyfit(boundary1(:,2), boundary1(:,1), 1); ab2 = polyfit(boundary2(:,2), boundary2(:,1), 1);
Используйте скалярное произведение, чтобы найти угол.
vect1 = [1 ab1(1)]; % create a vector based on the line equation vect2 = [1 ab2(1)]; dp = dot(vect1, vect2); % compute vector lengths length1 = sqrt(sum(vect1.^2)); length2 = sqrt(sum(vect2.^2)); % obtain the larger angle of intersection in degrees angle = 180-acos(dp/(length1*length2))*180/pi
angle = 129.4971
Решите систему двух уравнений, чтобы получить координаты (X, Y) точки пересечения.
intersection = [1 ,-ab1(1); 1, -ab2(1)] \ [ab1(2); ab2(2)]; % apply offsets in order to compute the location in the original, % i.e. not cropped, image. intersection = intersection + [offsetY; offsetX]
intersection = 2×1
143.0917
295.7494
inter_x = intersection(2); inter_y = intersection(1); % draw an "X" at the point of intersection plot(inter_x,inter_y,'yx','LineWidth',2); text(inter_x-60, inter_y-30, [sprintf('%1.3f',angle),'{\circ}'],... 'Color','y','FontSize',14,'FontWeight','bold'); interString = sprintf('(%2.1f,%2.1f)', inter_x, inter_y); text(inter_x-10, inter_y+20, interString,... 'Color','y','FontSize',14,'FontWeight','bold');

bwboundaries | bwtraceboundary | imbinarize | polyfit