Spaces:
Sleeping
Sleeping
Upload 5 files
Browse files- .gitattributes +1 -0
- app.py +89 -0
- captcha_model.hdf5 +3 -0
- captcha_solver_hf.py +62 -0
- model_labels.dat +0 -0
- requirements.txt +5 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
| 33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
| 36 |
+
captcha_model.hdf5 filter=lfs diff=lfs merge=lfs -text
|
app.py
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import cv2
|
| 3 |
+
import numpy as np
|
| 4 |
+
from captcha_solver_hf import solve_captcha
|
| 5 |
+
|
| 6 |
+
def predict_captcha(image):
|
| 7 |
+
if image is None:
|
| 8 |
+
return "Please upload an image."
|
| 9 |
+
img_array = np.array(image)
|
| 10 |
+
img_cv = cv2.cvtColor(img_array, cv2.COLOR_RGB2BGR)
|
| 11 |
+
result = solve_captcha(img_cv)
|
| 12 |
+
return result
|
| 13 |
+
|
| 14 |
+
# Example images (replace these with actual CAPTCHA images)
|
| 15 |
+
examples = [
|
| 16 |
+
"example_captcha1.png",
|
| 17 |
+
"example_captcha2.png",
|
| 18 |
+
"example_captcha3.png"
|
| 19 |
+
]
|
| 20 |
+
|
| 21 |
+
css = """
|
| 22 |
+
.gradio-container {
|
| 23 |
+
font-family: 'Arial', sans-serif;
|
| 24 |
+
}
|
| 25 |
+
.gr-button {
|
| 26 |
+
color: white;
|
| 27 |
+
border-color: black;
|
| 28 |
+
background: linear-gradient(45deg, #007bff, #00bcd4);
|
| 29 |
+
}
|
| 30 |
+
.gr-button:hover {
|
| 31 |
+
background: linear-gradient(45deg, #0056b3, #008ba3);
|
| 32 |
+
}
|
| 33 |
+
.gr-form {
|
| 34 |
+
flex-direction: column;
|
| 35 |
+
align-items: center;
|
| 36 |
+
}
|
| 37 |
+
.gr-image-input {
|
| 38 |
+
width: 100% !important;
|
| 39 |
+
max-width: 400px;
|
| 40 |
+
margin: auto;
|
| 41 |
+
}
|
| 42 |
+
.footer {
|
| 43 |
+
margin-top: 20px;
|
| 44 |
+
text-align: center;
|
| 45 |
+
color: #666;
|
| 46 |
+
}
|
| 47 |
+
h1, h3 {
|
| 48 |
+
text-align: center;
|
| 49 |
+
}
|
| 50 |
+
"""
|
| 51 |
+
|
| 52 |
+
with gr.Blocks(css=css) as iface:
|
| 53 |
+
gr.Markdown(
|
| 54 |
+
"""
|
| 55 |
+
# CAPTCHA Solver
|
| 56 |
+
### Unlock the Power of AI-Driven CAPTCHA Recognition
|
| 57 |
+
Upload your CAPTCHA image and let our advanced AI model decipher it instantly!
|
| 58 |
+
"""
|
| 59 |
+
)
|
| 60 |
+
with gr.Column(scale=1):
|
| 61 |
+
input_image = gr.Image(type="numpy", label="Upload CAPTCHA Image")
|
| 62 |
+
output_text = gr.Textbox(label="Predicted Text")
|
| 63 |
+
|
| 64 |
+
solve_button = gr.Button("Solve CAPTCHA", variant="primary")
|
| 65 |
+
solve_button.click(fn=predict_captcha, inputs=input_image, outputs=output_text)
|
| 66 |
+
|
| 67 |
+
gr.Examples(examples, inputs=input_image)
|
| 68 |
+
|
| 69 |
+
gr.Markdown(
|
| 70 |
+
"""
|
| 71 |
+
### How It Works
|
| 72 |
+
1. Upload a CAPTCHA image
|
| 73 |
+
2. Click "Solve CAPTCHA"
|
| 74 |
+
3. Get instant results!
|
| 75 |
+
|
| 76 |
+
Our state-of-the-art AI model processes your image and provides accurate text recognition.
|
| 77 |
+
"""
|
| 78 |
+
)
|
| 79 |
+
|
| 80 |
+
gr.Markdown(
|
| 81 |
+
"""
|
| 82 |
+
<div class="footer">
|
| 83 |
+
Developed with ❤️ by Arnav Agarwal | © 2024 All Rights Reserved
|
| 84 |
+
</div>
|
| 85 |
+
"""
|
| 86 |
+
)
|
| 87 |
+
|
| 88 |
+
if __name__ == "__main__":
|
| 89 |
+
iface.launch()
|
captcha_model.hdf5
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:dbc5e6a8bd85d16acaaede3bc8050c9ff1f9f4ea8c2602f2bee16bc846d5e11a
|
| 3 |
+
size 8045424
|
captcha_solver_hf.py
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import cv2
|
| 3 |
+
import pickle
|
| 4 |
+
from keras.models import load_model
|
| 5 |
+
from helpers import resize_to_fit
|
| 6 |
+
|
| 7 |
+
# Ensure these files are in the same directory as your script
|
| 8 |
+
MODEL_FILENAME = "captcha_model.hdf5"
|
| 9 |
+
MODEL_LABELS_FILENAME = "model_labels.dat"
|
| 10 |
+
|
| 11 |
+
# Load the model and labels
|
| 12 |
+
with open(MODEL_LABELS_FILENAME, "rb") as f:
|
| 13 |
+
lb = pickle.load(f)
|
| 14 |
+
|
| 15 |
+
model = load_model(MODEL_FILENAME)
|
| 16 |
+
|
| 17 |
+
def solve_captcha(image):
|
| 18 |
+
# Convert the image to grayscale
|
| 19 |
+
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
| 20 |
+
|
| 21 |
+
# Add some extra padding around the image
|
| 22 |
+
image = cv2.copyMakeBorder(image, 20, 20, 20, 20, cv2.BORDER_REPLICATE)
|
| 23 |
+
|
| 24 |
+
# Threshold the image
|
| 25 |
+
thresh = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
|
| 26 |
+
|
| 27 |
+
# Find contours
|
| 28 |
+
contours, _ = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
| 29 |
+
|
| 30 |
+
letter_image_regions = []
|
| 31 |
+
|
| 32 |
+
for contour in contours:
|
| 33 |
+
(x, y, w, h) = cv2.boundingRect(contour)
|
| 34 |
+
if w / h > 1.25:
|
| 35 |
+
half_width = int(w / 2)
|
| 36 |
+
letter_image_regions.append((x, y, half_width, h))
|
| 37 |
+
letter_image_regions.append((x + half_width, y, half_width, h))
|
| 38 |
+
else:
|
| 39 |
+
letter_image_regions.append((x, y, w, h))
|
| 40 |
+
|
| 41 |
+
if len(letter_image_regions) != 4:
|
| 42 |
+
return "Error: Could not identify 4 letters in the CAPTCHA"
|
| 43 |
+
|
| 44 |
+
letter_image_regions = sorted(letter_image_regions, key=lambda x: x[0])
|
| 45 |
+
|
| 46 |
+
predictions = []
|
| 47 |
+
|
| 48 |
+
for letter_bounding_box in letter_image_regions:
|
| 49 |
+
x, y, w, h = letter_bounding_box
|
| 50 |
+
letter_image = image[y - 2:y + h + 2, x - 2:x + w + 2]
|
| 51 |
+
letter_image = resize_to_fit(letter_image, 20, 20)
|
| 52 |
+
letter_image = np.expand_dims(letter_image, axis=2)
|
| 53 |
+
letter_image = np.expand_dims(letter_image, axis=0)
|
| 54 |
+
|
| 55 |
+
prediction = model.predict(letter_image)
|
| 56 |
+
letter = lb.inverse_transform(prediction)[0]
|
| 57 |
+
predictions.append(letter)
|
| 58 |
+
|
| 59 |
+
captcha_text = "".join(predictions)
|
| 60 |
+
return captcha_text
|
| 61 |
+
|
| 62 |
+
# We don't need a test function here anymore, as testing will be done through the Gradio interface
|
model_labels.dat
ADDED
|
Binary file (450 Bytes). View file
|
|
|
requirements.txt
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
numpy
|
| 2 |
+
imutils
|
| 3 |
+
sklearn
|
| 4 |
+
tensorflow
|
| 5 |
+
keras
|