基于Raspberry Pi 4的Python CAPTCHA图像逆扭曲实现求助
Hey Michael, glad to hear manual Photoshop fixes work with Tesseract—let's replicate that automatedly using pure Python tools that play seamlessly with Raspbian, since you're having OpenCV deployment issues. Here's a step-by-step plan:
1. Install Required Libraries
First, make sure you have these lightweight alternatives to OpenCV installed:
Pillow(for image manipulation)numpy(for numerical calculations)pytesseract(for OCR)- Tesseract OCR engine itself
Run these commands in your terminal:
sudo apt update && sudo apt install tesseract-ocr pip install pillow numpy pytesseract
2. Understand the S-Curve Warp Model
Your CAPTCHA uses a horizontal S-shaped warp, which is essentially a sine wave applied to the x-coordinate of each pixel. For a given pixel at (x, y) in the original flat image, the warped position (x', y) would look like:x' = x + A * sin(2πy/H)
Where:
A= amplitude of the warp (how much pixels shift horizontally)H= height of the CAPTCHA image
To reverse this, we calculate the original x-coordinate from the warped one:x = x' - A * sin(2πy/H)
3. Implement the Unwarping Function
Here's a Python script that applies this inverse warp, then passes the flattened image to Tesseract for recognition:
from PIL import Image import numpy as np import pytesseract def unwarp_s_captcha(img_path, warp_amplitude=20): # Load image and convert to grayscale (improves Tesseract accuracy) img = Image.open(img_path).convert('L') img_np = np.array(img) height, width = img_np.shape # Initialize empty array for unwarped image unwarped_img_np = np.full_like(img_np, 255) # Fill background with white # Iterate over each pixel row to apply inverse warp for y in range(height): # Calculate horizontal offset for this row based on sine curve offset = int(warp_amplitude * np.sin(2 * np.pi * y / height)) for x in range(width): # Compute original x-coordinate before warp original_x = x - offset # Only copy pixels that fall within the original image bounds if 0 <= original_x < width: unwarped_img_np[y, x] = img_np[y, original_x] # Convert back to PIL Image unwarped_img = Image.fromarray(unwarped_img_np) return unwarped_img # Example usage if __name__ == "__main__": # Adjust warp_amplitude based on your CAPTCHA's distortion level unwarped_image = unwarp_s_captcha("your_captcha.png", warp_amplitude=18) unwarped_image.save("unwarped_captcha.png") # Configure Tesseract to focus on alphanumeric characters only tesseract_config = "--psm 10 --oem 3 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" captcha_text = pytesseract.image_to_string(unwarped_image, config=tesseract_config) print(f"Recognized CAPTCHA: {captcha_text.strip()}")
4. Fine-Tune for Your CAPTCHA
- Adjust
warp_amplitude: Start with a value between 15-25, then tweak it based on how well the unwarped image looks (openunwarped_captcha.pngto check). If characters are still curved, increase the amplitude; if they're shifted too far, decrease it. - Add Preprocessing: For better Tesseract accuracy, add a binarization step after converting to grayscale:
This turns the image into pure black-and-white, eliminating gray noise.# Add this right after converting to grayscale img = img.point(lambda pixel: 0 if pixel < 127 else 255, '1')
5. Test with Multiple CAPTCHA Samples
Once you have your amplitude dialed in, test the script with your uploaded CAPTCHA examples to ensure consistency. If some samples have slightly different warp intensities, you could add a small adjustment loop to auto-tune the amplitude based on edge detection (using Pillow's edge filters), but the manual tweak should work for most uniform CAPTCHAs.
内容的提问来源于stack exchange,提问作者Michael

