Views
No views yet
| Metric | Value |
|---|---|
| Accuracy | 1.0000 |
| Precision | 1.0000 |
| Recall | 1.0000 |
| F1 Score | 1.0000 |
| Parameters | 23,473 |
| Inference | <1ms (CPU) |
1import numpy as np
2import cv2
3import torch
4import torch.nn as nn
5
6class ScreenClassifier(nn.Module):
7 def __init__(self):
8 super().__init__()
9 self.features = nn.Sequential(
10 nn.Conv2d(1, 16, 3, padding=1, bias=False), nn.BatchNorm2d(16), nn.ReLU(True), nn.MaxPool2d(2),
11 nn.Conv2d(16, 32, 3, padding=1, bias=False), nn.BatchNorm2d(32), nn.ReLU(True), nn.MaxPool2d(2),
12 nn.Conv2d(32, 64, 3, padding=1, bias=False), nn.BatchNorm2d(64), nn.ReLU(True), nn.AdaptiveAvgPool2d(1),
13 )
14 self.classifier = nn.Sequential(nn.Flatten(), nn.Dropout(0.3), nn.Linear(64, 1))
15
16 def forward(self, x):
17 return self.classifier(self.features(x))
18
19# Load
20model = ScreenClassifier()
21model.load_state_dict(torch.load("screen_classifier_best.pth", map_location="cpu", weights_only=True))
22model.eval()
23
24# Predict from OpenCV frame
25frame = cv2.imread("phone_screen.jpg")
26gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
27resized = cv2.resize(gray, (64, 64), interpolation=cv2.INTER_AREA)
28tensor = torch.from_numpy(resized.astype(np.float32)).div(255.0)
29tensor = (tensor - 0.5) / 0.5
30tensor = tensor.unsqueeze(0).unsqueeze(0)
31
32with torch.no_grad():
33 prob = torch.sigmoid(model(tensor).squeeze()).item()
34
35label = "ON" if prob >= 0.5 else "OFF"
36confidence = prob if label == "ON" else 1.0 - prob
37print(f"{label} (confidence: {confidence:.1%})")screen_classifier_best.pth — PyTorch state dictscreen_classifier_best.pt — TorchScript (deploy without class definition)metrics.json — Training metricsscreen_classifier.py — Full training + inference code