Skip to Main Content Skip to Search
File Exchange
MATLAB Newsgroup
Link Exchange
  Blogs  
 Contest 
MathWorks.com

Steve on Image Processing

November 27th, 2007

General connectivity

The notion of neighbor connectivity is discussed in most image processing textbooks. Specifically, what is the set of neighbors of a pixel? For example, a commonly-used neighborhood connectivity is 4-connected, where each pixel has four neighbors. The neighborhood looks like this:

   1
 1 1 1
   1

Another common connectivity is 8-connected, where each pixel has eight neighbors. The neighborhood looks like this:

 1 1 1
 1 1 1
 1 1 1

Many Image Processing Toolbox functions depend on a definition of connectivity. Most of these functions allow you to specify the desired connectivity in a very general, flexible way.

Consider bwperim. This function computes perimeter pixels by finding the foreground pixels that are connected to background pixels. Some definition of connectivity is therefore required. Let's look at an example.

bw = [ 0     0     0     0     0     0     0
       0     0     1     1     1     0     0
       0     1     1     1     1     1     0
       0     1     1     1     1     1     0
       0     1     1     1     1     1     0
       0     0     1     1     1     0     0
       0     0     0     0     0     0     0 ];

Find the foreground pixels that are 4-connected to the background.

perim4 = bwperim(bw, 4)
perim4 =

     0     0     0     0     0     0     0
     0     0     1     1     1     0     0
     0     1     0     0     0     1     0
     0     1     0     0     0     1     0
     0     1     0     0     0     1     0
     0     0     1     1     1     0     0
     0     0     0     0     0     0     0

Now find the foreground pixels that are 8-connected to the background.

perim8 = bwperim(bw, 8)
perim8 =

     0     0     0     0     0     0     0
     0     0     1     1     1     0     0
     0     1     1     0     1     1     0
     0     1     0     0     0     1     0
     0     1     1     0     1     1     0
     0     0     1     1     1     0     0
     0     0     0     0     0     0     0

In addition to specifying connectivity as "4" or "8", you can also use a 3-by-3 matrix of 0s and 1s to specify other kinds of connectivity. The 3-by-3 connectivity matrix below says that a pixel has only two neighbors: The pixel above and the pixel below.

conn2 = [ 0 1 0
          0 1 0
          0 1 0 ];

perim2 = bwperim(bw, conn2)
perim2 =

     0     0     0     0     0     0     0
     0     0     1     1     1     0     0
     0     1     0     0     0     1     0
     0     0     0     0     0     0     0
     0     1     0     0     0     1     0
     0     0     1     1     1     0     0
     0     0     0     0     0     0     0

Note that the (4,2) and (4,6) pixels are not considered to be perimeter pixels with this connectivity. That's because their upper and lower neighbors are both part of the foreground, not the background.

Sometimes it's useful to define 6-connectivity. There are two different flavors, both of which can be expressed using the 3-by-3 matrix form:

conn6a = [ 1 1 0
           1 1 1
           0 1 1 ];

conn6b = [ 0 1 1
           1 1 1
           1 1 0 ];

For processing three-dimensional arrays, you specify 6-connectivity (face-adjacent pixels), 18-connectivity (face- or edge-adjacent pixels), or 26-connectivity (face-, edge-, or vertex-adjacent pixels). But you can specify your own flavor of connectivity by using a 3-by-3-by-3 matrix. Here's an example.

bw_3d = false(5,5,3);
bw_3d(2:4,2:4,:) = true;

% Label three-dimensional connected components.
L1 = bwlabeln(bw_3d)
L1(:,:,1) =

     0     0     0     0     0
     0     1     1     1     0
     0     1     1     1     0
     0     1     1     1     0
     0     0     0     0     0


L1(:,:,2) =

     0     0     0     0     0
     0     1     1     1     0
     0     1     1     1     0
     0     1     1     1     0
     0     0     0     0     0


L1(:,:,3) =

     0     0     0     0     0
     0     1     1     1     0
     0     1     1     1     0
     0     1     1     1     0
     0     0     0     0     0

There's only one three-dimensional connected component. But that's using the default connectivity. Let's define a three-dimensional connectivity such that each pixel has neighbors only in the same plane.

conn_3d = cat(3, zeros(3,3), ones(3,3), zeros(3,3))
conn_3d(:,:,1) =

     0     0     0
     0     0     0
     0     0     0


conn_3d(:,:,2) =

     1     1     1
     1     1     1
     1     1     1


conn_3d(:,:,3) =

     0     0     0
     0     0     0
     0     0     0

L2 = bwlabeln(bw_3d, conn_3d)
L2(:,:,1) =

     0     0     0     0     0
     0     1     1     1     0
     0     1     1     1     0
     0     1     1     1     0
     0     0     0     0     0


L2(:,:,2) =

     0     0     0     0     0
     0     2     2     2     0
     0     2     2     2     0
     0     2     2     2     0
     0     0     0     0     0


L2(:,:,3) =

     0     0     0     0     0
     0     3     3     3     0
     0     3     3     3     0
     0     3     3     3     0
     0     0     0     0     0

Now there are three connected components, one in each plane of the array.

The Image Processing Toolbox functions bwlabel, bweuler, bwboundaries, and bwtraceboundary can accept either 4 or 8 connectivity.

The toolbox functions bwareaopen, bwlabeln, bwperim, bwulterode, imclearborder, imextendedmax, imextendedmin, imhmax, imhmin, imimposemin, imreconstruct, imregionalmax, imregionalmin, and watershed can all accept general 3-by-3 (or higher dimensional) connectivity matrices.

Have you used this general connectivity capability before? If so, I'd like to hear about it.


Get the MATLAB code

Published with MATLAB® 7.5

5 Responses to “General connectivity”

  1. Harun Koku replied on :

    Hi Steve,

    Thanks for the great blog, and hope you keep this up. I have a question about the bwperim - connectivity example here. When I try this simple code:

    conn1 = 4
    A = [0 0 1 1 1 1 1 0 0
    0 0 1 1 1 1 1 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0]
    B = bwperim(A,conn1)

    I get the resulting perim matrix B:
    B =

    0 0 1 1 1 1 1 0 0
    0 0 1 1 1 1 1 0 0
    0 0 0 0 0 0 0 0 0
    0 0 0 0 0 0 0 0 0

    Ideally A(1,4), A(1,5) and A(1,6) shouldn’t be perimeter pixels. Is there some way to get the right perimeter? Thanks in advance!

  2. Steve replied on :

    Harun—There is an implicit assumption in bwperim that pixels “outside” the image are background pixels. That’s why A(1,4:6) are identified as perimeter pixels. You could get your desired result by prepadding the boundary with ones using padarray.

  3. Harun replied on :

    Tried it and works like a charm. But there’s the additional hassle of removing the pads once bwperim does its work, hope this can be addressed in future versions. Thanks a lot Steve!

  4. dave replied on :

    hey Steve,

    thanks for your great blog. i had a question extending the general connectivity (perhaps we could call it specific connectivity?:)

    can you think of a way to extend bwperim (or any function or set of functions) to connect open objects, such as the incomplete perimeters of circles? for example, let’s say i have the following matrix, and i want to complete the circle… perhaps by recursively checking for 8-pixel connectivity. any ideas?

    circperim = bwperim(fspecial(’disk’,8)>0);
    circperim(1:5,1:5) = zeros(5);
    imshow(circperim);

    0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
    0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
    1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
    0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
    0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
    0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0
    0 0 0 1 1 0 0 0 0 0 0 0 1 1 0 0 0
    0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0

    thanks!

    dave

  5. Steve replied on :

    Dave—I think you’re pushing the idea of pixel connectivity way past where it was meant to go. :-) You might try using a Hough circle detection algorithm. Some of these do a good job detecting partial circles. Once you have the center and radius, you can fill in the perimeter pixels.

Leave a Reply


Steve Eddins manages the Image & Geospatial development team at The MathWorks and coauthored Digital Image Processing Using MATLAB. He writes here about image processing concepts, algorithm implementations, and MATLAB.

  • Mikr: I look for answers before asking people… “But we still can’t see the coordinates!...
  • Steve: Mikr—You might want to take a look at the Getting Started section of the MATLAB documentation in order...
  • Mikr: thanks but is it possible to see and write to file (Excel ?) that matrix of pixel coordinates ? instead of...
  • Steve: Mikr—An image in MATLAB is simply a matrix of pixel values. It can be saved (exported) to several common...
  • Mikr: thanks, Steve just started to learn matlab and to clarify matlab saves image files as a matrix of pixel...
  • Steve: Mikr—As far as I know, the commonly used image file formats such as TIFF, JPEG, PNG, etc., do not...
  • Mikr: how to write pixel coordinates in file ?
  • Steve: M.S.—Code for the bwtraceboundaries function ships with the Image Processing Toolbox.
  • M.S.Cheema: i need to know the detailed algorithm for bwtraceboundaries. i want how that function works. so please...
  • Steve: Wagas—It depends on how much memory you have on your computer. You should be able to load a 94 MB TIFF...

These postings are the author's and don't necessarily represent the opinions of The MathWorks.

Related Topics