基于Python与OpenCV的验证码去噪优化及自动识别技术求助
Hey there! Let's tackle this captcha denoising problem together—since you're new to image processing, I'll break down practical tweaks to your current workflow that should get you closer to usable OCR input.
1. First, Fix Your HSV Masking (The Root of Many Issues)
Your current HSV mask might not be precisely targeting the captcha text's color range, which leads to leftover noise or missing text fragments. Instead of guessing values, use an interactive tool to dial in the perfect H/S/V bounds:
import cv2 import numpy as np def nothing(x): pass # Load your captcha image img = cv2.imread("your_captcha.png") hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # Create a trackbar window to adjust values in real-time cv2.namedWindow("HSV Tuner") cv2.createTrackbar("Hue Min", "HSV Tuner", 0, 179, nothing) cv2.createTrackbar("Hue Max", "HSV Tuner", 179, 179, nothing) cv2.createTrackbar("Sat Min", "HSV Tuner", 0, 255, nothing) cv2.createTrackbar("Sat Max", "HSV Tuner", 255, 255, nothing) cv2.createTrackbar("Val Min", "HSV Tuner", 0, 255, nothing) cv2.createTrackbar("Val Max", "HSV Tuner", 255, 255, nothing) while True: # Get current trackbar values h_min = cv2.getTrackbarPos("Hue Min", "HSV Tuner") h_max = cv2.getTrackbarPos("Hue Max", "HSV Tuner") s_min = cv2.getTrackbarPos("Sat Min", "HSV Tuner") s_max = cv2.getTrackbarPos("Sat Max", "HSV Tuner") v_min = cv2.getTrackbarPos("Val Min", "HSV Tuner") v_max = cv2.getTrackbarPos("Val Max", "HSV Tuner") # Generate mask and preview lower_bound = np.array([h_min, s_min, v_min]) upper_bound = np.array([h_max, s_max, v_max]) mask = cv2.inRange(hsv, lower_bound, upper_bound) masked_img = cv2.bitwise_and(img, img, mask=mask) cv2.imshow("Mask", mask) cv2.imshow("Masked Text", masked_img) # Press 'q' to exit and save your values if cv2.waitKey(1) & 0xFF == ord("q"): break cv2.destroyAllWindows()
Once you find values that isolate the text perfectly, hardcode them into your script—this eliminates most noise right out the gate.
2. Improve Thresholding with Pre-Processing & Morphology
After getting a clean mask, your adaptive threshold can work better with a few extra steps:
- Blur first: Gaussian blur softens tiny noise specks before thresholding
- Tweak adaptive threshold params: Adjust
blockSize(must be odd) andC(the constant subtracted from the mean) to balance noise removal and text integrity - Morphological operations: Erode to wipe small white noise, then dilate to repair any broken text strokes
Here's how to implement this:
# Start with your masked image from step 1 gray = cv2.cvtColor(masked_img, cv2.COLOR_BGR2GRAY) # Apply Gaussian blur to reduce small noise blurred = cv2.GaussianBlur(gray, (3, 3), 0) # Adaptive thresholding (invert if text is dark on light background) thresh = cv2.adaptiveThreshold( blurred, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 11, 2 ) # Clean up with morphology kernel = np.ones((3, 3), np.uint8) # Erode to remove tiny noise dots cleaned = cv2.erode(thresh, kernel, iterations=1) # Dilate to fix any text gaps caused by erosion cleaned = cv2.dilate(cleaned, kernel, iterations=1)
3. Bonus: Filter Noise with Contour Detection
If there's still leftover noise (like thin lines or random dots), use contour analysis to keep only text-shaped regions:
# Find external contours contours, _ = cv2.findContours(cleaned.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # Create a blank image to draw filtered contours filtered = np.zeros_like(cleaned) for cnt in contours: # Keep only contours with area above a threshold (adjust based on your captcha's text size) if cv2.contourArea(cnt) > 20: cv2.drawContours(filtered, [cnt], 0, 255, -1)
This step eliminates any tiny, non-text noise that slipped through the previous filters.
By following these steps—starting with precise color masking, then refining with blur, adaptive thresholding, morphology, and contour filtering—you'll end up with a much cleaner image that OCR tools (like Tesseract) can reliably parse.
内容的提问来源于stack exchange,提问作者Dmitry

