File size: 6,005 Bytes
cc1d1af | 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 | # contentClassifier.py - Lightweight Content Detection
# FROZEN - DO NOT MODIFY
import numpy as np
from PIL import Image
from collections import Counter
class ContentClassifier:
"""Lightweight content detection - FROZEN."""
def __init__(self):
self.categories = [
'simple_graphic', 'human_hair', 'human', 'anime',
'logo_icon', 'product_white_bg', 'general_photo', 'complex'
]
def classify(self, image: Image.Image) -> dict:
"""Classify image content."""
if image.mode != 'RGB':
image = image.convert('RGB')
small = image.copy()
small.thumbnail((150, 150), Image.Resampling.LANCZOS)
np_img = np.array(small)
h, w = np_img.shape[:2]
signals = {
'dimensions': (w, h),
'aspect_ratio': h / w if w > 0 else 0,
'border_uniformity': self._border_uniformity(np_img),
'edge_density': self._edge_density(np_img),
'color_complexity': self._color_complexity(small),
'skin_score': self._skin_score(np_img),
'border_connected': self._border_connected(np_img),
'texture': self._texture(np_img)
}
category = self._classify(signals)
confidence = self._calculate_confidence(category, signals)
return {
'category': category,
'confidence': confidence,
'signals': signals
}
def _border_uniformity(self, np_img: np.ndarray) -> float:
h, w = np_img.shape[:2]
border_pixels = []
step = max(1, min(h, w) // 10)
for x in range(0, w, step):
border_pixels.append(tuple(np_img[0, x][:3]))
border_pixels.append(tuple(np_img[h-1, x][:3]))
for y in range(0, h, step):
border_pixels.append(tuple(np_img[y, 0][:3]))
border_pixels.append(tuple(np_img[y, w-1][:3]))
if not border_pixels:
return 0.0
unique = len(set(border_pixels))
return 1 - (unique / len(border_pixels))
def _edge_density(self, np_img: np.ndarray) -> float:
gray = np.mean(np_img, axis=2).astype(np.float32)
grad_x = np.abs(gray[:, 1:] - gray[:, :-1])
grad_y = np.abs(gray[1:, :] - gray[:-1, :])
edges = (grad_x > 25).sum() + (grad_y > 25).sum()
total = (gray.shape[0] - 1) * gray.shape[1] + gray.shape[0] * (gray.shape[1] - 1)
return edges / total if total > 0 else 0
def _color_complexity(self, image: Image.Image) -> float:
quantized = image.quantize(colors=32)
unique = len(quantized.getcolors())
return min(1.0, unique / 32)
def _skin_score(self, np_img: np.ndarray) -> float:
h, w = np_img.shape[:2]
pixels = []
step = max(1, min(h, w) // 5)
for y in range(0, h, step):
for x in range(0, w, step):
pixels.append(np_img[y, x][:3])
skin = 0
for r, g, b in pixels:
if (r > 60 and g > 40 and b > 20 and
r > g and r > b and
abs(r - g) < 60 and abs(r - b) < 60):
skin += 1
return skin / len(pixels) if pixels else 0
def _border_connected(self, np_img: np.ndarray) -> float:
h, w = np_img.shape[:2]
border_colors = set()
border_colors.add(tuple(np_img[0, 0][:3]))
border_colors.add(tuple(np_img[0, w-1][:3]))
border_colors.add(tuple(np_img[h-1, 0][:3]))
border_colors.add(tuple(np_img[h-1, w-1][:3]))
interior_colors = set()
step = max(1, min(h, w) // 4)
for y in range(h//4, 3*h//4, step):
for x in range(w//4, 3*w//4, step):
interior_colors.add(tuple(np_img[y, x][:3]))
overlap = border_colors & interior_colors
return len(overlap) / max(len(border_colors), 1)
def _texture(self, np_img: np.ndarray) -> float:
gray = np.mean(np_img, axis=2).astype(np.float32)
variance = np.var(gray)
return min(1.0, variance / 5000)
def _classify(self, signals: dict) -> str:
s = signals
# Simple graphic
if (s['color_complexity'] < 0.3 and
s['edge_density'] > 0.3 and
s['border_uniformity'] > 0.7):
return 'simple_graphic'
# Human with hair
if (s['skin_score'] > 0.15 and
s['texture'] > 0.3 and
s['edge_density'] > 0.2):
return 'human_hair'
# Human
if s['skin_score'] > 0.1:
return 'human'
# Anime
if (s['skin_score'] < 0.08 and
s['color_complexity'] > 0.3 and
s['texture'] < 0.3 and
s['edge_density'] > 0.3):
return 'anime'
# Logo/icon
if (s['edge_density'] > 0.4 and
s['color_complexity'] < 0.3 and
s['border_uniformity'] > 0.6):
return 'logo_icon'
# Product on white bg
if (s['border_uniformity'] > 0.6 and
s['color_complexity'] < 0.5 and
s['edge_density'] < 0.4):
return 'product_white_bg'
# General photo
if s['color_complexity'] > 0.3:
return 'general_photo'
return 'complex'
def _calculate_confidence(self, category: str, signals: dict) -> float:
base = 0.7
if category == 'simple_graphic':
if signals['border_uniformity'] > 0.8:
base += 0.2
elif category == 'human_hair':
if signals['skin_score'] > 0.2 and signals['texture'] > 0.4:
base += 0.2
elif category == 'human':
if signals['skin_score'] > 0.15:
base += 0.2
return min(1.0, base) |