How to create a centerline between lines in image
조회 수: 2 (최근 30일)
이전 댓글 표시
Hi,
I'm trying to create a centerline between the two lines. Can someone help me?
[rows, columns] = size(birdsEyeImage);
leftEdges = nan(rows, 1);
rightEdges = nan(rows, 1);
for row = 1 : rows
t = find(birdsEyeImage(row, :), 1, 'first');
if ~isempty(t)
leftEdges(row) = t;
rightEdges(row) = find(birdsEyeImage(row, :), 1, 'last');
end
end
midPoints = ((leftEdges + rightEdges) / 2);
imshow(birdsEyeImage)
hold on
%x = 1:rows;
plot(midPoints, '*')
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/975255/image.jpeg)
댓글 수: 2
Matt J
2022년 4월 23일
I'm trying to create a centerline between the two lines.
I see 4 lines in the image you have posted, two white and two blue.
채택된 답변
Image Analyst
2022년 4월 23일
If you want no breaks, then interpolate. Like this. midX and midY are the line coordinates.
% Initialization steps.
clc;
clearvars;
close all;
workspace;
fontSize = 16;
grayImage = imread('2 lines.png');
if ndims(grayImage) == 3
% It's color. Take the red channel.
grayImage = grayImage(:, :, 1);
end
imshow(grayImage, []);
impixelinfo;
axis('on', 'image')
mask = logical(grayImage > 140 & grayImage < 255);
mask = bwareafilt(mask, 2); % Make sure we have only two lines.
mask = bwskel(mask);
imshow(mask);
impixelinfo;
axis('on', 'image')
labeledImage = bwlabel(mask);
line1 = ismember(labeledImage, 1);
line2 = ismember(labeledImage, 2);
% Get rows and columns of each line.
[r1, c1] = find(line1);
[r2, c2] = find(line2);
for k = 1 : length(r1)
distances = sqrt((r1(k) - r2) .^ 2 + (c1(k) - c2) .^ 2);
[minDistance, index] = min(distances);
% Find the midPoint
midX(k) = mean([c1(k), c2(index)]);
midY(k) = mean([r1(k), r2(index)]);
% Burn into mask
mask(round(midY(k)), round(midX(k))) = true;
end
% Need to add a small amount of noise to x to make the values unique.
midX = midX + 0.001 * rand(size(midX));
midY = midY + 0.001 * rand(size(midY));
% Interpolate x and y to make sure there are no gaps.
kVec = 1 : length(midX);
kFit = linspace(1, kVec(end), 10000);
xFit = interp1(kVec, midX, kFit, 'linear');
yFit = interp1(kVec, midY, kFit, 'linear');
% Remove duplicate values
xy = unique(round([xFit(:), yFit(:)]), "rows");
% Extract individual x and y.
midX = xy(:, 1);
midY = xy(:, 2);
hold on;
plot(midX, midY, 'r.', 'MarkerSize', 10);
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/975490/image.png)
댓글 수: 2
Image Analyst
2022년 4월 23일
If it worked, the usual thing to do is to click the "Accept this answer", 🙂 unless you want to wait to see if anyone else will offer a better answer.
추가 답변 (2개)
Image Analyst
2022년 4월 23일
편집: Image Analyst
2022년 4월 23일
Make it easy for us to help you. Attach the actual PNG image file, not a Fig file. Then we can open it with imread() and not have any other stuff surrounding it like tick marks, etc. Just attach the one with white lines, not white and blue lines.
What I'd to is to skeletonize and label the image. Then I'd loop over all pixels in the one line and use sqrt() to get distances to all the other pixels in the other line. Then use min() to get the index of the closest one. Then get the average of the two pixels x and y values and assign that point to be true or use plot() to drop a marker there. Here's a start
mask = logical(imread(filename));
mask = bwareafilt(mask, 2); % Make sure we have only two lines.
mask = bwskel(mask);
imshow(mask);
labeledImage = bwlabel(mask);
line1 = ismember(labeledImage, 1);
line2 = ismember(labeledImage, 2);
% Get rows and columns of each line.
[r1, c1] = find(line1);
[r2, c2] = find(line2);
for k = 1 : length(r1)
distances = sqrt((r1(k) - r2) .^ 2 + (c1(k) - c2) .^ 2);
[minDistance, index] = min(distances);
% Find the midPoint
midX = mean([c1(k), c2(index)]);
midY = mean([r1(k), r2(index)]);
% Burn into mask
mask(round(midY), round(midX)) = true;
% Optionally drop a marker there
hold on;
plot(midX, midY, 'r.', 'MarkerSize', 10);
end
댓글 수: 2
Image Analyst
2022년 4월 23일
OK, that's a color image, not a binary image. So I need to do a little extra color segmentation to get just the two lines. But I did it for you and here it is:
% Initialization steps.
clc;
clearvars;
close all;
workspace;
fontSize = 16;
grayImage = imread('2 lines.png');
if ndims(grayImage) == 3
% It's color. Take the red channel.
grayImage = grayImage(:, :, 1);
end
imshow(grayImage, []);
impixelinfo;
mask = logical(grayImage > 140 & grayImage < 255);
mask = bwareafilt(mask, 2); % Make sure we have only two lines.
mask = bwskel(mask);
imshow(mask);
labeledImage = bwlabel(mask);
line1 = ismember(labeledImage, 1);
line2 = ismember(labeledImage, 2);
% Get rows and columns of each line.
[r1, c1] = find(line1);
[r2, c2] = find(line2);
for k = 1 : length(r1)
distances = sqrt((r1(k) - r2) .^ 2 + (c1(k) - c2) .^ 2);
[minDistance, index] = min(distances);
% Find the midPoint
midX = mean([c1(k), c2(index)]);
midY = mean([r1(k), r2(index)]);
% Burn into mask
mask(round(midY), round(midX)) = true;
% Optionally drop a marker there
hold on;
plot(midX, midY, 'r.', 'MarkerSize', 10);
end
![](https://www.mathworks.com/matlabcentral/answers/uploaded_files/975370/image.png)
If you want the line to be unbroken, you can use interp1() to get a value for either every row or every column. Just index your midpoints and call interp1(). I think you can do it, right?
참고 항목
카테고리
Help Center 및 File Exchange에서 Musical Instrument Digital Interface (MIDI)에 대해 자세히 알아보기
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!