An OpenCV preprocessing pipeline for automated print inspection
From raw frame to clean part crop
cv2.threshold after a Gaussian blur separates the two reliably. Morphological open removes specks, close fills holes, and the largest contour gives the bounding box of the part. Cropping to that box throws away everything that is not the part — the single biggest robustness win in the whole pipeline.CLAHE plus adaptive threshold beats global thresholding
cv2.adaptiveThreshold then binarizes the print using each pixel's own neighbourhood instead of one global value. A medianBlur in between removes salt noise without eating edges. The result is a stable black-and-white image of the marking, almost independent of ambient light — exactly the input the template matcher needs.Six parameters, tuned from the GUI
config.json and are adjusted with sliders over the live camera image, so a line operator can re-tune the station for a new product in minutes, without touching a single line of code or redeploying anything.A snippet from the implementation
Straight from the example as deployed on the Raspberry Pi + USB camera — copy it freely:
def synthetic_image():
"""Generates a light 'part' on a dark background with a silkscreen print."""
img = np.full((480, 640, 3), 25, np.uint8) # dark background
cv2.rectangle(img, (180, 120), (460, 360), (190, 190, 190), -1) # part
cv2.putText(img, "IS-42", (230, 260), cv2.FONT_HERSHEY_SIMPLEX,
1.6, (40, 40, 40), 4) # silkscreen
noise = np.random.randint(0, 18, img.shape, np.uint8) # camera noise
return cv2.add(img, noise)The full example is a complete program — wiring header, setup and main loop — ready to adapt to your application.
Frequently asked questions
Why not just compare the raw camera images directly?
Raw frames change with lighting, part position and camera noise. Comparing binarized, cropped prints makes the verdict depend on the marking itself, which is what you actually want to inspect.
Is a Raspberry Pi fast enough for this pipeline?
Yes. All stages are standard OpenCV operations on a small cropped region; a Raspberry Pi 4 processes a part in well under a second, which fits typical manual-feed station rates.
What camera settings matter most?
Fixed manual focus and constant exposure. Autofocus hunting between parts is the main source of inconsistent binarization, so the deployment locks focus via V4L2 and stores it in the config file.