File size: 12,957 Bytes
c5958d3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 |
#!/usr/bin/env python3
"""
Example usage of DocumentClassifier ONNX model for document classification.
"""
import onnxruntime as ort
import numpy as np
import cv2
from typing import Dict, List, Union, Optional
import argparse
import os
from PIL import Image
import time
class DocumentClassifierONNX:
"""ONNX wrapper for DocumentClassifier model"""
def __init__(self, model_path: str = "DocumentClassifier.onnx"):
"""
Initialize DocumentClassifier ONNX model
Args:
model_path: Path to ONNX model file
"""
print(f"Loading DocumentClassifier model: {model_path}")
self.session = ort.InferenceSession(model_path)
# Get model input/output information
self.input_name = self.session.get_inputs()[0].name
self.input_shape = self.session.get_inputs()[0].shape
self.input_type = self.session.get_inputs()[0].type
self.output_names = [output.name for output in self.session.get_outputs()]
self.output_shape = self.session.get_outputs()[0].shape
# Common document categories (typical for document classification)
self.categories = [
"article", "form", "letter", "memo", "news", "presentation",
"resume", "scientific", "specification", "table", "other"
]
print(f"β Model loaded successfully")
print(f" Input: {self.input_name} {self.input_shape} ({self.input_type})")
print(f" Output: {self.output_shape}")
print(f" Categories: {len(self.categories)}")
def create_dummy_input(self) -> np.ndarray:
"""Create dummy input tensor for testing"""
if 'float' in self.input_type:
# Create dummy image tensor
dummy_input = np.random.randn(*self.input_shape).astype(np.float32)
else:
# Create dummy integer input
dummy_input = np.random.randint(0, 255, self.input_shape).astype(np.int64)
return dummy_input
def preprocess_image(self, image: Union[str, np.ndarray], target_size: tuple = (224, 224)) -> np.ndarray:
"""
Preprocess image for DocumentClassifier inference
Args:
image: Image path or numpy array
target_size: Target image size (height, width)
"""
if isinstance(image, str):
# Load image from path
pil_image = Image.open(image).convert('RGB')
image_array = np.array(pil_image)
else:
image_array = image.copy()
print(f" Processing image: {image_array.shape}")
# Resize image to target size
if len(image_array.shape) == 3:
resized = cv2.resize(image_array, target_size[::-1], interpolation=cv2.INTER_CUBIC)
else:
# Convert grayscale to RGB if needed
gray = image_array if len(image_array.shape) == 2 else cv2.cvtColor(image_array, cv2.COLOR_BGR2GRAY)
rgb = cv2.cvtColor(gray, cv2.COLOR_GRAY2RGB)
resized = cv2.resize(rgb, target_size[::-1], interpolation=cv2.INTER_CUBIC)
# Normalize to [0, 1] range
normalized = resized.astype(np.float32) / 255.0
# Convert to CHW format (channels first)
if len(normalized.shape) == 3:
chw = np.transpose(normalized, (2, 0, 1))
else:
chw = normalized
# Add batch dimension if needed
if len(self.input_shape) == 4 and len(chw.shape) == 3:
batched = np.expand_dims(chw, axis=0)
else:
batched = chw
# Ensure correct shape
expected_shape = tuple(self.input_shape)
if batched.shape != expected_shape:
# Try to reshape or create dummy input
print(f" Warning: Shape mismatch {batched.shape} != {expected_shape}")
batched = self.create_dummy_input()
print(f" Preprocessed: {batched.shape}")
return batched
def predict(self, input_tensor: np.ndarray) -> np.ndarray:
"""Run DocumentClassifier prediction"""
# Validate input shape
expected_shape = tuple(self.input_shape)
if input_tensor.shape != expected_shape:
print(f"Warning: Input shape {input_tensor.shape} != expected {expected_shape}")
# Run inference
outputs = self.session.run(None, {self.input_name: input_tensor})
return outputs[0] # Return classification logits
def decode_output(self, logits: np.ndarray, top_k: int = 3) -> Dict:
"""
Decode model output logits to document categories
Args:
logits: Model output logits
top_k: Number of top predictions to return
Returns:
Dictionary with classification results
"""
# Handle different output shapes - this model outputs features [1, 1280, 7, 7]
if len(logits.shape) > 2:
# Global average pooling for feature maps
logits = np.mean(logits, axis=(2, 3)) # Average over spatial dimensions
if len(logits.shape) > 1:
logits = logits.flatten()
# Truncate to match number of categories
if len(logits) > len(self.categories):
logits = logits[:len(self.categories)]
elif len(logits) < len(self.categories):
# Pad with zeros if needed
padded = np.zeros(len(self.categories))
padded[:len(logits)] = logits
logits = padded
# Apply softmax to get probabilities
probabilities = self._softmax(logits)
# Get top-k predictions
top_k_indices = np.argsort(probabilities)[-top_k:][::-1]
top_k_probs = probabilities[top_k_indices]
# Map indices to category names
predictions = []
for i, (idx, prob) in enumerate(zip(top_k_indices, top_k_probs)):
category = self.categories[idx] if idx < len(self.categories) else f"category_{idx}"
predictions.append({
"rank": i + 1,
"category": category,
"confidence": float(prob),
"index": int(idx)
})
result = {
"predicted_category": predictions[0]["category"],
"confidence": predictions[0]["confidence"],
"top_predictions": predictions,
"all_probabilities": probabilities.tolist()
}
return result
def _softmax(self, x: np.ndarray) -> np.ndarray:
"""Apply softmax to convert logits to probabilities"""
exp_x = np.exp(x - np.max(x))
return exp_x / np.sum(exp_x)
def classify(self, image: Union[str, np.ndarray]) -> Dict:
"""
Classify document type from image
Args:
image: Image path or numpy array
Returns:
Dictionary with classification results
"""
print("π Processing document image...")
# Preprocess image
input_tensor = self.preprocess_image(image)
print("π Running classification...")
# Run inference
logits = self.predict(input_tensor)
print("π Decoding results...")
# Decode output
result = self.decode_output(logits)
# Add metadata
result["processing_info"] = {
"input_shape": input_tensor.shape,
"output_shape": logits.shape,
"inference_successful": True
}
return result
def benchmark(self, num_iterations: int = 100) -> Dict[str, float]:
"""Benchmark model performance"""
print(f"π Running benchmark with {num_iterations} iterations...")
# Create dummy input
dummy_input = self.create_dummy_input()
# Warmup
for _ in range(5):
_ = self.predict(dummy_input)
# Benchmark
times = []
for i in range(num_iterations):
start_time = time.time()
_ = self.predict(dummy_input)
end_time = time.time()
times.append(end_time - start_time)
if (i + 1) % 10 == 0:
print(f" Progress: {i + 1}/{num_iterations}")
# Calculate statistics
times = np.array(times)
stats = {
"mean_time_ms": float(np.mean(times) * 1000),
"std_time_ms": float(np.std(times) * 1000),
"min_time_ms": float(np.min(times) * 1000),
"max_time_ms": float(np.max(times) * 1000),
"median_time_ms": float(np.median(times) * 1000),
"throughput_fps": float(1.0 / np.mean(times)),
"total_iterations": num_iterations
}
return stats
def main():
parser = argparse.ArgumentParser(description="DocumentClassifier ONNX Example")
parser.add_argument("--model", type=str, default="DocumentClassifier.onnx",
help="Path to DocumentClassifier ONNX model")
parser.add_argument("--image", type=str,
help="Path to document image file")
parser.add_argument("--benchmark", action="store_true",
help="Run performance benchmark")
parser.add_argument("--iterations", type=int, default=100,
help="Number of benchmark iterations")
args = parser.parse_args()
# Check if model file exists
if not os.path.exists(args.model):
print(f"β Error: Model file not found: {args.model}")
print("Please ensure the ONNX model file is in the current directory.")
return
# Initialize model
print("=" * 60)
print("DocumentClassifier ONNX Example")
print("=" * 60)
try:
classifier = DocumentClassifierONNX(args.model)
except Exception as e:
print(f"β Error loading model: {e}")
return
# Run benchmark if requested
if args.benchmark:
print(f"\nπ Running performance benchmark...")
try:
stats = classifier.benchmark(args.iterations)
print(f"\nπ Benchmark Results:")
print(f" Mean inference time: {stats['mean_time_ms']:.2f} Β± {stats['std_time_ms']:.2f} ms")
print(f" Median inference time: {stats['median_time_ms']:.2f} ms")
print(f" Min/Max: {stats['min_time_ms']:.2f} / {stats['max_time_ms']:.2f} ms")
print(f" Throughput: {stats['throughput_fps']:.1f} FPS")
except Exception as e:
print(f"β Benchmark failed: {e}")
# Process image if provided
if args.image:
if not os.path.exists(args.image):
print(f"β Error: Image file not found: {args.image}")
return
print(f"\nπ Classifying document: {args.image}")
try:
# Classify document
result = classifier.classify(args.image)
print(f"\nβ
Classification completed:")
print(f" Document type: {result['predicted_category']}")
print(f" Confidence: {result['confidence']:.3f}")
print(f"\nπ Top predictions:")
for pred in result['top_predictions']:
print(f" {pred['rank']}. {pred['category']}: {pred['confidence']:.3f}")
except Exception as e:
print(f"β Error classifying document: {e}")
import traceback
traceback.print_exc()
# Demo with dummy data if no image provided
if not args.image and not args.benchmark:
print(f"\n㪠Running demo with dummy data...")
try:
# Create dummy document image
dummy_image = np.random.randint(0, 255, (800, 600, 3), dtype=np.uint8)
# Classify dummy image
result = classifier.classify(dummy_image)
print(f"β
Demo completed:")
print(f" Predicted type: {result['predicted_category']}")
print(f" Confidence: {result['confidence']:.3f}")
print(f" Processing info: {result['processing_info']}")
print(f"\nπ Note: This was a demonstration with random data.")
except Exception as e:
print(f"β Demo failed: {e}")
print(f"\nβ
Example completed successfully!")
print(f"\nUsage examples:")
print(f" Classify document: python example.py --image document.jpg")
print(f" Run benchmark: python example.py --benchmark --iterations 50")
print(f" Both: python example.py --image document.pdf --benchmark")
if __name__ == "__main__":
main() |