从图像中自动选择方形斑点区域:计算机视觉
Auto selecting square blob area from image : Computer Vision
我正在尝试开发自动校准插件,为此我需要图像中心斑点的平均像素值。截至目前,我正在将此图像转换为二进制,并能够识别图像中的不同斑点。
但是,我希望以某种方式识别中心 blob。也许我们可以借助周围的 6 个小斑点。
原图:https://drive.google.com/open?id=0B9kvfpiOcM1EWnhJeGtBZ3A4eTg
Matlab代码:
I = imread('BLOB.TIF');
Ibw = ~im2bw(I, 0.75);
Ifill = imfill(Ibw,'holes');
Iarea = bwareaopen(Ifill, 500);
stat = regionprops(Ifinal,'boundingbox');
imshow(I); hold on;
for cnt = 1 : numel(stat)
bb = stat(cnt).BoundingBox;
rectangle('position',bb,'edgecolor','r','linewidth',2);
end
您的结果非常接近。在执行转换为二进制、阈值化并执行区域打开后,您将得到此图像:
沿像素边界的像素仍然存在。您可以使用 imclearborder
函数删除接触边框的像素。为了绝对确定,使用 8-connectedness 以便它在所有 8 个方向上搜索像素。默认是使用 4-connectedness,即仅北、南、东和西:
Iclear = imclearborder(Iarea, 8);
我们现在得到这张图片:
我们快完成了。您希望检测到整个斑点,而不仅仅是斑点的不同部分。我建议您做的是使用形态闭合运算符来填补所有空白。使用相当大的结构元素以确保填补空白。大小为 50 x 50 的正方形结构元素应该可以工作。使用imclose
in conjunction with strel
指定结构元素:
se = strel('square', 50);
out = imclose(Iclear, se);
我们现在得到:
我们现在可以使用上面的图像作为遮罩,通过将遮罩和图像相乘来遮罩除您感兴趣的斑点之外的所有图像。您还可以使用掩码直接索引图像并将不属于掩码的像素设置为 0。让我们选择第二个选项。先复制图片,再做索引:
filt = I;
filt(~out) = 0;
imshow(filt);
我们现在得到:
它并不完美,但它是一个好的开始。您可能需要稍微调整参数以使其更好。
祝你好运!
这是一个非常不适定的问题。您和其他答案都对您在自动校准期间拍摄的此类图像的性质做出了非常具体的假设。由于这些没有明确定义,我们只能假设我们认为合理的任何东西。
例如,我的回答假设您拍摄的任何此类图像中定义最明确的水平线将位于您放置在那里的对象上,或者作为顶部的阴影,或者对象背景和对象之间的线大广场。它还假定中心大方块的顶线将是您在图像中找到的第二长连续水平线(除了对象的底部边界和大方块的下线)。最后我假设视角不会改变太多。
在每一步之后经常使用 imagesc() 来了解发生了什么,否则这个答案将需要 50 页。
% Normalize Image
image = double(BLOB);
image = (image - min(image(:)))*255/(max(image(:))-min(image(:)));
% Find Strong Horizontal Lines
Gy = imfilter(image,[-1 0 1]','replicate');
HH = abs(Gy)>prctile(abs(Gy(:)),95);
% Find the 10 Largest Lines
CC = bwconncomp(HH);
LengthList=sort(cellfun(@length,CC.PixelIdxList)','descend');
Lines = bwareaopen(HH,LengthList(10));
CC2 = bwconncomp(Lines);
这是线路:
Need Reputation to Put Images...
% Get Coordinates of Every Point in the 10 Largest Lines
[y x] = cellfun(@(X) ind2sub(size(Lines),X) ,CC2.PixelIdxList,'UniformOutput',false);
% Find Descriptive Parameters of Each Line
minx = cell2mat(cellfun(@min ,x,'UniformOutput',false))';
maxx = cell2mat(cellfun(@max ,x,'UniformOutput',false))';
miny = cell2mat(cellfun(@min ,y,'UniformOutput',false))';
maxy = cell2mat(cellfun(@max ,y,'UniformOutput',false))';
meanx = mean([minx maxx],2);
% Find the Horizontal Length of Each Line
LineLengths = maxx-minx;
% Find the Pair of 2 Second Largest Lines - The Top and Bottom Border of
% the Square
SecondLongestLineUpperBound = max(LineLengths)-0.2*max(LineLengths);
SecondLongestLineLowerBound = max(LineLengths)/3;
SquareBorderIndx = find(LineLengths>=SecondLongestLineLowerBound & LineLengths<=SecondLongestLineUpperBound);
% Make Sure First of the Pair is the Lower Line
[~,OrderedIndx] = sort(maxy(SquareBorderIndx));
SquareBorderIndx = SquareBorderIndx(OrderedIndx);
% Draw a Small Rectangle in the ROI and Get the ROI
DD =zeros(size(Lines));
DD(maxy(SquareBorderIndx(1)):miny(SquareBorderIndx(2)),meanx(SquareBorderIndx(1))-LineLengths(SquareBorderIndx(1))/5:meanx(SquareBorderIndx(2))+LineLengths(SquareBorderIndx(2))/5)=1;
ROI = double(BLOB).*DD;
这是投资回报率:
Need Reputation to Put Images...
% Find Mean Intensity In the ROI
Result = mean(ROI(ROI(:)>0));
Result =
4.3598e+04
但是,我希望以某种方式识别中心 blob。也许我们可以借助周围的 6 个小斑点。
原图:https://drive.google.com/open?id=0B9kvfpiOcM1EWnhJeGtBZ3A4eTg
Matlab代码:
I = imread('BLOB.TIF');
Ibw = ~im2bw(I, 0.75);
Ifill = imfill(Ibw,'holes');
Iarea = bwareaopen(Ifill, 500);
stat = regionprops(Ifinal,'boundingbox');
imshow(I); hold on;
for cnt = 1 : numel(stat)
bb = stat(cnt).BoundingBox;
rectangle('position',bb,'edgecolor','r','linewidth',2);
end
您的结果非常接近。在执行转换为二进制、阈值化并执行区域打开后,您将得到此图像:
沿像素边界的像素仍然存在。您可以使用 imclearborder
函数删除接触边框的像素。为了绝对确定,使用 8-connectedness 以便它在所有 8 个方向上搜索像素。默认是使用 4-connectedness,即仅北、南、东和西:
Iclear = imclearborder(Iarea, 8);
我们现在得到这张图片:
我们快完成了。您希望检测到整个斑点,而不仅仅是斑点的不同部分。我建议您做的是使用形态闭合运算符来填补所有空白。使用相当大的结构元素以确保填补空白。大小为 50 x 50 的正方形结构元素应该可以工作。使用imclose
in conjunction with strel
指定结构元素:
se = strel('square', 50);
out = imclose(Iclear, se);
我们现在得到:
我们现在可以使用上面的图像作为遮罩,通过将遮罩和图像相乘来遮罩除您感兴趣的斑点之外的所有图像。您还可以使用掩码直接索引图像并将不属于掩码的像素设置为 0。让我们选择第二个选项。先复制图片,再做索引:
filt = I;
filt(~out) = 0;
imshow(filt);
我们现在得到:
它并不完美,但它是一个好的开始。您可能需要稍微调整参数以使其更好。
祝你好运!
这是一个非常不适定的问题。您和其他答案都对您在自动校准期间拍摄的此类图像的性质做出了非常具体的假设。由于这些没有明确定义,我们只能假设我们认为合理的任何东西。
例如,我的回答假设您拍摄的任何此类图像中定义最明确的水平线将位于您放置在那里的对象上,或者作为顶部的阴影,或者对象背景和对象之间的线大广场。它还假定中心大方块的顶线将是您在图像中找到的第二长连续水平线(除了对象的底部边界和大方块的下线)。最后我假设视角不会改变太多。
在每一步之后经常使用 imagesc() 来了解发生了什么,否则这个答案将需要 50 页。
% Normalize Image
image = double(BLOB);
image = (image - min(image(:)))*255/(max(image(:))-min(image(:)));
% Find Strong Horizontal Lines
Gy = imfilter(image,[-1 0 1]','replicate');
HH = abs(Gy)>prctile(abs(Gy(:)),95);
% Find the 10 Largest Lines
CC = bwconncomp(HH);
LengthList=sort(cellfun(@length,CC.PixelIdxList)','descend');
Lines = bwareaopen(HH,LengthList(10));
CC2 = bwconncomp(Lines);
这是线路:
Need Reputation to Put Images...
% Get Coordinates of Every Point in the 10 Largest Lines
[y x] = cellfun(@(X) ind2sub(size(Lines),X) ,CC2.PixelIdxList,'UniformOutput',false);
% Find Descriptive Parameters of Each Line
minx = cell2mat(cellfun(@min ,x,'UniformOutput',false))';
maxx = cell2mat(cellfun(@max ,x,'UniformOutput',false))';
miny = cell2mat(cellfun(@min ,y,'UniformOutput',false))';
maxy = cell2mat(cellfun(@max ,y,'UniformOutput',false))';
meanx = mean([minx maxx],2);
% Find the Horizontal Length of Each Line
LineLengths = maxx-minx;
% Find the Pair of 2 Second Largest Lines - The Top and Bottom Border of
% the Square
SecondLongestLineUpperBound = max(LineLengths)-0.2*max(LineLengths);
SecondLongestLineLowerBound = max(LineLengths)/3;
SquareBorderIndx = find(LineLengths>=SecondLongestLineLowerBound & LineLengths<=SecondLongestLineUpperBound);
% Make Sure First of the Pair is the Lower Line
[~,OrderedIndx] = sort(maxy(SquareBorderIndx));
SquareBorderIndx = SquareBorderIndx(OrderedIndx);
% Draw a Small Rectangle in the ROI and Get the ROI
DD =zeros(size(Lines));
DD(maxy(SquareBorderIndx(1)):miny(SquareBorderIndx(2)),meanx(SquareBorderIndx(1))-LineLengths(SquareBorderIndx(1))/5:meanx(SquareBorderIndx(2))+LineLengths(SquareBorderIndx(2))/5)=1;
ROI = double(BLOB).*DD;
这是投资回报率:
Need Reputation to Put Images...
% Find Mean Intensity In the ROI
Result = mean(ROI(ROI(:)>0));
Result =
4.3598e+04