Upload folder using huggingface_hub
Browse files- README.md +91 -91
- app.py +86 -167
- deploy_to_hf.py +0 -1
- requirements.txt +2 -5
README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
emoji: 🎲
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: red
|
|
@@ -7,120 +7,120 @@ sdk: gradio
|
|
| 7 |
sdk_version: 4.19.2
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
|
|
|
| 10 |
---
|
| 11 |
|
| 12 |
-
#
|
| 13 |
|
| 14 |
-
This is a deep learning model that can recognize and analyze Rubik's cubes in images. The model is built using TensorFlow
|
| 15 |
|
| 16 |
-
## Features
|
| 17 |
|
| 18 |
-
- Upload images of Rubik's cubes
|
| 19 |
-
-
|
| 20 |
-
- Simple and intuitive interface
|
|
|
|
| 21 |
|
| 22 |
-
## How to Use
|
| 23 |
|
| 24 |
-
1.
|
| 25 |
-
2.
|
| 26 |
-
3.
|
| 27 |
|
| 28 |
-
## Technical Details
|
| 29 |
|
| 30 |
-
-
|
| 31 |
-
-
|
| 32 |
-
-
|
|
|
|
|
|
|
| 33 |
|
| 34 |
-
##
|
| 35 |
|
| 36 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
## 🌟 Model Description
|
| 47 |
-
|
| 48 |
-
The model is based on RetinaNet with SpineNet-49 backbone, trained to detect:
|
| 49 |
-
- Rubik's cube faces
|
| 50 |
-
- Individual color tiles (red, white, blue, orange, green, yellow)
|
| 51 |
-
|
| 52 |
-
### Model Architecture
|
| 53 |
-
- Base Model: RetinaNet-SpineNet-49
|
| 54 |
-
- Input Size: 640x640x3
|
| 55 |
-
- Number of Classes: 7 (6 colors + face)
|
| 56 |
-
- Output: Bounding boxes with class predictions
|
| 57 |
|
| 58 |
## 📊 Performance Metrics
|
| 59 |
|
| 60 |
-
| Metric |
|
| 61 |
-
|
| 62 |
-
| mAP
|
| 63 |
-
|
|
|
|
|
| 64 |
|
| 65 |
-
##
|
| 66 |
|
| 67 |
```bash
|
| 68 |
# Clone the repository
|
| 69 |
-
git clone https://huggingface.co/spaces/
|
|
|
|
| 70 |
|
| 71 |
# Install dependencies
|
| 72 |
pip install -r requirements.txt
|
| 73 |
|
| 74 |
-
# Run the
|
| 75 |
python app.py
|
| 76 |
```
|
| 77 |
|
| 78 |
-
##
|
| 79 |
|
| 80 |
```
|
| 81 |
rubiks-cube-recognition/
|
| 82 |
-
├── app.py
|
| 83 |
-
├──
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
│
|
| 87 |
-
|
| 88 |
-
│
|
| 89 |
-
│
|
| 90 |
-
|
| 91 |
-
├──
|
| 92 |
-
├──
|
| 93 |
-
└──
|
| 94 |
```
|
| 95 |
|
| 96 |
-
##
|
| 97 |
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
```python
|
| 101 |
-
python src/model/trainer.py --config configs/retinanet_config.py
|
| 102 |
-
```
|
| 103 |
|
| 104 |
-
|
| 105 |
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
|
|
|
|
|
|
| 109 |
|
| 110 |
-
##
|
| 111 |
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
- Classes: 7 (face, red_tile, white_tile, blue_tile, orange_tile, green_tile, yellow_tile)
|
| 120 |
|
| 121 |
## 🤝 Contributing
|
| 122 |
|
| 123 |
-
Contributions are welcome!
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
|
| 125 |
## 📄 License
|
| 126 |
|
|
@@ -128,26 +128,26 @@ This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENS
|
|
| 128 |
|
| 129 |
## 🙏 Acknowledgements
|
| 130 |
|
| 131 |
-
- TensorFlow Model Garden
|
| 132 |
-
-
|
| 133 |
-
-
|
|
|
|
| 134 |
|
| 135 |
## 📧 Contact
|
| 136 |
|
| 137 |
-
- GitHub
|
| 138 |
-
- Hugging Face
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
|
| 140 |
-
|
| 141 |
|
| 142 |
-
- [How to Train Custom Object Detection Models using RetinaNet](https://medium.com/@van.evanfebrianto/how-to-train-custom-object-detection-models-using-retinanet-aeed72f5d701)
|
| 143 |
-
- labelme2coco: https://github.com/fcakyon/labelme2coco
|
| 144 |
-
|
| 145 |
-
- **Keras RetinaNet**: https://github.com/fizyr/keras-retinanet
|
| 146 |
-
- **TensorFlow 2.x RetinaNet**: https://github.com/srihari-humbarwadi/retinanet-tensorflow2.x
|
| 147 |
-
- **SpineNet-PyTorch**: https://github.com/yan-roo/SpineNet-Pytorch
|
| 148 |
|
| 149 |
-
- **LabelMe to COCO Converter**: https://github.com/wkentaro/labelme
|
| 150 |
-
- **labelme-json-to-coco-json**: https://roboflow.com/convert/labelme-json-to-coco-json
|
| 151 |
|
| 152 |
-
|
| 153 |
-
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Rubiks Cube Recognition
|
| 3 |
emoji: 🎲
|
| 4 |
colorFrom: blue
|
| 5 |
colorTo: red
|
|
|
|
| 7 |
sdk_version: 4.19.2
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
+
license: apache-2.0
|
| 11 |
---
|
| 12 |
|
| 13 |
+
# 🎲 Rubik's Cube Recognition with TensorFlow RetinaNet
|
| 14 |
|
| 15 |
+
This is a deep learning model that can recognize and analyze Rubik's cubes in images. The model is built using TensorFlow and RetinaNet architecture for object detection.
|
| 16 |
|
| 17 |
+
## 🚀 Features
|
| 18 |
|
| 19 |
+
- **Real-time Detection**: Upload images of Rubik's cubes for instant analysis
|
| 20 |
+
- **Multi-class Recognition**: Detect cube faces and 6 different color tiles
|
| 21 |
+
- **Interactive Interface**: Simple and intuitive Gradio web interface
|
| 22 |
+
- **Advanced AI**: Powered by RetinaNet with SpineNet-49 backbone
|
| 23 |
|
| 24 |
+
## 🎯 How to Use
|
| 25 |
|
| 26 |
+
1. **Upload**: Click "Upload Rubik's Cube Image" and select your image
|
| 27 |
+
2. **Analyze**: Click "🔍 Analyze Image" or wait for automatic processing
|
| 28 |
+
3. **Results**: View detection results and visualization with bounding boxes
|
| 29 |
|
| 30 |
+
## 🔬 Technical Details
|
| 31 |
|
| 32 |
+
- **Framework**: TensorFlow 2.15+ with Gradio interface
|
| 33 |
+
- **Architecture**: RetinaNet with SpineNet-49 backbone
|
| 34 |
+
- **Input Size**: 640×640 pixels
|
| 35 |
+
- **Classes**: 7 total (1 face + 6 color tiles)
|
| 36 |
+
- **Colors Detected**: Red, White, Blue, Orange, Green, Yellow
|
| 37 |
|
| 38 |
+
## 🌟 Model Architecture
|
| 39 |
|
| 40 |
+
### RetinaNet-SpineNet-49
|
| 41 |
+
- **Base Model**: RetinaNet for object detection
|
| 42 |
+
- **Backbone**: SpineNet-49 for feature extraction
|
| 43 |
+
- **Input Resolution**: 640×640×3
|
| 44 |
+
- **Output**: Bounding boxes with class predictions and confidence scores
|
| 45 |
|
| 46 |
+
### Detection Classes
|
| 47 |
+
1. `face` - Rubik's cube face
|
| 48 |
+
2. `red_tile` - Red color tile
|
| 49 |
+
3. `white_tile` - White color tile
|
| 50 |
+
4. `blue_tile` - Blue color tile
|
| 51 |
+
5. `orange_tile` - Orange color tile
|
| 52 |
+
6. `green_tile` - Green color tile
|
| 53 |
+
7. `yellow_tile` - Yellow color tile
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
|
| 55 |
## 📊 Performance Metrics
|
| 56 |
|
| 57 |
+
| Metric | Target | Status |
|
| 58 |
+
|--------|--------|--------|
|
| 59 |
+
| mAP@0.5 | >0.85 | In Training |
|
| 60 |
+
| Inference Speed | <100ms | Optimized |
|
| 61 |
+
| Accuracy | >90% | Evaluating |
|
| 62 |
|
| 63 |
+
## 🛠️ Local Development
|
| 64 |
|
| 65 |
```bash
|
| 66 |
# Clone the repository
|
| 67 |
+
git clone https://huggingface.co/spaces/itsyuimorii/rubiks-cube-recognition
|
| 68 |
+
cd rubiks-cube-recognition
|
| 69 |
|
| 70 |
# Install dependencies
|
| 71 |
pip install -r requirements.txt
|
| 72 |
|
| 73 |
+
# Run the application
|
| 74 |
python app.py
|
| 75 |
```
|
| 76 |
|
| 77 |
+
## 📁 Project Structure
|
| 78 |
|
| 79 |
```
|
| 80 |
rubiks-cube-recognition/
|
| 81 |
+
├── app.py # Main Gradio application
|
| 82 |
+
├── requirements.txt # Python dependencies
|
| 83 |
+
├── README.md # This file
|
| 84 |
+
├── configs/ # Model configurations
|
| 85 |
+
│ └── retinanet_config.py
|
| 86 |
+
├── src/ # Source code
|
| 87 |
+
│ ├── data/ # Data processing utilities
|
| 88 |
+
│ └── model/ # Model training and inference
|
| 89 |
+
└── images/ # Training and test datasets
|
| 90 |
+
├── train/ # Training images and annotations
|
| 91 |
+
├── test/ # Test images and annotations
|
| 92 |
+
└── valid/ # Validation images and annotations
|
| 93 |
```
|
| 94 |
|
| 95 |
+
## 🎮 Demo Status
|
| 96 |
|
| 97 |
+
⚠️ **Note**: This is a demo version. The complete trained model is currently being developed. The interface will show a preview of the detection capabilities.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 98 |
|
| 99 |
+
## 📝 Dataset Information
|
| 100 |
|
| 101 |
+
- **Format**: COCO annotation format
|
| 102 |
+
- **Image Size**: 640×640 pixels
|
| 103 |
+
- **Training Images**: 50+ annotated cube images
|
| 104 |
+
- **Classes**: 7 object classes (face + 6 colors)
|
| 105 |
+
- **Annotation Tool**: LabelMe
|
| 106 |
|
| 107 |
+
## 🔧 Training Pipeline
|
| 108 |
|
| 109 |
+
```python
|
| 110 |
+
# Training command
|
| 111 |
+
python src/model/trainer.py --config configs/retinanet_config.py
|
| 112 |
|
| 113 |
+
# Inference command
|
| 114 |
+
python src/model/visualize.py --image path/to/cube_image.jpg
|
| 115 |
+
```
|
|
|
|
| 116 |
|
| 117 |
## 🤝 Contributing
|
| 118 |
|
| 119 |
+
Contributions are welcome! Areas for improvement:
|
| 120 |
+
- Additional training data
|
| 121 |
+
- Model optimization
|
| 122 |
+
- UI/UX enhancements
|
| 123 |
+
- Performance improvements
|
| 124 |
|
| 125 |
## 📄 License
|
| 126 |
|
|
|
|
| 128 |
|
| 129 |
## 🙏 Acknowledgements
|
| 130 |
|
| 131 |
+
- **TensorFlow Model Garden** - RetinaNet implementation
|
| 132 |
+
- **SpineNet** - Backbone architecture
|
| 133 |
+
- **Gradio** - Web interface framework
|
| 134 |
+
- **Hugging Face** - Model hosting and deployment
|
| 135 |
|
| 136 |
## 📧 Contact
|
| 137 |
|
| 138 |
+
- **GitHub**: [@itsyuimorii](https://github.com/itsyuimorii)
|
| 139 |
+
- **Hugging Face**: [@itsyuimorii](https://huggingface.co/itsyuimorii)
|
| 140 |
+
|
| 141 |
+
## 🔗 References
|
| 142 |
+
|
| 143 |
+
- [RetinaNet Paper](https://arxiv.org/abs/1708.02002)
|
| 144 |
+
- [SpineNet Architecture](https://arxiv.org/abs/1912.05027)
|
| 145 |
+
- [TensorFlow Object Detection API](https://github.com/tensorflow/models/tree/master/research/object_detection)
|
| 146 |
+
- [LabelMe Annotation Tool](https://github.com/wkentaro/labelme)
|
| 147 |
+
|
| 148 |
+
---
|
| 149 |
|
| 150 |
+
*🎲 Ready to solve your Rubik's cube detection challenges!*
|
| 151 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 152 |
|
|
|
|
|
|
|
| 153 |
|
|
|
|
|
|
app.py
CHANGED
|
@@ -1,8 +1,6 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
-
import tensorflow as tf
|
| 3 |
import numpy as np
|
| 4 |
from PIL import Image
|
| 5 |
-
import cv2
|
| 6 |
import os
|
| 7 |
|
| 8 |
# Simplified category index
|
|
@@ -16,174 +14,84 @@ CATEGORY_INDEX = {
|
|
| 16 |
7: {'id': 7, 'name': 'yellow_tile'}
|
| 17 |
}
|
| 18 |
|
| 19 |
-
|
| 20 |
-
def preprocess_image(image):
|
| 21 |
-
"""
|
| 22 |
-
Preprocess input image
|
| 23 |
-
"""
|
| 24 |
-
if image is None:
|
| 25 |
-
return None
|
| 26 |
-
|
| 27 |
-
# Convert to PIL image
|
| 28 |
-
if isinstance(image, np.ndarray):
|
| 29 |
-
image = Image.fromarray(image)
|
| 30 |
-
|
| 31 |
-
# Resize to model expected size
|
| 32 |
-
image = image.resize((640, 640))
|
| 33 |
-
|
| 34 |
-
# Convert to numpy array and normalize
|
| 35 |
-
image_array = np.array(image) / 255.0
|
| 36 |
-
|
| 37 |
-
# Add batch dimension
|
| 38 |
-
image_array = np.expand_dims(image_array, axis=0)
|
| 39 |
-
|
| 40 |
-
return image_array.astype(np.float32)
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
def load_model():
|
| 44 |
-
"""
|
| 45 |
-
Load pretrained model
|
| 46 |
-
"""
|
| 47 |
-
try:
|
| 48 |
-
# Try to load saved model
|
| 49 |
-
if os.path.exists('exported_model'):
|
| 50 |
-
model = tf.saved_model.load('exported_model')
|
| 51 |
-
return model
|
| 52 |
-
else:
|
| 53 |
-
# If no model file exists, return None
|
| 54 |
-
return None
|
| 55 |
-
except Exception as e:
|
| 56 |
-
print(f"Model loading failed: {e}")
|
| 57 |
-
return None
|
| 58 |
-
|
| 59 |
-
|
| 60 |
def predict_image(image):
|
| 61 |
"""
|
| 62 |
-
Make predictions on input image
|
| 63 |
"""
|
| 64 |
if image is None:
|
| 65 |
return "Please upload an image", None
|
| 66 |
|
| 67 |
try:
|
| 68 |
-
#
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
if processed_image is None:
|
| 72 |
-
return "Image preprocessing failed", None
|
| 73 |
-
|
| 74 |
-
# Load model
|
| 75 |
-
model = load_model()
|
| 76 |
-
|
| 77 |
-
if model is None:
|
| 78 |
-
return "Model not found. This is a demo version, actual model needs to be trained first.\n\nDetected a Rubik's cube image!", image
|
| 79 |
-
|
| 80 |
-
# Make prediction
|
| 81 |
-
model_fn = model.signatures['serving_default']
|
| 82 |
-
|
| 83 |
-
# Convert input format
|
| 84 |
-
input_tensor = tf.convert_to_tensor(processed_image)
|
| 85 |
|
| 86 |
-
#
|
| 87 |
-
|
| 88 |
-
|
| 89 |
-
#
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 116 |
|
| 117 |
except Exception as e:
|
| 118 |
-
error_msg = f"Error
|
| 119 |
return error_msg, image
|
| 120 |
|
| 121 |
-
|
| 122 |
-
def draw_boxes_on_image(image, boxes, classes, scores):
|
| 123 |
-
"""
|
| 124 |
-
Draw detection boxes on image (simplified version)
|
| 125 |
-
"""
|
| 126 |
-
try:
|
| 127 |
-
# Convert to OpenCV format
|
| 128 |
-
if isinstance(image, Image.Image):
|
| 129 |
-
cv_image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
|
| 130 |
-
else:
|
| 131 |
-
cv_image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
|
| 132 |
-
|
| 133 |
-
h, w = cv_image.shape[:2]
|
| 134 |
-
|
| 135 |
-
# Draw detection boxes
|
| 136 |
-
for box, cls, score in zip(boxes, classes, scores):
|
| 137 |
-
if score > 0.5:
|
| 138 |
-
# Convert coordinates (assuming normalized coordinates)
|
| 139 |
-
y1, x1, y2, x2 = box
|
| 140 |
-
x1, x2 = int(x1 * w), int(x2 * w)
|
| 141 |
-
y1, y2 = int(y1 * h), int(y2 * h)
|
| 142 |
-
|
| 143 |
-
# Draw rectangle
|
| 144 |
-
cv2.rectangle(cv_image, (x1, y1), (x2, y2), (0, 255, 0), 2)
|
| 145 |
-
|
| 146 |
-
# Add label
|
| 147 |
-
class_name = CATEGORY_INDEX.get(
|
| 148 |
-
cls, {}).get('name', f'class_{cls}')
|
| 149 |
-
label = f"{class_name}: {score:.2f}"
|
| 150 |
-
cv2.putText(cv_image, label, (x1, y1-10),
|
| 151 |
-
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1)
|
| 152 |
-
|
| 153 |
-
# Convert back to RGB
|
| 154 |
-
result_image = cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB)
|
| 155 |
-
return Image.fromarray(result_image)
|
| 156 |
-
|
| 157 |
-
except Exception as e:
|
| 158 |
-
print(f"Error drawing detection boxes: {e}")
|
| 159 |
-
return image
|
| 160 |
-
|
| 161 |
-
# Create Gradio interface
|
| 162 |
-
|
| 163 |
-
|
| 164 |
def create_demo():
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
**Features:**
|
| 172 |
-
- Detect cube faces and color tiles
|
| 173 |
-
- Support 6 color recognition: Red, White, Blue, Orange, Green, Yellow
|
| 174 |
-
- Real-time detection and visualization
|
| 175 |
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
|
|
|
|
|
|
|
|
|
| 180 |
""")
|
| 181 |
|
| 182 |
with gr.Row():
|
| 183 |
-
with gr.Column():
|
|
|
|
|
|
|
| 184 |
input_image = gr.Image(
|
| 185 |
label="Upload Rubik's Cube Image",
|
| 186 |
-
type="pil"
|
|
|
|
| 187 |
)
|
| 188 |
|
| 189 |
analyze_btn = gr.Button(
|
|
@@ -191,42 +99,53 @@ def create_demo():
|
|
| 191 |
variant="primary",
|
| 192 |
size="lg"
|
| 193 |
)
|
| 194 |
-
|
| 195 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 196 |
result_text = gr.Textbox(
|
| 197 |
-
label="Detection
|
| 198 |
-
lines=
|
| 199 |
-
max_lines=15
|
|
|
|
| 200 |
)
|
| 201 |
|
| 202 |
output_image = gr.Image(
|
| 203 |
-
label="
|
| 204 |
-
type="pil"
|
|
|
|
| 205 |
)
|
| 206 |
|
| 207 |
-
#
|
| 208 |
-
gr.Markdown("### 📋 Usage Examples")
|
| 209 |
-
gr.Markdown(
|
| 210 |
-
"Upload Rubik's cube images similar to the following for testing:")
|
| 211 |
-
|
| 212 |
-
# Bind events
|
| 213 |
analyze_btn.click(
|
| 214 |
fn=predict_image,
|
| 215 |
inputs=[input_image],
|
| 216 |
outputs=[result_text, output_image]
|
| 217 |
)
|
| 218 |
|
| 219 |
-
# Auto-analyze when image is uploaded
|
| 220 |
input_image.change(
|
| 221 |
fn=predict_image,
|
| 222 |
inputs=[input_image],
|
| 223 |
outputs=[result_text, output_image]
|
| 224 |
)
|
| 225 |
|
| 226 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 227 |
|
|
|
|
| 228 |
|
| 229 |
-
# Launch application
|
| 230 |
if __name__ == "__main__":
|
| 231 |
demo = create_demo()
|
| 232 |
demo.launch(
|
|
|
|
| 1 |
import gradio as gr
|
|
|
|
| 2 |
import numpy as np
|
| 3 |
from PIL import Image
|
|
|
|
| 4 |
import os
|
| 5 |
|
| 6 |
# Simplified category index
|
|
|
|
| 14 |
7: {'id': 7, 'name': 'yellow_tile'}
|
| 15 |
}
|
| 16 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
def predict_image(image):
|
| 18 |
"""
|
| 19 |
+
Make predictions on input image - Demo version
|
| 20 |
"""
|
| 21 |
if image is None:
|
| 22 |
return "Please upload an image", None
|
| 23 |
|
| 24 |
try:
|
| 25 |
+
# Convert to PIL image if needed
|
| 26 |
+
if isinstance(image, np.ndarray):
|
| 27 |
+
image = Image.fromarray(image)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
|
| 29 |
+
# Get image information
|
| 30 |
+
width, height = image.size
|
| 31 |
+
|
| 32 |
+
# Demo response since model is not trained yet
|
| 33 |
+
result_text = f"""🎲 Rubik's Cube Analysis Results
|
| 34 |
+
|
| 35 |
+
📊 Image Information:
|
| 36 |
+
- Dimensions: {width} × {height} pixels
|
| 37 |
+
- Format: {getattr(image, 'format', 'PIL Image')}
|
| 38 |
+
|
| 39 |
+
🔍 Detection Status:
|
| 40 |
+
✅ Image uploaded successfully
|
| 41 |
+
✅ Image format is valid
|
| 42 |
+
⚠️ AI model is currently in development
|
| 43 |
+
|
| 44 |
+
📝 Demo Mode:
|
| 45 |
+
This is a preview of the Rubik's cube recognition system.
|
| 46 |
+
The complete RetinaNet model will detect:
|
| 47 |
+
|
| 48 |
+
🎯 Target Detection Classes:
|
| 49 |
+
- Cube faces
|
| 50 |
+
- Red tiles
|
| 51 |
+
- White tiles
|
| 52 |
+
- Blue tiles
|
| 53 |
+
- Orange tiles
|
| 54 |
+
- Green tiles
|
| 55 |
+
- Yellow tiles
|
| 56 |
+
|
| 57 |
+
🚀 Coming Soon:
|
| 58 |
+
- Real-time object detection
|
| 59 |
+
- Bounding box visualization
|
| 60 |
+
- Confidence scores
|
| 61 |
+
- 3D cube state analysis
|
| 62 |
+
"""
|
| 63 |
+
|
| 64 |
+
return result_text, image
|
| 65 |
|
| 66 |
except Exception as e:
|
| 67 |
+
error_msg = f"Error processing image: {str(e)}\n\nThis is a demo version."
|
| 68 |
return error_msg, image
|
| 69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 70 |
def create_demo():
|
| 71 |
+
"""Create the Gradio interface"""
|
| 72 |
+
|
| 73 |
+
with gr.Blocks(
|
| 74 |
+
title="🎲 Rubik's Cube Recognition System",
|
| 75 |
+
theme=gr.themes.Soft()
|
| 76 |
+
) as demo:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
|
| 78 |
+
gr.HTML("""
|
| 79 |
+
<div style="text-align: center; padding: 20px;">
|
| 80 |
+
<h1>🎲 Rubik's Cube Recognition System</h1>
|
| 81 |
+
<p style="font-size: 18px; color: #666;">
|
| 82 |
+
Deep Learning-based Rubik's Cube Detection using RetinaNet Architecture
|
| 83 |
+
</p>
|
| 84 |
+
</div>
|
| 85 |
""")
|
| 86 |
|
| 87 |
with gr.Row():
|
| 88 |
+
with gr.Column(scale=1):
|
| 89 |
+
gr.Markdown("### 📤 Upload Image")
|
| 90 |
+
|
| 91 |
input_image = gr.Image(
|
| 92 |
label="Upload Rubik's Cube Image",
|
| 93 |
+
type="pil",
|
| 94 |
+
height=350
|
| 95 |
)
|
| 96 |
|
| 97 |
analyze_btn = gr.Button(
|
|
|
|
| 99 |
variant="primary",
|
| 100 |
size="lg"
|
| 101 |
)
|
| 102 |
+
|
| 103 |
+
gr.Markdown("""
|
| 104 |
+
### 💡 Tips
|
| 105 |
+
- Upload clear images of Rubik's cubes
|
| 106 |
+
- Good lighting recommended
|
| 107 |
+
- JPG/PNG formats supported
|
| 108 |
+
""")
|
| 109 |
+
|
| 110 |
+
with gr.Column(scale=1):
|
| 111 |
+
gr.Markdown("### 📊 Analysis Results")
|
| 112 |
+
|
| 113 |
result_text = gr.Textbox(
|
| 114 |
+
label="Detection Report",
|
| 115 |
+
lines=12,
|
| 116 |
+
max_lines=15,
|
| 117 |
+
show_copy_button=True
|
| 118 |
)
|
| 119 |
|
| 120 |
output_image = gr.Image(
|
| 121 |
+
label="Processed Image",
|
| 122 |
+
type="pil",
|
| 123 |
+
height=350
|
| 124 |
)
|
| 125 |
|
| 126 |
+
# Event handlers
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
analyze_btn.click(
|
| 128 |
fn=predict_image,
|
| 129 |
inputs=[input_image],
|
| 130 |
outputs=[result_text, output_image]
|
| 131 |
)
|
| 132 |
|
|
|
|
| 133 |
input_image.change(
|
| 134 |
fn=predict_image,
|
| 135 |
inputs=[input_image],
|
| 136 |
outputs=[result_text, output_image]
|
| 137 |
)
|
| 138 |
|
| 139 |
+
gr.HTML("""
|
| 140 |
+
<div style="text-align: center; padding: 20px; margin-top: 20px; border-top: 1px solid #eee;">
|
| 141 |
+
<p><strong>🔬 Technology Stack:</strong> TensorFlow • RetinaNet • SpineNet-49 • Gradio</p>
|
| 142 |
+
<p><strong>📧 Contact:</strong> <a href="https://huggingface.co/itsyuimorii">@itsyuimorii</a></p>
|
| 143 |
+
</div>
|
| 144 |
+
""")
|
| 145 |
|
| 146 |
+
return demo
|
| 147 |
|
| 148 |
+
# Launch the application
|
| 149 |
if __name__ == "__main__":
|
| 150 |
demo = create_demo()
|
| 151 |
demo.launch(
|
deploy_to_hf.py
CHANGED
|
@@ -11,7 +11,6 @@ def deploy_to_huggingface():
|
|
| 11 |
"""Deploy the project to Hugging Face Spaces"""
|
| 12 |
|
| 13 |
# Set your token
|
| 14 |
-
token = "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"
|
| 15 |
|
| 16 |
# Initialize HF API
|
| 17 |
api = HfApi()
|
|
|
|
| 11 |
"""Deploy the project to Hugging Face Spaces"""
|
| 12 |
|
| 13 |
# Set your token
|
|
|
|
| 14 |
|
| 15 |
# Initialize HF API
|
| 16 |
api = HfApi()
|
requirements.txt
CHANGED
|
@@ -1,6 +1,3 @@
|
|
| 1 |
gradio>=4.0.0
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
Pillow>=8.0.0
|
| 5 |
-
opencv-python-headless>=4.5.1
|
| 6 |
-
matplotlib>=3.2.2
|
|
|
|
| 1 |
gradio>=4.0.0
|
| 2 |
+
numpy>=1.21.0
|
| 3 |
+
Pillow>=8.0.0
|
|
|
|
|
|
|
|
|