Identify specific rectangular shape in image and measure distance

I'd like to be able to identify a specific rectangle within my image, because I would then like to meake a measurement from the edge of the image to the upper boundary of this rectangle.
I will have several images of the same object containing the rectangle from several differnet imaging systems. The orientation and position of the object should always be very close to as it appears in these examples, but it will be aligned by hand so there may be some small differences.
My image looks like this, and I am after the long thin horizontal band in the center of the image:
Ultimately, I want to make the measurement in yellow- from the top of the image to the top of the horizontal rectangle in the center of the image drawn in red.
I am having trouble segmenting out the rectangle- I don't have much expereince and have tried some simple thresholding and morphology but have not been succressful. I've attached a couple different example images. Perhaps I need to look into some sort of edge detection? If the object is grossly misaligned, the measurement is useless anyway, so perhps an inital crop could work. Thaniks for any help or insights.

 채택된 답변

Try this. Adapt as needed.
% Demo by Image Analyst
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 = 16;
markerSize = 20;
%--------------------------------------------------------------------------------------------------------
% READ IN TEST IMAGE
folder = pwd;
baseFileName = "marcus.png";
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~isfile(fullFileName)
% The file doesn't exist -- didn't find it there in that folder.
% Check the entire search path (other folders) for the file by stripping off the folder.
fullFileNameOnSearchPath = baseFileName; % No path this time.
if ~exist(fullFileNameOnSearchPath, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
% Read in image file.
grayImage = imread(fullFileName);
% Get size
[rows, columns, numberOfColorChannels] = size(grayImage)
rows = 650
columns = 649
numberOfColorChannels = 3
if numberOfColorChannels == 3
% If it's color, convert to gray scale.
grayImage = rgb2gray(grayImage);
end
% Display the image.
subplot(2, 1, 1);
imshow(grayImage);
axis('on', 'image');
impixelinfo;
title('Original Image', 'FontSize', fontSize, 'Interpreter', 'None');
% Maximize window.
g = gcf;
g.WindowState = 'maximized';
g.Name = 'Demo by Image Analyst';
g.NumberTitle = 'off';
drawnow;
%--------------------------------------------------------------------------------------------------------
% Get the mean across columns
verticalProfile = mean(grayImage, 2);
% Erase top and bottom parts.
line1 = 262;
line2 = 362;
maxGL = max(grayImage(line1:line2, :), [], 'all')
maxGL = uint8 255
verticalProfile(1 : line1) = maxGL;
verticalProfile(line2 : end) = maxGL;
y = 1 : rows;
subplot(2, 1, 2);
plot(verticalProfile, y, 'b-', 'LineWidth', 2);
grid on;
title('Vertical Profile', 'FontSize',fontSize);
xlabel('Mean Intensity', 'FontSize',fontSize);
ylabel('Row', 'FontSize',fontSize);
%--------------------------------------------------------------------------------------------------------
% Find the first place where the mean drops below 140.
threshold = 140;
topRow = find(verticalProfile < threshold, 1, 'first')
topRow = 313
% Draw a red line at the threshold.
xline(threshold, 'Color', 'r', 'LineWidth', 2)
% Draw a red line going across the average black lines height.
subplot(2, 1, 1);
yline(topRow, 'Color', 'r', 'LineWidth', 2)
% Draw a yellow line there
xMid = columns/2;
line([xMid, xMid], [1, topRow], 'Color', 'y', 'LineWidth', 2);

댓글 수: 3

Marcus Glover
Marcus Glover 2024년 1월 12일
편집: Marcus Glover 2024년 1월 12일
Thanks for the response.
This method of choosing a threshold works well when all the images have the same realtive intensity, but unfortunately that is not always the case. Is there a simple way to determine the threshold value based on each individual image? I'd like to automate this process for many images from many imaging systems.
I've attached three files here where there is not a threshold that would satisfy all cases. Not sure what makes the most sense from here- all I am after is the measurement in yellow. Perhaps some sort of intensity adjustment or normalization?
One thing to try is to find the mean of the first image we used. Then for other images, standardize the intensity by dividing the image by it's mean intensity (to get it to the range 0-1) and then multiply by the intensity of the first image. That way all images should have the same intensity.
Or you could try imhistmatch
Thank you. The mean approach did not work for all cases, but I was able to get things working using imhistmatch. I am using it on the entire image but I may try to crop a smaller section out of thr center of the image and see if that improves the matching.

댓글을 달려면 로그인하십시오.

추가 답변 (0개)

카테고리

도움말 센터File Exchange에서 Matrix Indexing에 대해 자세히 알아보기

제품

릴리스

R2022b

질문:

2024년 1월 4일

댓글:

2024년 1월 18일

Community Treasure Hunt

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

Start Hunting!

Translated by