Steve on Image Processing with MATLAB

Image processing concepts, algorithms, and MATLAB

Identifying Border-Touching Objects Using imclearborder or regionprops

I have seen some requests and questions related to identifying objects in a binary image that are touching the image border. Sometimes the question relates to the use of imclearborder, and sometimes the question is about regionprops. Today, I'll show you how to tackle the problem both ways.

Using imclearborder

I'll be using this binary version of the rice.png sample image from the Image Processing Toolbox.
url = "https://blogs.mathworks.com/steve/files/rice-bw-1.png";
A = imread(url);
imshow(A)
The function imclearborder removes all objects touching the border.
B = imclearborder(A);
imshow(B)
That seems to be the opposite of what we want. We can, however, convert this into the desired result by using the MATLAB element-wise logical operators, such as & (and), | (or), and ~ (not). In words, we want the foreground pixels that are in A and are not in B. As a MATLAB expression, it looks like this:
C = A & ~B;
imshow(C)

Using regionprops

The function regionprops can compute all sorts of properties of binary image objects. Here is a simple example that computes the area and centroid of each object in our sample image. I'm using the form of regionprops that returns a table.
props = regionprops("table",A,["Area" "Centroid"])
t = 97×2 table
 AreaCentroid
11385.985535.0870
21216.446362.0579
3672.104585.1940
41784.5056117.5674
51579.4650141.2675
628611.8007168.5350
719512.0872205.2974
81359.4296223.0296
917621.369395.9716
1020824.197126.3125
1119928.185948.2563
1218822.1011122.6011
1321628.2778179.4630
1414328.3427251.9720
My technique for finding border-touching objects with regionprops uses the BoundingBox property, so include that property along with any other properties that you want to measure.
props = regionprops("table",A,["Area" "Centroid" "BoundingBox"])
t = 97×3 table
 AreaCentroidBoundingBox
11385.985535.08700.500022.50001322
21216.446362.05790.500053.50001316
3672.104585.19400.500073.5000423
41784.5056117.56740.5000102.50001028
51579.4650141.26750.5000132.50002016
628611.8007168.53500.5000152.50002633
719512.0872205.29740.5000199.50002412
81359.4296223.02960.5000218.50002010
917621.369395.97169.500086.50002517
1020824.197126.312510.500018.50002616
1119928.185948.256317.500037.50001923
1218822.1011122.601117.5000108.50001029
1321628.2778179.463017.5000166.50002024
1414328.3427251.972018.5000245.50002311
For any particular object, BoundingBox is a four-element vector containing the left, top, width, and height of the bounding box. For example, here is the bounding box of the 20th object:
props.BoundingBox(20,:)
ans = 1×4
35.5000 113.5000 9.0000 28.0000
By comparing these values to the size of the image, we can identify which objects touch the image border.
Start by determining the objects that touch specific borders.
left_coordinate = props.BoundingBox(:,1);
props.TouchesLeftBorder = (left_coordinate == 0.5);
top_coordinate = props.BoundingBox(:,2);
props.TouchesTopBorder = (top_coordinate == 0.5);
right_coordinate = left_coordinate + props.BoundingBox(:,3);
bottom_coordinate = top_coordinate + props.BoundingBox(:,4);
[M,N] = size(A);
props.TouchesRightBorder = (right_coordinate == (N+0.5));
props.TouchesBottomBorder = (bottom_coordinate == (M+0.5))
t = 97×7 table
 AreaCentroidBoundingBoxTouchesLeftBorderTouchesTopBorderTouchesRightBorderTouchesBottomBorder
11385.985535.08700.500022.500013221000
21216.446362.05790.500053.500013161000
3672.104585.19400.500073.50004231000
41784.5056117.56740.5000102.500010281000
51579.4650141.26750.5000132.500020161000
628611.8007168.53500.5000152.500026331000
719512.0872205.29740.5000199.500024121000
81359.4296223.02960.5000218.500020101000
917621.369395.97169.500086.500025170000
1020824.197126.312510.500018.500026160000
1119928.185948.256317.500037.500019230000
1218822.1011122.601117.5000108.500010290000
1321628.2778179.463017.5000166.500020240000
1414328.3427251.972018.5000245.500023110001
Finally, compute whether objects touch any border using |, the element-wise OR operator.
props.TouchesAnyBorder = props.TouchesLeftBorder | ...
props.TouchesTopBorder | ...
props.TouchesRightBorder | ...
props.TouchesBottomBorder
t = 97×8 table
 AreaCentroidBoundingBoxTouchesLeftBorderTouchesTopBorderTouchesRightBorderTouchesBottomBorderTouchesAnyBorder
11385.985535.08700.500022.5000132210001
21216.446362.05790.500053.5000131610001
3672.104585.19400.500073.500042310001
41784.5056117.56740.5000102.5000102810001
51579.4650141.26750.5000132.5000201610001
628611.8007168.53500.5000152.5000263310001
719512.0872205.29740.5000199.5000241210001
81359.4296223.02960.5000218.5000201010001
917621.369395.97169.500086.5000251700000
1020824.197126.312510.500018.5000261600000
1119928.185948.256317.500037.5000192300000
1218822.1011122.601117.5000108.5000102900000
1321628.2778179.463017.5000166.5000202400000
1414328.3427251.972018.5000245.5000231100011
I'll finish with a quick visual sanity check of the results.
L = bwlabel(A);
L_touches_border = ismember(L,find(props.TouchesAnyBorder));
imshowpair(A,L_touches_border)
|
  • print

评论

要发表评论,请点击 此处 登录到您的 MathWorks 帐户或创建一个新帐户。