refactor: streamline onboarding modal by removing unnecessary slide preparation logic and enhancing loading state management for improved user experience
This commit is contained in:
295
.cursor/rules/scikit-image.mdc
Normal file
295
.cursor/rules/scikit-image.mdc
Normal file
@@ -0,0 +1,295 @@
|
||||
---
|
||||
description: This rule provides guidelines for best practices and coding standards when using the scikit-image library for image processing in Python. It covers code organization, performance, security, testing, and common pitfalls.
|
||||
globs: *.py
|
||||
---
|
||||
- Always use UV when installing dependencies for faster and more deterministic dependency resolution.
|
||||
- Always use Python 3.12 or later to leverage the latest language features and performance improvements.
|
||||
- Utilize classes instead of standalone functions where appropriate for better code organization and encapsulation, especially when dealing with stateful image processing operations.
|
||||
|
||||
## Scikit-image Best Practices and Coding Standards
|
||||
|
||||
This document outlines the best practices and coding standards for using the scikit-image library in Python for image processing. Following these guidelines will help ensure code clarity, maintainability, performance, and security.
|
||||
|
||||
### Library Information:
|
||||
- Name: scikit-image
|
||||
- Tags: python, image-processing, scientific-computing
|
||||
|
||||
### 1. Code Organization and Structure:
|
||||
|
||||
- **Directory Structure:**
|
||||
- Adopt a modular directory structure to organize your scikit-image projects.
|
||||
- Example:
|
||||
|
||||
project_name/
|
||||
├── data/ # Contains image data (e.g., input images, sample datasets)
|
||||
├── src/ # Source code directory
|
||||
│ ├── __init__.py # Marks src as a Python package
|
||||
│ ├── modules/
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── image_io.py # Image input/output related functions
|
||||
│ │ ├── processing.py # Core image processing algorithms
|
||||
│ │ ├── segmentation.py # Segmentation algorithms
|
||||
│ │ └── feature.py # Feature extraction modules
|
||||
│ ├── utils.py # Utility functions
|
||||
│ └── main.py # Main application entry point
|
||||
├── tests/ # Unit and integration tests
|
||||
│ ├── __init__.py
|
||||
│ ├── test_image_io.py
|
||||
│ ├── test_processing.py
|
||||
│ └── test_segmentation.py
|
||||
├── notebooks/ # Jupyter notebooks for exploration
|
||||
├── requirements.txt # Project dependencies
|
||||
├── pyproject.toml # Project metadata and build system
|
||||
└── README.md # Project documentation
|
||||
|
||||
|
||||
- **File Naming Conventions:**
|
||||
- Use descriptive and consistent file names.
|
||||
- Module files: `image_io.py`, `processing.py`, `segmentation.py`
|
||||
- Test files: `test_image_io.py`, `test_processing.py`
|
||||
- Utility files: `utils.py`
|
||||
|
||||
- **Module Organization:**
|
||||
- Group related functions and classes into modules.
|
||||
- Avoid monolithic modules; break down large modules into smaller, more manageable ones.
|
||||
- Use `__init__.py` files to define packages and control namespace exposure.
|
||||
- Example (in `src/modules/processing.py`):
|
||||
python
|
||||
from skimage import filters
|
||||
from skimage import morphology
|
||||
import numpy as np
|
||||
|
||||
def apply_threshold(image, threshold_value=128):
|
||||
"""Applies a simple threshold to an image."""
|
||||
return image > threshold_value
|
||||
|
||||
def remove_small_objects(binary_image, min_size=100):
|
||||
"""Removes small connected components from a binary image."""
|
||||
return morphology.remove_small_objects(binary_image, min_size=min_size)
|
||||
|
||||
|
||||
- **Component Architecture:**
|
||||
- Design components with clear responsibilities and well-defined interfaces.
|
||||
- Favor composition over inheritance for greater flexibility.
|
||||
- Use abstract base classes (ABCs) to define interfaces for components.
|
||||
- Example:
|
||||
python
|
||||
from abc import ABC, abstractmethod
|
||||
|
||||
class ImageProcessor(ABC):
|
||||
@abstractmethod
|
||||
def process_image(self, image):
|
||||
pass
|
||||
|
||||
class GrayscaleConverter(ImageProcessor):
|
||||
def process_image(self, image):
|
||||
from skimage.color import rgb2gray
|
||||
return rgb2gray(image)
|
||||
|
||||
|
||||
- **Code Splitting Strategies:**
|
||||
- Decompose complex image processing pipelines into smaller, reusable functions.
|
||||
- Use generators or iterators for processing large images in chunks.
|
||||
- Consider using multiprocessing or multithreading for parallel processing of image regions.
|
||||
- Utilize lazy loading techniques for large image datasets.
|
||||
|
||||
### 2. Common Patterns and Anti-patterns:
|
||||
|
||||
- **Design Patterns:**
|
||||
- **Factory Pattern:** Use factory functions or classes to create image processing objects.
|
||||
- **Strategy Pattern:** Implement different image processing algorithms as strategies that can be swapped at runtime.
|
||||
- **Observer Pattern:** Notify observers when an image processing operation completes.
|
||||
|
||||
- **Recommended Approaches:**
|
||||
- Use NumPy arrays as the primary data structure for image representation.
|
||||
- Leverage scikit-image's functional API for modular and composable image processing pipelines.
|
||||
- Use `img_as_float` or other data type conversion utilities to ensure consistent data types.
|
||||
- Document image processing functions and classes using docstrings.
|
||||
|
||||
- **Anti-patterns and Code Smells:**
|
||||
- **Global State:** Avoid using global variables to store image data or processing parameters.
|
||||
- **Magic Numbers:** Use named constants instead of hardcoded numerical values.
|
||||
- **Deeply Nested Loops:** Optimize image processing loops using NumPy's vectorized operations.
|
||||
- **Ignoring Data Types:** Always be aware of the data types of images and intermediate results.
|
||||
- **Over-Complicating Code:** Aim for simplicity and readability in your image processing code.
|
||||
|
||||
- **State Management:**
|
||||
- Encapsulate state within classes or data structures.
|
||||
- Use immutable data structures where possible.
|
||||
- Avoid modifying image data in-place unless necessary.
|
||||
|
||||
- **Error Handling:**
|
||||
- Use try-except blocks to handle potential exceptions (e.g., file I/O errors, invalid image formats).
|
||||
- Log errors and warnings using the `logging` module.
|
||||
- Provide informative error messages to the user.
|
||||
- Consider custom exception types for scikit-image related errors.
|
||||
- Example:
|
||||
python
|
||||
import logging
|
||||
from skimage import io
|
||||
|
||||
logging.basicConfig(level=logging.ERROR)
|
||||
|
||||
def load_image(filepath):
|
||||
try:
|
||||
image = io.imread(filepath)
|
||||
return image
|
||||
except FileNotFoundError:
|
||||
logging.error(f"File not found: {filepath}")
|
||||
return None
|
||||
except Exception as e:
|
||||
logging.exception(f"Error loading image: {e}")
|
||||
return None
|
||||
|
||||
|
||||
### 3. Performance Considerations:
|
||||
|
||||
- **Optimization Techniques:**
|
||||
- Vectorize image processing operations using NumPy's broadcasting and array manipulation features.
|
||||
- Use Cython to optimize performance-critical sections of code.
|
||||
- Explore Numba for just-in-time (JIT) compilation of image processing functions.
|
||||
- Utilize `skimage.util.apply_parallel` for parallel processing of image regions.
|
||||
- Example using NumPy vectorization:
|
||||
python
|
||||
import numpy as np
|
||||
|
||||
def brighten_image(image, factor=1.5):
|
||||
"""Brightens an image by multiplying each pixel by a factor."""
|
||||
return np.clip(image * factor, 0, 255).astype(image.dtype) # Clip values to valid range
|
||||
|
||||
|
||||
- **Memory Management:**
|
||||
- Use appropriate data types to minimize memory usage (e.g., `uint8` for grayscale images).
|
||||
- Release large image arrays when they are no longer needed.
|
||||
- Avoid creating unnecessary copies of image data.
|
||||
- Consider using memory-mapped arrays for very large images.
|
||||
|
||||
- **Rendering Optimization:**
|
||||
- Optimize image display using appropriate colormaps and scaling.
|
||||
- Use hardware acceleration (e.g., OpenGL) for faster rendering.
|
||||
|
||||
- **Bundle Size Optimization:**
|
||||
- Minimize dependencies in your scikit-image projects.
|
||||
- Use tree shaking to remove unused code from your bundles.
|
||||
- Compress image assets using appropriate compression algorithms.
|
||||
|
||||
- **Lazy Loading:**
|
||||
- Load large images only when they are needed.
|
||||
- Use generators or iterators to process images in chunks.
|
||||
- Implement caching mechanisms to avoid redundant image loading.
|
||||
|
||||
### 4. Security Best Practices:
|
||||
|
||||
- **Common Vulnerabilities:**
|
||||
- **Denial-of-Service (DoS) Attacks:** Protect against DoS attacks by limiting the size of input images.
|
||||
- **Code Injection:** Sanitize user-provided image processing parameters to prevent code injection attacks.
|
||||
|
||||
- **Input Validation:**
|
||||
- Validate the format, size, and data type of input images.
|
||||
- Check for malicious image headers or metadata.
|
||||
- Sanitize user-provided parameters to prevent code injection.
|
||||
- Example:
|
||||
python
|
||||
from skimage import io
|
||||
|
||||
def process_image(filepath, resize_factor):
|
||||
if not isinstance(resize_factor, (int, float)):
|
||||
raise ValueError("Resize factor must be a number.")
|
||||
if resize_factor <= 0:
|
||||
raise ValueError("Resize factor must be positive.")
|
||||
|
||||
try:
|
||||
image = io.imread(filepath)
|
||||
# Perform image processing operations using resize_factor
|
||||
except Exception as e:
|
||||
print(f"Error processing image: {e}")
|
||||
|
||||
|
||||
- **Authentication and Authorization:**
|
||||
- Implement authentication and authorization mechanisms to control access to image processing resources.
|
||||
- Use secure protocols (e.g., HTTPS) for API communication.
|
||||
|
||||
- **Data Protection:**
|
||||
- Encrypt sensitive image data at rest and in transit.
|
||||
- Implement access control policies to protect image data.
|
||||
- Use secure storage mechanisms for image data.
|
||||
|
||||
- **Secure API Communication:**
|
||||
- Use HTTPS for all API communication.
|
||||
- Implement rate limiting to prevent abuse.
|
||||
- Use input validation to prevent injection attacks.
|
||||
|
||||
### 5. Testing Approaches:
|
||||
|
||||
- **Unit Testing:**
|
||||
- Write unit tests for individual functions and classes.
|
||||
- Use mocking and stubbing to isolate components during testing.
|
||||
- Test edge cases and boundary conditions.
|
||||
|
||||
- **Integration Testing:**
|
||||
- Write integration tests to verify the interaction between components.
|
||||
- Test complex image processing pipelines.
|
||||
- Use realistic test data.
|
||||
|
||||
- **End-to-End Testing:**
|
||||
- Write end-to-end tests to verify the entire application workflow.
|
||||
- Use automated testing frameworks (e.g., Selenium).
|
||||
|
||||
- **Test Organization:**
|
||||
- Organize tests into separate directories for unit, integration, and end-to-end tests.
|
||||
- Use descriptive test names.
|
||||
- Follow a consistent testing style.
|
||||
|
||||
- **Mocking and Stubbing:**
|
||||
- Use mocking libraries (e.g., `unittest.mock`) to replace external dependencies with mock objects.
|
||||
- Use stubbing to provide predefined outputs for specific function calls.
|
||||
|
||||
### 6. Common Pitfalls and Gotchas:
|
||||
|
||||
- **Data Type Issues:**
|
||||
- Be aware of the data types of images and intermediate results.
|
||||
- Use `img_as_float` or other data type conversion utilities to ensure consistent data types.
|
||||
- Pay attention to data type ranges (e.g., 0-255 for `uint8`, 0.0-1.0 for float).
|
||||
|
||||
- **Coordinate Conventions:**
|
||||
- Understand the coordinate conventions used by scikit-image (row, col) and NumPy.
|
||||
|
||||
- **Memory Consumption:**
|
||||
- Avoid creating unnecessary copies of image data.
|
||||
- Process large images in chunks or tiles.
|
||||
|
||||
- **Version Compatibility:**
|
||||
- Be aware of version-specific API changes and deprecations.
|
||||
- Check scikit-image's changelog for breaking changes.
|
||||
|
||||
- **Image I/O Issues:**
|
||||
- Use appropriate image formats for your application.
|
||||
- Handle file I/O errors gracefully.
|
||||
|
||||
### 7. Tooling and Environment:
|
||||
|
||||
- **Recommended Development Tools:**
|
||||
- IDE: VS Code, PyCharm
|
||||
- Debugger: pdb, ipdb
|
||||
- Profiler: cProfile, line_profiler
|
||||
|
||||
- **Build Configuration:**
|
||||
- Use `pyproject.toml` to manage project metadata and build dependencies.
|
||||
- Use `requirements.txt` to specify project dependencies.
|
||||
|
||||
- **Linting and Formatting:**
|
||||
- Use a linter (e.g., flake8, pylint) to enforce coding style and detect errors.
|
||||
- Use a formatter (e.g., black, autopep8) to automatically format code.
|
||||
- Configure your IDE to run linters and formatters automatically.
|
||||
|
||||
- **Deployment:**
|
||||
- Use virtual environments to isolate project dependencies.
|
||||
- Containerize your scikit-image applications using Docker.
|
||||
- Deploy your applications to cloud platforms (e.g., AWS, Azure, GCP).
|
||||
|
||||
- **CI/CD Integration:**
|
||||
- Use a CI/CD pipeline (e.g., GitHub Actions, GitLab CI, Jenkins) to automate testing, building, and deployment.
|
||||
- Run linters, formatters, and tests in your CI/CD pipeline.
|
||||
- Use code coverage tools to measure the effectiveness of your tests.
|
||||
|
||||
By adhering to these best practices, you can develop robust, maintainable, and performant image processing applications using the scikit-image library.
|
||||
Reference in New Issue
Block a user