# Demo iadholecenter

namespace: morph iadholecenter

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.

# Script

## Reading

The image of the PCB is read.

```1. a = mmreadgray('pcbholes.tif')
2. mmshow(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.

```01. from ia870 import iaclohole
02. from ia870 import iadist
03. from ia870 import iasecross
04. from ia870 import iaregmax
05. from ia870 import iasebox
06. from ia870 import iathreshad
07. from ia870 import iaintersec
08. from ia870 import iablob
09. from ia870 import ialabel
10. from ia870 import iadil
11.
12.
13. b = iaclohole(a)
14. mmshow(b)
15. d = iadist(b,iasecross(),'EUCLIDEAN')
16. e = iaregmax(d,iasebox())
17. f = iathreshad(d, uint16([20]))   # radius larger than 20 pixels
18. g = iaintersec(e,f)
19. h = iablob( ialabel(g,iasebox()),'CENTROID'); # pad center
20. mmshow(b,iadil(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.

```1. from ia870 import iasubm
2.
3.
4. i = iasubm(b,a)
5. mmshow(i)
6. j = iadist(i,iasecross(),'EUCLIDEAN')
7. k = iaregmax(j,iasebox())
8. l = iablob( ialabel(k,iasebox()),'CENTROID') # hole center
9. mmshow(i,iadil(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.

```01. from ia870 import ianeg
02. from ia870 import iagray
03.
04.
05. mmshow(a,h,l)
06. m = iadist( ianeg(l),iasecross(),'EUCLIDEAN')
07. n = iaintersec( iagray(h),uint8(m))
08. mmshow(n,a)
09. i = nonzero(n.flat)
10. if type(i) == type(()):
11.     i = i[0]        # numarray nonzero returns tuple
12. x = i / n.shape[1]
13. y = i % n.shape[1]
14. for k in range(len(i)):
15.     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)
```

## 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.

```01. from ia870 import iathin
02. from ia870 import iaendpoints
03. from ia870 import iagrain
04. from ia870 import iacmp
05.
06.
07. o=iathin(a)
08. p=iathin(o,iaendpoints())
09. mmshow(a,p)
10. q = iadist(a,iasecross(),'EUCLIDEAN')
11. r = iagrain( ialabel(p,iasebox()),q,'min') # minimum
12. s = iagrain( ialabel(p,iasebox()),q,'min','data') # minimum
13. for k in ravel(s):
14.   print 'Minimum distance: %d pixels' %(2*k+1)
15. t = iaintersec( iacmp(r,'==',q),a)
16. mmshow(a,iadil(t))```
```Minimum distance: 7 pixels
Minimum distance: 7 pixels
Minimum distance: 3 pixels
```