Wiuhh commited on
Commit
c33ad35
·
verified ·
1 Parent(s): 7a4e666

Upload 8 files

Browse files
Files changed (8) hide show
  1. Dockerfile +34 -0
  2. README.md +57 -0
  3. app.py +162 -0
  4. image_to_sketch.py +223 -0
  5. pyproject.toml +12 -0
  6. replit.md +64 -0
  7. requirements.txt +5 -0
  8. uv.lock +0 -0
Dockerfile ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+
3
+ # Create user for security
4
+ RUN useradd -m -u 1000 user
5
+ USER user
6
+ ENV PATH="/home/user/.local/bin:$PATH"
7
+
8
+ # Set working directory
9
+ WORKDIR /app
10
+
11
+ # Install system dependencies
12
+ USER root
13
+ RUN apt-get update && apt-get install -y \
14
+ libglib2.0-0 \
15
+ libgomp1 \
16
+ && rm -rf /var/lib/apt/lists/*
17
+
18
+ USER user
19
+
20
+ # Copy requirements and install Python dependencies
21
+ COPY --chown=user ./requirements.txt requirements.txt
22
+ RUN pip install --no-cache-dir --upgrade -r requirements.txt
23
+
24
+ # Copy application files
25
+ COPY --chown=user . /app
26
+
27
+ # Create necessary directories
28
+ RUN mkdir -p uploads results
29
+
30
+ # Expose port (will be set by Hugging Face)
31
+ EXPOSE 7860
32
+
33
+ # Start application with gunicorn (bind to PORT env var with 7860 fallback)
34
+ CMD ["bash", "-c", "exec gunicorn --workers=2 --threads=4 --timeout=60 --bind=0.0.0.0:${PORT:-7860} app:app"]
README.md ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: SketchAI - Image to Sketch Converter
3
+ emoji: 🎨
4
+ colorFrom: purple
5
+ colorTo: pink
6
+ sdk: docker
7
+ app_file: app.py
8
+ pinned: false
9
+ license: mit
10
+ ---
11
+
12
+ # SketchAI - Image to Sketch Converter
13
+
14
+ Transform your photos into beautiful pencil sketch drawings with AI! SketchAI uses advanced computer vision techniques to convert regular photographs into artistic sketch representations.
15
+
16
+ ## Features
17
+
18
+ ✨ **Beautiful Web Interface** - Stunning dark theme with animated gradient borders
19
+ 🖼️ **Drag & Drop Upload** - Easy image uploading with support for multiple formats
20
+ ⚙️ **Customizable Settings** - Adjust blur intensity and enable enhanced line definition
21
+ 👁️ **Real-time Preview** - See your original and sketch side-by-side
22
+ 💾 **Instant Download** - Get your sketch with one click
23
+ 📱 **Mobile Friendly** - Works perfectly on all devices
24
+
25
+ ## How It Works
26
+
27
+ 1. **Upload** your image by dragging and dropping or browsing files
28
+ 2. **Customize** the sketch settings (blur intensity, enhanced lines)
29
+ 3. **Process** - Watch as AI transforms your photo into a sketch
30
+ 4. **Download** your beautiful pencil sketch drawing
31
+
32
+ ## Supported Formats
33
+
34
+ - JPG/JPEG
35
+ - PNG
36
+ - BMP
37
+ - TIFF
38
+ - WebP
39
+
40
+ ## Technical Details
41
+
42
+ The application uses a multi-step image processing pipeline:
43
+ - **Grayscale Conversion** - Converts color images to grayscale
44
+ - **Image Inversion** - Creates negative for sketch effect
45
+ - **Gaussian Blur** - Applies customizable blur for artistic effect
46
+ - **Color Dodge Blending** - Combines images for realistic pencil sketch appearance
47
+ - **Optional Enhancement** - Adaptive thresholding for sharper lines
48
+
49
+ Built with Flask, OpenCV, and modern web technologies.
50
+
51
+ ## Usage
52
+
53
+ Simply visit the app, upload any photo, adjust settings to your liking, and download your personalized sketch artwork!
54
+
55
+ ---
56
+
57
+ *Created with ❤️ using OpenCV and Flask*
app.py ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import uuid
3
+ from flask import Flask, render_template, request, jsonify, send_from_directory, url_for
4
+ from werkzeug.utils import secure_filename
5
+ import cv2
6
+ import numpy as np
7
+ from PIL import Image
8
+ from image_to_sketch import ImageToSketch
9
+
10
+ app = Flask(__name__)
11
+
12
+ # Configuration
13
+ app.config['MAX_CONTENT_LENGTH'] = 10 * 1024 * 1024 # 10MB max file size
14
+ app.config['UPLOAD_FOLDER'] = 'uploads'
15
+ app.config['RESULT_FOLDER'] = 'results'
16
+
17
+ # Allowed file extensions
18
+ ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif', 'bmp', 'tiff', 'webp'}
19
+
20
+ def allowed_file(filename):
21
+ """Check if file extension is allowed."""
22
+ return '.' in filename and \
23
+ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
24
+
25
+ def ensure_directories():
26
+ """Ensure upload and result directories exist."""
27
+ for directory in [app.config['UPLOAD_FOLDER'], app.config['RESULT_FOLDER']]:
28
+ if not os.path.exists(directory):
29
+ os.makedirs(directory)
30
+
31
+ @app.route('/')
32
+ def index():
33
+ """Serve the main page."""
34
+ return render_template('index.html')
35
+
36
+ @app.route('/convert', methods=['POST'])
37
+ def convert_image():
38
+ """Handle image conversion to sketch."""
39
+ try:
40
+ # Check if image was uploaded
41
+ if 'image' not in request.files:
42
+ return jsonify({'error': 'No image file provided'}), 400
43
+
44
+ file = request.files['image']
45
+ if file.filename == '':
46
+ return jsonify({'error': 'No file selected'}), 400
47
+
48
+ if not allowed_file(file.filename):
49
+ return jsonify({'error': 'Invalid file type. Please upload an image file.'}), 400
50
+
51
+ # Get processing options
52
+ blur_value = int(request.form.get('blur', 21))
53
+ enhance = request.form.get('enhance', 'false').lower() == 'true'
54
+
55
+ # Validate blur value
56
+ if blur_value < 1:
57
+ return jsonify({'error': 'Blur value must be positive'}), 400
58
+
59
+ # Make blur value odd
60
+ if blur_value % 2 == 0:
61
+ blur_value += 1
62
+
63
+ # Generate unique filename
64
+ file_id = str(uuid.uuid4())
65
+ if file.filename and '.' in file.filename:
66
+ original_ext = file.filename.rsplit('.', 1)[1].lower()
67
+ else:
68
+ original_ext = 'jpg' # Default extension
69
+ input_filename = f"{file_id}_original.{original_ext}"
70
+ output_filename = f"{file_id}_sketch.jpg"
71
+
72
+ # Save uploaded file
73
+ input_path = os.path.join(app.config['UPLOAD_FOLDER'], input_filename)
74
+ output_path = os.path.join(app.config['RESULT_FOLDER'], output_filename)
75
+
76
+ file.save(input_path)
77
+
78
+ # Convert image to sketch
79
+ converter = ImageToSketch()
80
+ sketch = converter.convert_to_sketch(
81
+ input_path,
82
+ output_path,
83
+ blur_value=blur_value,
84
+ enhance=enhance
85
+ )
86
+
87
+ # Generate URL for the result
88
+ sketch_url = url_for('get_result', filename=output_filename)
89
+
90
+ # Clean up input file after successful processing
91
+ try:
92
+ os.remove(input_path)
93
+ except Exception:
94
+ pass # Don't fail if cleanup fails
95
+
96
+ return jsonify({
97
+ 'success': True,
98
+ 'sketch_url': sketch_url,
99
+ 'blur_value': blur_value,
100
+ 'enhanced': enhance
101
+ })
102
+
103
+ except cv2.error as e:
104
+ print(f"OpenCV error processing image: {str(e)}")
105
+ return jsonify({'error': 'Invalid or corrupted image file'}), 400
106
+ except Exception as e:
107
+ print(f"Error processing image: {str(e)}")
108
+ return jsonify({'error': 'Failed to process image. Please try again.'}), 500
109
+
110
+ @app.route('/results/<filename>')
111
+ def get_result(filename):
112
+ """Serve result images."""
113
+ return send_from_directory(app.config['RESULT_FOLDER'], filename)
114
+
115
+ # Removed /uploads route for security - originals should not be publicly accessible
116
+
117
+ @app.errorhandler(413)
118
+ def too_large(e):
119
+ """Handle file too large error."""
120
+ return jsonify({'error': 'File size exceeds 10MB limit'}), 413
121
+
122
+ @app.errorhandler(500)
123
+ def internal_error(e):
124
+ """Handle internal server errors."""
125
+ return jsonify({'error': 'Internal server error'}), 500
126
+
127
+ def cleanup_old_files():
128
+ """Clean up old uploaded and result files."""
129
+ import time
130
+ current_time = time.time()
131
+ max_age = 24 * 60 * 60 # 24 hours
132
+
133
+ for folder in [app.config['UPLOAD_FOLDER'], app.config['RESULT_FOLDER']]:
134
+ if os.path.exists(folder):
135
+ for filename in os.listdir(folder):
136
+ file_path = os.path.join(folder, filename)
137
+ if os.path.isfile(file_path):
138
+ file_age = current_time - os.path.getctime(file_path)
139
+ if file_age > max_age:
140
+ try:
141
+ os.remove(file_path)
142
+ print(f"Cleaned up old file: {file_path}")
143
+ except Exception as e:
144
+ print(f"Error cleaning up {file_path}: {e}")
145
+
146
+ if __name__ == '__main__':
147
+ ensure_directories()
148
+
149
+ # Clean up old files on startup
150
+ try:
151
+ cleanup_old_files()
152
+ except Exception as e:
153
+ print(f"Error during cleanup: {e}")
154
+
155
+ # Auto-detect port: prefer PORT env var, else 7860 for HF, else 5000 for local
156
+ port = int(os.environ.get('PORT') or (7860 if 'SPACE_ID' in os.environ else 5000))
157
+
158
+ # Start the Flask development server
159
+ print("Starting SketchAI Web Application...")
160
+ print(f"Open your browser and navigate to: http://localhost:{port}")
161
+
162
+ app.run(host='0.0.0.0', port=port, debug=False)
image_to_sketch.py ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Image to Sketch Converter
4
+ A Python program that converts images to pencil sketch style drawings.
5
+ """
6
+
7
+ import cv2
8
+ import numpy as np
9
+ from PIL import Image
10
+ import argparse
11
+ import os
12
+ import sys
13
+
14
+
15
+ class ImageToSketch:
16
+ """Class to handle image to sketch conversion operations."""
17
+
18
+ def __init__(self):
19
+ # Note: OpenCV supports many formats, so we mainly rely on cv2.imread success
20
+ self.supported_formats = ['.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.tif', '.webp']
21
+
22
+ def validate_image_file(self, filepath):
23
+ """Validate if the file exists and has a supported format."""
24
+ if not os.path.exists(filepath):
25
+ raise FileNotFoundError(f"Image file not found: {filepath}")
26
+
27
+ file_ext = os.path.splitext(filepath)[1].lower()
28
+ if file_ext not in self.supported_formats:
29
+ raise ValueError(f"Unsupported image format: {file_ext}. Supported formats: {', '.join(self.supported_formats)}")
30
+
31
+ return True
32
+
33
+ def load_image(self, filepath):
34
+ """Load image from file path."""
35
+ self.validate_image_file(filepath)
36
+
37
+ # Load image using OpenCV
38
+ image = cv2.imread(filepath)
39
+ if image is None:
40
+ raise ValueError(f"Could not load image: {filepath}")
41
+
42
+ return image
43
+
44
+ def convert_to_grayscale(self, image):
45
+ """Convert color image to grayscale."""
46
+ return cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
47
+
48
+ def invert_image(self, image):
49
+ """Invert the grayscale image (create negative)."""
50
+ return 255 - image
51
+
52
+ def apply_gaussian_blur(self, image, blur_value=21):
53
+ """Apply Gaussian blur to the image."""
54
+ # Validate blur value
55
+ if blur_value < 1:
56
+ raise ValueError(f"Blur value must be positive (>= 1), got: {blur_value}")
57
+ if blur_value % 2 == 0:
58
+ blur_value += 1
59
+ return cv2.GaussianBlur(image, (blur_value, blur_value), 0)
60
+
61
+ def create_sketch_blend(self, grayscale_img, blurred_img):
62
+ """Create sketch effect by blending grayscale and blurred images."""
63
+ # Use color dodge blend mode to create sketch effect
64
+ sketch = cv2.divide(grayscale_img, 255 - blurred_img, scale=256)
65
+ return sketch
66
+
67
+ def enhance_sketch(self, sketch):
68
+ """Enhance the sketch with additional processing."""
69
+ # Apply adaptive threshold for better line definition
70
+ enhanced = cv2.adaptiveThreshold(
71
+ sketch, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 9, 9
72
+ )
73
+ return enhanced
74
+
75
+ def convert_to_sketch(self, input_path, output_path=None, blur_value=21, enhance=False):
76
+ """
77
+ Main method to convert image to sketch.
78
+
79
+ Args:
80
+ input_path (str): Path to input image
81
+ output_path (str): Path to save sketch (optional)
82
+ blur_value (int): Gaussian blur intensity (default: 21)
83
+ enhance (bool): Apply enhancement for better line definition
84
+
85
+ Returns:
86
+ numpy.ndarray: Sketch image array
87
+ """
88
+ print(f"Loading image: {input_path}")
89
+
90
+ # Load the original image
91
+ original_image = self.load_image(input_path)
92
+
93
+ # Convert to grayscale
94
+ print("Converting to grayscale...")
95
+ grayscale = self.convert_to_grayscale(original_image)
96
+
97
+ # Invert the grayscale image
98
+ print("Creating inverted image...")
99
+ inverted = self.invert_image(grayscale)
100
+
101
+ # Apply Gaussian blur to inverted image
102
+ print(f"Applying Gaussian blur (blur value: {blur_value})...")
103
+ blurred = self.apply_gaussian_blur(inverted, blur_value)
104
+
105
+ # Create sketch by blending
106
+ print("Creating sketch blend...")
107
+ sketch = self.create_sketch_blend(grayscale, blurred)
108
+
109
+ # Apply enhancement if requested
110
+ if enhance:
111
+ print("Enhancing sketch...")
112
+ sketch = self.enhance_sketch(sketch)
113
+
114
+ # Save the sketch if output path is provided
115
+ if output_path:
116
+ self.save_sketch(sketch, output_path)
117
+ print(f"Sketch saved to: {output_path}")
118
+
119
+ return sketch
120
+
121
+ def save_sketch(self, sketch, output_path):
122
+ """Save sketch image to file."""
123
+ # Ensure output directory exists
124
+ output_dir = os.path.dirname(output_path)
125
+ if output_dir and not os.path.exists(output_dir):
126
+ os.makedirs(output_dir)
127
+
128
+ # Save using OpenCV
129
+ success = cv2.imwrite(output_path, sketch)
130
+ if not success:
131
+ raise ValueError(f"Failed to save sketch to: {output_path}")
132
+
133
+ def display_comparison(self, original_path, sketch):
134
+ """Display original and sketch side by side using matplotlib."""
135
+ try:
136
+ import matplotlib.pyplot as plt
137
+
138
+ # Load original for comparison
139
+ original = self.load_image(original_path)
140
+ original_rgb = cv2.cvtColor(original, cv2.COLOR_BGR2RGB)
141
+
142
+ # Create side-by-side comparison
143
+ fig, axes = plt.subplots(1, 2, figsize=(12, 6))
144
+
145
+ axes[0].imshow(original_rgb)
146
+ axes[0].set_title('Original Image')
147
+ axes[0].axis('off')
148
+
149
+ axes[1].imshow(sketch, cmap='gray')
150
+ axes[1].set_title('Sketch')
151
+ axes[1].axis('off')
152
+
153
+ plt.tight_layout()
154
+ plt.show()
155
+
156
+ except ImportError:
157
+ print("Matplotlib not available for display. Sketch conversion completed successfully.")
158
+
159
+
160
+ def main():
161
+ """Main function to handle command line interface."""
162
+ parser = argparse.ArgumentParser(
163
+ description="Convert images to pencil sketch style drawings",
164
+ formatter_class=argparse.RawDescriptionHelpFormatter,
165
+ epilog="""
166
+ Examples:
167
+ python image_to_sketch.py input.jpg
168
+ python image_to_sketch.py input.jpg -o sketch.png
169
+ python image_to_sketch.py input.jpg -o sketch.png --blur 25 --enhance
170
+ python image_to_sketch.py input.jpg --display
171
+ """
172
+ )
173
+
174
+ parser.add_argument('input', help='Input image file path')
175
+ parser.add_argument('-o', '--output', help='Output sketch file path')
176
+ parser.add_argument('--blur', type=int, default=21,
177
+ help='Gaussian blur value (default: 21, must be odd)')
178
+ parser.add_argument('--enhance', action='store_true',
179
+ help='Apply enhancement for better line definition')
180
+ parser.add_argument('--display', action='store_true',
181
+ help='Display original and sketch comparison')
182
+
183
+ args = parser.parse_args()
184
+
185
+ # Validate blur value (must be positive and odd)
186
+ if args.blur < 1:
187
+ print(f"Error: Blur value must be positive (>= 1), got: {args.blur}", file=sys.stderr)
188
+ sys.exit(1)
189
+ if args.blur % 2 == 0:
190
+ args.blur += 1
191
+ print(f"Blur value adjusted to {args.blur} (must be odd)")
192
+
193
+ # Generate output filename if not provided
194
+ if not args.output:
195
+ input_name, input_ext = os.path.splitext(args.input)
196
+ args.output = f"{input_name}_sketch{input_ext}"
197
+
198
+ try:
199
+ # Create converter instance
200
+ converter = ImageToSketch()
201
+
202
+ # Convert image to sketch
203
+ sketch = converter.convert_to_sketch(
204
+ args.input,
205
+ args.output,
206
+ blur_value=args.blur,
207
+ enhance=args.enhance
208
+ )
209
+
210
+ print(f"\n✓ Successfully converted '{args.input}' to sketch!")
211
+ print(f"✓ Sketch saved as: '{args.output}'")
212
+
213
+ # Display comparison if requested
214
+ if args.display:
215
+ converter.display_comparison(args.input, sketch)
216
+
217
+ except Exception as e:
218
+ print(f"Error: {e}", file=sys.stderr)
219
+ sys.exit(1)
220
+
221
+
222
+ if __name__ == "__main__":
223
+ main()
pyproject.toml ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "repl-nix-workspace"
3
+ version = "0.1.0"
4
+ description = "Add your description here"
5
+ requires-python = ">=3.11"
6
+ dependencies = [
7
+ "flask>=3.1.2",
8
+ "matplotlib>=3.10.6",
9
+ "numpy>=2.3.3",
10
+ "opencv-python>=4.11.0.86",
11
+ "pillow>=11.3.0",
12
+ ]
replit.md ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Image to Sketch Converter
2
+
3
+ ## Overview
4
+
5
+ This is a Python-based image processing application that converts regular photographs and images into pencil sketch style drawings. The application uses computer vision techniques to transform color images into artistic sketch representations, providing a simple command-line interface for image conversion operations.
6
+
7
+ ## Recent Changes
8
+
9
+ ### September 29, 2025
10
+ - Created complete image-to-sketch conversion program (`image_to_sketch.py`)
11
+ - Implemented core algorithms: grayscale conversion, image inversion, Gaussian blur, and color-dodge blending
12
+ - Added comprehensive command-line interface with help system
13
+ - Included optional sketch enhancement with adaptive thresholding
14
+ - **NEW: Built beautiful web interface with Flask backend**
15
+ - Adapted stunning dark theme design for sketch conversion
16
+ - Drag & drop file upload with animated gradient borders
17
+ - Real-time image processing with visual feedback
18
+ - Side-by-side original vs sketch comparison
19
+ - Adjustable settings (blur intensity, enhanced lines)
20
+ - Secure file handling and automatic cleanup
21
+ - Successfully tested complete web application and verified output quality
22
+ - Configured workflow for easy web server deployment
23
+
24
+ ## User Preferences
25
+
26
+ Preferred communication style: Simple, everyday language.
27
+
28
+ ## System Architecture
29
+
30
+ ### Core Processing Architecture
31
+ - **Object-oriented design**: Built around the `ImageToSketch` class that encapsulates all conversion logic and image processing operations
32
+ - **Pipeline-based processing**: Uses a multi-step conversion process including grayscale conversion and image inversion as the foundation for sketch creation
33
+ - **File validation system**: Implements robust input validation to ensure image files exist and are in supported formats before processing
34
+
35
+ ### Image Processing Framework
36
+ - **OpenCV integration**: Primary image processing library for loading, manipulating, and converting images with support for multiple image formats
37
+ - **PIL/Pillow support**: Secondary image handling capability for additional format compatibility and image operations
38
+ - **NumPy arrays**: Underlying data structure for efficient image pixel manipulation and mathematical operations
39
+
40
+ ### Input/Output Handling
41
+ - **Multi-format support**: Handles common image formats including JPG, PNG, BMP, TIFF, and WebP files
42
+ - **Command-line interface**: Uses argparse for parsing command-line arguments and user input processing
43
+ - **Error handling**: Comprehensive validation for file existence, format compatibility, and image loading failures
44
+
45
+ ### Processing Pipeline
46
+ - **Grayscale conversion**: First step converts color images to grayscale using OpenCV's color space transformation
47
+ - **Image inversion**: Creates negative images by inverting pixel values (255 - pixel_value) as part of the sketch effect
48
+ - **Extensible design**: Architecture allows for easy addition of additional processing steps in the conversion pipeline
49
+
50
+ ## External Dependencies
51
+
52
+ ### Core Libraries
53
+ - **OpenCV (cv2)**: Primary computer vision library for image loading, processing, and format handling
54
+ - **NumPy**: Numerical computing library for efficient array operations and pixel manipulation
55
+ - **PIL/Pillow**: Python Imaging Library for additional image processing capabilities and format support
56
+
57
+ ### System Dependencies
58
+ - **Python 3**: Requires Python 3.x runtime environment
59
+ - **argparse**: Built-in Python module for command-line argument parsing
60
+ - **os and sys**: Standard library modules for file system operations and system interaction
61
+
62
+ ### File System Requirements
63
+ - **Input validation**: Depends on local file system for image file validation and loading
64
+ - **Format detection**: Uses file extensions and OpenCV's built-in format detection for image compatibility
requirements.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ flask==3.1.2
2
+ opencv-python-headless==4.11.0.86
3
+ numpy==2.3.3
4
+ pillow==11.3.0
5
+ gunicorn==23.0.0
uv.lock ADDED
The diff for this file is too large to render. See raw diff