PCBの反りの測定

このアプリケーション例は、という名前のC ++サンプルプログラムとして提供されています。
□ | ソースコードはにあります。 |
□ | サンプル画像はにあります。 |
このプログラムを実行するには、Easy3DとEasyGaugeのライセンスが必要です。
3D PCB Warpageアプリケーションの出力例の表示
キャリブレーションプロセスはこのドキュメントでは説明しません。キャリブレーションが行われ、使用されたメートル単位がmmであると仮定します。

このアプリケーションでは、PCBの反りを測定する方法を示します。
このアプリケーションでは、PCB回帰面が水平に向いているときの最も高い表面点と最も低い表面点の差として反りを定義します。言い換えれば、PCBポイントに平面を当てはめ、上の最高点とこの回帰平面の下の最下点との間の垂直距離を取ります。
このプロセスの主なステップは次のとおりです。
1. | 平均PCB平面の最初の推定値を使用して初期ZMapを作成します。 |
2. | データのフィルタリング: |
□ | 周辺との高さのずれが大きい点を削除します。 |
□ | 残りの点に滑らかなフィルタを適用します。 |
最後のZMapを生成するために、アプリケーションは残った/フィルタリングされたデータを介して回帰平面に適合します。
3. | ZMap上で、アライメントのためにPCBのコーナーを検出します(オプション)。 |
4. | アプリケーションがPCBの反りの計算に使用する最終ZMapを生成します。 |
PCBエッジの(オプションの)アラインメントにより、測定中のPCBの向きに関係なく、結果として得られるZMapが常に同じになります。
さらに、最終的なZMapでは、水平線はPCB回帰平面と平行です。これは、明確に定義された反りの値を持つのに必要です。

5. | キャリブレーションモデル(コード内の)と深度マップ(« »)を使用して、アプリケーションはポイントクラウド(« »)を生成します。 |
別の方法として、ファイルからポイントクラウドを直接ロードすることもできます。
6. | このポイントクラウドでは、アプリケーションは、タイプの平面ファインダオブジェクトを使用して、最大平面を検索することによってPCB平面をローカライズします。湾曲したPCBを処理する時は、平面ファインダオブジェクトによって大きな公差(+/- 1mm)が使用されます。 |
このステップは、タイプのと呼ばれる基準面を生成します。
7. | アプリケーションは、基準面から1mm以上離れた任意のデータ点を切り抜きます。 |
8. | »を使用して、最初のZMap()を生成します。実際、ZMap生成に使用される基準面はの10mm下にあり、ZMapのすべてのピクセル値は正です。これは下の図に示されています。 |
を生成するコードを以下に示します。
// Apply calibration to the depth map, a metric 3D point cloud is generated
E3DDepthMapToPointCloudConverter converter;
converter.SetCalibrationModel(model_);
converter.Convert(dm_, pc_);
// Search for the PCB plane
float maximumDistanceToPlane = 1.0f; // 1.0 mm
E3DPlaneFinder finder(maximumDistanceToPlane); // tolerance for plane search = 1.0 mm
E3DPlane refPlane_1 = finder.Find(pc_); // finds the largest plane in the point cloud
// Crop any point distant from PCB plane
E3DPlaneCropper cropperPCB(refPlane_1); // 'refPlane_1' = ref.plane for the cropper
EPointCloud pcPlaneOnly; // only keep points close to the ref.plane
cropperPCB.Crop(pc_, pcPlaneOnly, EPlaneCropperType_KeepClose, maximumDistanceToPlane);
// ZMap projection of PCB plane, using reference plane and fixed resolution
float zMapPixelSize = 0.050f; // ZMap horizontal resolution: 1 pixel = 50µm = 0.050 mm
float zMapVerticalResolution = 0.001f; // ZMap vertical resol.: 1 gray value = 1µm (= 0.001 mm)
float zMapOffset = 10.0f; // 10 mm
E3DZMapGenerator zmapGenerator;
EZMap16 zmapBeforeAlignment;
zmapGenerator.SetScale(zMapPixelSize); // horizontal resolution = 50µm/pixel
zmapGenerator.SetZScale(zMapVerticalResolution); // vertical resolution = 1 µm/GV
zmapGenerator.SetReferencePlane(refPlane_1 - zMapOffset); // 10mm below refPlane_1
zmapGenerator.SetOrientationVectorMode(EZMapOrientationVectorMode_XAxis);
zmapGenerator.SetExtension(1.f); // add a 1mm 3D extension, create a border around the ZMap
zmapGenerator.Convert(pcPlaneOnly, zmapBeforeAlignment);
int zmapWidth = zmapBeforeAlignment.GetWidth();
int zmapHeight = zmapBeforeAlignment.GetHeight();
次の図は、1ピクセルあたり16ビットの解像度を持つこの最初のZMapを示しています。
ZMap
この画像内では:
□ | 背景画素は値「0」(黒色)を有します。この値は「未定義のピクセル」に予約されています(何も検出されません)。0以外の値を有する画素は「有効画素」です。 |
□ | 水平解像度は50μm/ピクセルに設定され、垂直解像度は1グレー値に対して1μmに設定されます。 |
ZMapの基準面はPCBの10mm下にあるので、画像の平均グレー値は10000(10000グレー値=10000μm)です。
□ | このZMapのサイズは指定されていません。境界ボックスのサイズから自動的に計算され、PCBの周りに黒色の境界線ができるように1mmだけ拡大されます。この拡大は、ZMapジェネレータのメソッドによって指定されます。PCB周りの黒色の境界線は、エッジの検出に役立ちます。 |

Zmapでは、アプリケーションは、反りの計算中に次のポイントを無視する必要があります。
□ | 背景の孤立した騒音ポイント。 |
□ | 穴の内側またはパッド上の騒音ポイント |
アプリケーションはポイントを削除し、残りのポイントのローパスフィルタを適用して低速/大域PCB変形のみを検出します。このフィルタリングは2段階で行われます。
フィルタ1:外れ値を削除する
1. | フィルタは、ZMapの各ピクセルに移動するカーネルウィンドウを定義します。 |
2. | ZMap画像の各画素について、カーネルウインドウはこの画素の中心に置かれ、フィルタ条件は中心画素が保持されるか除去されるかを決定します。 |
ここで使用されるフィルタ条件はです。中央のピクセル値とカーネルウィンドウ内のすべての有効なピクセルの平均とを比較します。
これは下の図に示されています。
アプリケーションは、次のように中心ピクセルを保持または削除する条件を評価します。
□ | ウィンドウに定義されたピクセルの25%未満(コード内のを参照)がある場合、または中心ピクセルが既に定義されていない場合、この中心ピクセルは未定義としてマークされます。 |
□ | アプリケーションは、カーネルウィンドウ内のすべての有効な点に対する中心点の高さの偏差を計算し、その結果の高さの偏差が30μmを超える場合(コード内のを参照)、アプリケーションはカーネルウィンドウの中心にあるピクセルを削除します(実際には0に置き換えられ、「未定義ピクセル」を意味します)。 |
フィルタ2:平均化フィルタを適用する
1. | 第2ステップでは、ランダムノイズを除去するために、平均化フィルタ(ローパス)を適用します。 |
2. | フィルタは、すべてのピクセル上を移動するカーネルウィンドウも定義します。 |
3. | ウィンドウ内に十分な有効ピクセルがある場合(この場合は少なくとも25%)、中心ピクセルが有効な場合、この中心ピクセルはカーネルウィンドウ内のすべてのピクセルの平均で置き換えられます。 |
コードのフィルタリング
Zmapデータのフィルタリングに使用されるコードは次のとおりです。
// Process the ZMap to remove noise and small scale structures
// Filters parameters
int halfKernelSizeFilter = 25; // kernel size = 2 x halfKernelSizeFilter + 1 pixel = 51
float thresholdFilter = 0.030f; // threshold = maximum deviation from mean
float ratioValidPixelsFilter = 0.25f; // requires at least 25% of valid points in the kernel
// Apply noise removal filter
EZMap16 zmapBeforeAlignmentFilter1; // output of the filter
zmapBeforeAlignmentFilter1.SetSize(zmapBeforeAlignment);
Easy3D::RemoveNoise(zmapBeforeAlignment, zmapBeforeAlignmentFilter1,
E3DNoiseRemovalMethod_AbsoluteDifferenceFromMean,
halfKernelSizeFilter, thresholdFilter, ratioValidPixelsFilter, false);
// Apply low-pass filter
EZMap16 zmapBeforeAlignmentFilter2; // output of the second filter
zmapBeforeAlignmentFilter2.SetSize(zmapBeforeAlignment);
Easy3D::ComputeAverageMap(zmapBeforeAlignmentFilter1, zmapBeforeAlignmentFilter2,
halfKernelSizeFilter, ratioValidPixelsFilter);
フィルタリングのさまざまな手順を以下に示します。
Zmapフィルタリングの2つのステップ

このオプションのステップは、PCBの向き(矩形の検出)を見つけることにあります。
このステップをスキップして反りを計算することはできますが、エッジを整列させると、異なるZMapsの比較が容易になります。
PCBエッジ上に整列されたZMapを生成するには:
1. | アプリケーションはZMapを8ビットイメージに変換します。これは、Open eVisionの2Dツールセットを使用するために必要です。 |
2. | EasyGaugeを使用して、ZMapイメージに矩形を当てることによってPCBのエッジを検出します。 |
アプリケーションは、未定義(0)と有効ピクセル(非ゼロ)の間のトランジションを使用して、矩形のエッジの位置を検出します。
ZMapイメージ上に長方形のゲージを使用する方法を以下に示します。
対応するコードは次のとおりです。
// From the ZMap create an 8-bit image for alignment
EImageBW8 imageBeforeAlignment8(zmapWidth, zmapHeight);
// conversion 16-bits to 8-bits
EasyImage::Convert(&zmapBeforeAlignmentFilter2.AsEImage(), &imageBeforeAlignment8);
// Search for the PCB "rectangle" in 8-bits image
float rectangleDimTolerance = 500.f; // 500 pixels tolerance on the rectangle's dimension
ERectangleGauge ERectangleGauge1;
ERectangle measuredRectangle;
ERectangleGauge1.SetTolerance(rectangleDimTolerance);
ERectangleGauge1.SetSize((float)(zmapWidth), (float)(zmapHeight));
ERectangleGauge1.SetThreshold(20);
ERectangleGauge1.SetCenterXY((float)(zmapWidth / 2.0), (float)(zmapHeight / 2.0));
ERectangleGauge1.SetTransitionChoice(ETransitionChoice_NthFromBegin);
ERectangleGauge1.SetTransitionIndex(0); // take the first transition ...
ERectangleGauge1.SetTransitionType(ETransitionType_Bw); // ... from black to white
ERectangleGauge1.SetNumFilteringPasses(10);
ERectangleGauge1.SetFilteringThreshold(5.0f); // threshold = 5 x the mean deviation
ERectangleGauge1.Measure(&imageBeforeAlignment8);
measuredRectangle = ERectangleGauge1.GetMeasuredRectangle();
float rectangleSizeX = ceil(measuredRectangle.GetSizeX()); // will be the width of the final ZMap
float rectangleSizeY = ceil(measuredRectangle.GetSizeY()); // will be the height of the final ZMap
// Store the 3D coordinates of the aligned rectangle corners
EPoint corner_2D[4];
E3DPoint corner_3D[4];
measuredRectangle.GetCorners(corner_2D[0], corner_2D[1], corner_2D[2], corner_2D[3]);
for (int i = 0; i<4; i++)
{
E3DPoint cornerPtZMap;
cornerPtZMap = E3DPoint(corner_2D[i].GetX(), // X pixel position
corner_2D[i].GetY(), // Y pixel position
zMapOffset / zMapVerticalResolution); // = 10000 (height of the ZMap reference plane)
zmapBeforeAlignmentFilter2.PixelToWorld(cornerPtZMap, corner_3D[i]);
}

1. | 十分に定義された基準面(フィルタリングされた点を通る回帰平面と平行)を持つ新しいZMapを作成するために、アプリケーションは平滑化されたZMapからポイントクラウドを生成します。 |
下のコードでは、フィルタリングされたポイントクラウドの名前はです。
// From the filtered ZMap, generate a new 3D point cloud
// Use that point cloud to estimate a better reference plane
EPointCloud filteredPc;
zmapBeforeAlignmentFilter2.ToPointCloud(filteredPc);
E3DPlaneFitter planeFitter;
E3DPlane refPlane_2 = planeFitter.Fit(filteredPc); // find the best fit plane
2. | アプリケーションは、フィルタリングされたデータポイントを介して平面(と呼ばれる最終回帰平面)にフィットします。 |
3. | に非常に近いこの新しい基準面は、反りが計算される最終的なZMapを生成するための新しい«水平»基準です。 |
この平面は、元のデータに見られるノイズや外れ値には敏感ではありません。

1. | アプリケーションは、フィルタリングされたポイントクラウドを使用して最終的なZMapを作成します。 |
この新しいZMapの位置は、以下に基づいています。
□ | 平面から基準平面として10 mmを引いたもの。 |
□ | 基準(左下)コーナーと新しい平行方向(X軸)を決定するためのコーナーの3D位置。コーナー位置を使用して、2つの平面が互いに非常に近いと仮定して、新しいZMapの生成の原点と方向ベクトルを指定します。 |
この整列したZMapを生成するコードは次のとおりです。
// Generate the new ZMap with the filtered data
EZMap16 zmap_;
zmapGenerator.SetOrigin(corner_3D[2]);
zmapGenerator.SetReferencePlane(refPlane_2 - zMapOffset); // refPlane_2 – 10mm
E3DPoint horizDirection(corner_3D[1].X - corner_3D[0].X,
corner_3D[1].Y - corner_3D[0].Y,
corner_3D[1].Z - corner_3D[0].Z);
zmapGenerator.SetOrientationVector(horizDirection);
zmapGenerator.SetResolution((int)rectangleSizeX, (int)rectangleSizeY);
zmapGenerator.SetExtension(0.f); // no border
zmapGenerator.Convert(filteredPc, zmap_);
2. | PCBの反りを計算するには、アプリケーションは整列したZMapから最大高さと最小高さだけを必要とします。 |
クラスの静的メソッドを使用してこれらの値を取得します。
対応するコードは次のとおりです。
// Calculate warpage in metric unit
UINT32 validCount;
float minValue, maxValue, averageValue;
Easy3D::ComputeStatistics(zmap_, validCount, minValue, maxValue, averageValue);
float warpage = maxValue - minValue;
● | サンプルアプリケーションはPCBを3Dで表示し、カラーマップを適用します。 |
● | 3Dビューアは、反りを強調するためにZ軸に10倍の倍率を適用します。 |
得られた深度マップ(反りを示す)とそれに対応する反り測定のサンプル3Dレンダリングを以下に示します。
反り = 0.145 mm
反り = 0.407 mm
反り = 0.620 mm