# mmdholecenter
Hole center misalignment in PCB.

## Description

This demonstration illustrates the estimation of the eccentricity of the holes on the pads of a PCB, and the estimation of the narrowest copper around the holes.

## Demo Script

### Reading

The image of the PCB is read.

    >>> a = mmreadgray('pcbholes.tif')

    >>> mmshow(a)

a |

### First, find center of the pads.

Use the close hole function to remove the holes. Note that one hole is open. This is not considered in this experiment. The regional maxima of the distance transform gives the radius of the largest disk inside the pad. We are interested only in radius larger than 20 pixels.

    >>> b = mmclohole(a)

    >>> mmshow(b)

    >>> d = mmdist(b,mmsecross(),'EUCLIDEAN')

    >>> e = mmregmax(d,mmsebox())

    >>> f = mmthreshad(d, uint16([20]))   # radius larger than 20 pixels

    >>> g = mmintersec(e,f)

    >>> h = mmblob(mmlabel(g,mmsebox()),'CENTROID'); # pad center

    >>> mmshow(b,mmdil(h))

b | b,mmdil(h) |

### Find the center of the holes

The holes are given by the difference of the pad image from the original image. Repeat the same procedure to find the center of the pads to find now the center of the holes.

    >>> i = mmsubm(b,a)

    >>> mmshow(i)

    >>> j = mmdist(i,mmsecross(),'EUCLIDEAN')

    >>> k = mmregmax(j,mmsebox())

    >>> l = mmblob(mmlabel(k,mmsebox()),'CENTROID') # hole center

    >>> mmshow(i,mmdil(l))

i | i,mmdil(l) |

### Show the eccentricity

First both centers (pads and holes) are displayed together. Then the actual misalignment is computed using the distance from one point to the other.

    >>> from Numeric import nonzero

    >>> mmshow(a,h,l)

    >>> m = mmdist(mmneg(l),mmsecross(),'EUCLIDEAN')

    >>> n = mmintersec(mmgray(h),uint8(m))

    >>> mmshow(n,a)

    >>> i = nonzero(n.flat)

    >>> x = i / n.shape[1]

    >>> y = i % n.shape[1]

    >>> for k in range(len(i)):
      print 'displacement of %d at (%d,%d)\n' %(n[x[k],y[k]],x[k],y[k])

    displacement of 3 at (43,88)
    displacement of 8 at (44,191)
    displacement of 6 at (153,187)

a,h,l | n,a |

### Find the narrowest region around the holes

First, the thinning to compute the skeleton of the PCB image, then remove iteratively all the end points of the skeleton so just the skeleton loop around the holes remains. Find the minimum distance of these loops to the border and display their location.

    >>> o=mmthin(a)

    >>> p=mmthin(o,mmendpoints())

    >>> mmshow(a,p)

    >>> q = mmdist(a,mmsecross(),'EUCLIDEAN')

    >>> r = mmgrain(mmlabel(p,mmsebox()),q,'min') # minimum

    >>> s = mmgrain(mmlabel(p,mmsebox()),q,'min','data') # minimum

    >>> from Numeric import ravel

    >>> for k in ravel(s):
      print 'Minimum distance: %d pixels' %(2*k+1)

    Minimum distance: 7 pixels
    Minimum distance: 7 pixels
    Minimum distance: 3 pixels

    >>> t = mmintersec(mmcmp(r,'==',q),a)

    >>> mmshow(a,mmdil(t))

a,p | a,mmdil(t) |

[`mmdgear`] [Up] [`mmdleaf`] |
Copyright (c) 2003, Roberto A. Lotufo, UNICAMP-University of Campinas; Rubens C. Machado, CenPRA-Renato Archer Research Center.