Problem
Corrosion work at a process plant starts from its P&IDs: the equipment, the lines between it, and what each line carries. Many of those drawings exist only as scans. The aim is a tool that reads them into a connectivity graph. A later application would group the result into corrosion circuits. A vision model that reads P&IDs needs labelled drawings, so the first job is a generator that produces drawings whose labels are known exactly.
Constraints
- Every label has to be exactly right. A wrong box or a port in the wrong place teaches the model the wrong thing.
- Drawings in the field are scanned, skewed and noisy. Training images need the same damage, and the labels have to move with it.
- Whatever reads real drawings has to stay reviewable: an engineer sees the evidence behind each connection, corrects it, and the correction survives the next run.
What I built
A generator that keeps three separate representations of every drawing and never lets them blur together.
The process model is the plant itself: equipment, streams, instruments and control loops, with no coordinates at all. A pump does not know where it is drawn. The diagram model places symbols, pipe runs and labels on the sheet in millimetres and refers back to the process model by ID. The render layer draws a clean raster with Cairo, and the degrade step adds blur, noise and perspective skew.
Two rules keep the labels honest. The extractor that writes the labels uses the same transform chain as the renderer, so a label lands on the ink by construction rather than by coincidence. And every degradation that moves pixels must return a warp map, so the projector can move the labels exactly as far as the ink moved. Entity IDs such as V-1001 stay the same from the process model to the last degraded label. Generation is seeded, and a drawing is rejected outright if it has unintended crossings, overlapping text, invisible symbols or clipping.
How it was verified
Each layer has its own tests. Labels are projected through a known warp and must land within one pixel of where they should. An end-to-end test generates a sample and checks that every ID matches between the clean and degraded labels. Label overlays were checked against the ink by eye.
I also audited the generator against what the model actually needs, and wrote down what it cannot do yet: it draws a single process template, and many of its imported symbols have connection points that sit off the drawn ink.
Outcome
In development. The generator is tested and its labels line up with the drawing, but it does not yet produce enough variety to train on, so it is not used for training until those gaps are fixed and an experiment shows it helps. Results on real drawings are not published here.
Stack
- Python
- pycairo
- NumPy
- Pillow
- pytest