Detecting a rectangular reference panel in the image

I am trying to calibrate some hyperspectral images of a farm field. As part of the process, I need to detect the reference reflectance panel in the RGB image that I construct from three hyperspectral bands:
I need to extract the rectangular panel (which is composed of four smaller rectangles). I am wondering what would be the best way to achieve this? I tried the color thresholding technique but since the thresholds might vary from one image to another, I couldn't get a universal answer.

 采纳的回答

Why would the threshold change? Do you have gray background? If all your backgrounds are colored, I'd just convert to HSV, then threshold the S channel at about 0.25 to get the gray stuff. Take the largest blob, or the blob at the center (if that is where it always is). Then get the histogram of the rectangle to find the 4 intensity levels if you need them. Shouldn't be hard at all. Show me the code from the Color Thresholder app that you exported.

3 个评论

Thanks for your reply. Yes, the background is colored. I should say that I was using the same idea of converting to HSV. I went back and found out that the threshold for the S that I was using was a bit high (0.265) and I tuned it to 0.245. I am attaching the whole image here for the reference (there are two reference panels in the image). I Apply the following mask (which is auto generated by the Image Thresholder):
function [BW,maskedRGBImage] = createMask_new(RGB)
% Convert RGB image to chosen color space
I = rgb2hsv(RGB);
% Define thresholds for channel 1 based on histogram settings
channel1Min = 0.877;
channel1Max = 0.889;
% Define thresholds for channel 2 based on histogram settings
channel2Min = 0.000;
channel2Max = 0.245;
% Define thresholds for channel 3 based on histogram settings
channel3Min = 0.172;
channel3Max = 1.000;
% Create mask based on chosen histogram thresholds
sliderBW = ( (I(:,:,1) >= channel1Min) | (I(:,:,1) <= channel1Max) ) & ...
(I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
(I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
BW = sliderBW;
% Initialize output masked image based on input image.
maskedRGBImage = RGB;
% Set background pixels where BW is false to zero.
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;
end
Since some undesired regions still remain after masking, I filter the panels by searching for the approximate area and the ratio of the MinorAxisLength to MajorAxisLength:
sw_BW = createMask_new(sw_rgb);
sw_prpt = regionprops(sw_BW,'Area','MajorAxisLength','MinorAxisLength');
areas = sortrows([[sw_prpt.Area]' ...
[sw_prpt.MinorAxisLength]'./[sw_prpt.MajorAxisLength]'],'descend');
area_idx = find(areas(:,1)>8000 & areas(:,1)<14000 & areas(:,2)>0.5);
After masking each reference panel, I find the smaller rectangles by segmentation using "imsegkmeans".
So far this is giving me reasonable results (I should pray for not having any surprises in the future images).
I didn't try it but if you just want to get the largest blob, use bwareafilt(). If it's not the largest, then maybe it has the highest solidity so ask regionprops for Solidity, which will be 1 for convex objects, like a rectangle, and less than 1 for irregularly-shaped regions.
Thanks for your suggestions. Since a fixed threshold for S channel did not work for all images that I had, I ended up with applying a range of thresholds and screening the area, solidity, and perimeter to filter out panels.

请先登录,再进行评论。

更多回答(0 个)

产品

版本

R2020b

Community Treasure Hunt

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

Start Hunting!

Translated by