Verificacao de Identidade Bovina
Envie 3 fotos de referencia de um animal conhecido e 1 foto de prova para verificar se pertencem ao mesmo individuo. O sistema utiliza um ensemble de 3 modelos siameses com perda triplet para comparar embeddings do focinho bovino -- a "digital" unica de cada animal.
Como Funciona
1
Cadastrar
3 fotos do focinho de referencia
→
2
Verificar
1 foto de prova
→
3
Resultado
Mesmo animal? + confianca
Criterios de Decisao
Todos os criterios devem ser atendidos para decision.verdict retornar MATCH:
| Metrica | Limiar | Unidade | Descricao |
| Similaridade Cosseno | >= 0.60 | [0.0, 1.0] | Similaridade probe vs template de referencia. Maior = mais similar. |
| Distancia Euclidiana | <= 0.85 | [0.0, ~2.0] | Distancia no espaco de embeddings. Menor = mais similar. |
| Similaridade Mutua | >= 0.55 | [0.0, 1.0] | Consistencia entre as 3 referencias. Maior = referencias sao do mesmo animal. |
| Verificacao de Dominio | passar | binario | Fotos devem ser focinhos validos, nao ruido ou imagens fora do dominio. |
Exemplo de Requisicao
Exemplo JSON com 3 referencias e 1 probe em base64:
curl -X POST http://127.0.0.1:8000/predict \
-H "Content-Type: application/json" \
-H "X-API-Key: SUA_API_KEY" \
-d '{
"reference_photos": [
"BASE64_REF_1",
"BASE64_REF_2",
"BASE64_REF_3"
],
"probe_photo": "BASE64_PROBE"
}'
Campos da Resposta CONSUMER-FACING
A resposta tem 3 secoes de nivel raiz. decision e summary sao para o consumidor final. details e para debugging tecnico.
decision -- Veredicto e metricas principais
| Campo | Tipo | Range / Valores | Descricao |
decision.verdict | string | "MATCH" | "NO_MATCH" | "INVALID_INPUT" |
MATCH = probe e o mesmo animal das referencias. NO_MATCH = animal diferente. INVALID_INPUT = fotos fora do dominio ou referencias inconsistentes entre si. |
decision.score | float | [0.0, 1.0] |
ESTA E A METRICA PRINCIPAL. Similaridade cosseno do ensemble. Mostre este numero ao usuario final. Quanto mais proximo de 1.0, maior a similaridade. O veredicto e determinado comparando este valor com PREDICT_COSINE_THRESHOLD. |
decision.confidence | float | [0.0, 1.0] |
Score de confianca derivado da distancia euclidiana. Formula: max(0, min(1, (threshold - distance) / threshold)). Quanto maior, mais confiavel o veredicto. 0.0 = distancias muito altas, definitivamente animais diferentes. |
decision.confidence_label | string | "NOT_THE_ANIMAL" | "FAIR" | "GOOD" | "EXCELLENT" |
Classificacao de confianca em texto. NOT_THE_ANIMAL = confidence 0.0, definitely different. EXCELLENT = near-certain match. |
decision.explanation | string | texto |
Explicacao em texto do resultado. Use este campo para exibir ao usuario final sem precisar interpretar valores numericos. |
summary -- Detalhamento dos criterios
| Campo | Tipo | Descricao |
summary.criteria[].metric | string |
Nome da metrica: cosine_similarity, euclidean_distance, mutual_similarity, domain_check. Use para identificar programaticamente qual criterio foi avaliado. |
summary.criteria[].value | float |
Valor observado da metrica para esta predicao. |
summary.criteria[].threshold | float |
Limiar usado na comparacao. Compare value vs threshold: para cosine/mutual, passed = value >= threshold; para euclidean, passed = value <= threshold. |
summary.criteria[].passed | bool |
True = criterio satisfeito. False = criterio falhou. TODOS os criterios devem passar para MATCH. |
summary.criteria[].description | string |
Explicacao em texto do que foi avaliado, valor observado, limiar e se passou. Pronto para exibir ao usuario. |
details -- Dados tecnicos por modelo TECHNICAL / DEBUG
| Campo | Tipo | Descricao |
details.models[].model_id | int |
ID do modelo TensorFlow: 60, 62, ou 64. Cada modelo e um siames treinado independentemente. Use para auditar comportamento por modelo. |
details.models[].template_vs_probe_cosine | float |
Similaridade cosseno entre o embedding medio das 3 referencias e o probe, computado neste modelo especifico. Range [0.0, 1.0]. |
details.models[].reference_vs_probe[].reference_index | int |
Indice da referencia comparada: 0 (primeira), 1 (segunda), 2 (terceira). |
details.models[].reference_vs_probe[].cosine_similarity | float |
Similaridade cosseno entre esta referencia especifica e o probe. Range [0.0, 1.0]. Valores acima de ~0.60 tipicamente indicam mesmo animal. |
details.models[].reference_vs_probe[].euclidean_distance | float |
Distancia euclidiana entre esta referencia especifica e o probe. Range [0.0, ~2.0]. Valores abaixo de ~0.85 tipicamente indicam mesmo animal. |
details.models[].mean_cosine | float |
Media das 3 similaridades cosseno por referencia. Range [0.0, 1.0]. Resume a concordancia geral entre referencias e probe. |
details.models[].min_cosine | float |
Minimo das 3 similaridades cosseno. Range [0.0, 1.0]. Score mais conservador. Se min_cosine e alto mas mean_cosine tambem, ha consistencia. |
details.models[].max_cosine | float |
Maximo das 3 similaridades cosseno. Range [0.0, 1.0]. Score mais otista. Se max >> min, as referencias podem ser inconsistentes. |
details.ensemble.template_vs_probe_cosine | float |
Similaridade cosseno no espaco do ensemble (384 dimensoes = 3 modelos x 128). Este e o valor usado em decision.score. Range [0.0, 1.0]. |
details.ensemble.template_vs_probe_distance | float |
Distancia euclidiana no espaco do ensemble. Este valor e usado para calcular decision.confidence. Range [0.0, ~2.0]. |
details.reference_mutual_similarity | float |
Media da similaridade cosseno entre todos os pares das 3 fotos de referencia. Range [0.0, 1.0]. Valores altos indicam que as 3 referencias sao do mesmo animal. Valores baixos (< PREDICT_MUTUAL_MIN) indicam que as referencias sao de animais diferentes. |
Exemplo de Resposta Completo
Caso de MATCH -- mesmas 3 referencias e probe do mesmo animal:
{
"decision": {
"verdict": "MATCH",
"score": 0.87,
"confidence": 0.61,
"confidence_label": "GOOD",
"is_same_animal": true,
"explanation": "The probe photo matches the reference animal with GOOD confidence."
},
"summary": {
"criteria": [
{"metric": "cosine_similarity", "value": 0.87, "threshold": 0.62, "passed": true, "description": "Cosine similarity (0.87) is above threshold (0.62)"},
{"metric": "euclidean_distance", "value": 0.41, "threshold": 0.85, "passed": true, "description": "Euclidean distance (0.41) is below threshold (0.85)"},
{"metric": "mutual_similarity", "value": 0.79, "threshold": 0.40, "passed": true, "description": "Reference photos are consistent (0.79 > 0.40)"},
{"metric": "domain_check", "value": 1, "threshold": 1, "passed": true, "description": "Domain check passed for all 4 photos"}
]
},
"details": {
"models": [
{
"model_id": 60,
"template_vs_probe_cosine": 0.86,
"template_vs_probe_distance": 0.44,
"reference_vs_probe": [
{"cosine": 0.85, "distance": 0.47},
{"cosine": 0.87, "distance": 0.43},
{"cosine": 0.86, "distance": 0.45}
],
"mean_cosine": 0.86,
"min_cosine": 0.85,
"max_cosine": 0.87
},
{
"model_id": 62,
"template_vs_probe_cosine": 0.88,
"template_vs_probe_distance": 0.39,
"reference_vs_probe": [
{"cosine": 0.87, "distance": 0.41},
{"cosine": 0.89, "distance": 0.38},
{"cosine": 0.88, "distance": 0.40}
],
"mean_cosine": 0.88,
"min_cosine": 0.87,
"max_cosine": 0.89
},
{
"model_id": 64,
"template_vs_probe_cosine": 0.85,
"template_vs_probe_distance": 0.51,
"reference_vs_probe": [
{"cosine": 0.84, "distance": 0.53},
{"cosine": 0.86, "distance": 0.49},
{"cosine": 0.85, "distance": 0.51}
],
"mean_cosine": 0.85,
"min_cosine": 0.84,
"max_cosine": 0.86
}
],
"ensemble": {
"template_vs_probe_cosine": 0.87,
"template_vs_probe_distance": 0.41,
"mean_cosine": 0.87,
"min_cosine": 0.84,
"max_cosine": 0.89
},
"reference_mutual_similarity": 0.79
}
}
Exemplo: NO_MATCH
Caso em que o probe e de um animal diferente das referencias:
{
"decision": {
"verdict": "NO_MATCH",
"score": 0.54,
"confidence": 0.21,
"confidence_label": "FAIR",
"is_same_animal": false,
"explanation": "The probe photo does not match the reference animal."
},
"summary": {
"criteria": [
{"metric": "cosine_similarity", "value": 0.54, "threshold": 0.62, "passed": false, "description": "Cosine similarity (0.54) is below threshold (0.62)"},
{"metric": "euclidean_distance", "value": 1.02, "threshold": 0.85, "passed": false, "description": "Euclidean distance (1.02) exceeds threshold (0.85)"},
{"metric": "mutual_similarity", "value": 0.81, "threshold": 0.40, "passed": true, "description": "Reference photos are consistent (0.81 > 0.40)"},
{"metric": "domain_check", "value": 1, "threshold": 1, "passed": true, "description": "Domain check passed for all 4 photos"}
]
},
"details": {
"models": [
{
"model_id": 60,
"template_vs_probe_cosine": 0.53,
"template_vs_probe_distance": 1.05,
"reference_vs_probe": [
{"cosine": 0.52, "distance": 1.08},
{"cosine": 0.54, "distance": 1.04},
{"cosine": 0.53, "distance": 1.06}
],
"mean_cosine": 0.53,
"min_cosine": 0.52,
"max_cosine": 0.54
},
{
"model_id": 62,
"template_vs_probe_cosine": 0.56,
"template_vs_probe_distance": 0.98,
"reference_vs_probe": [
{"cosine": 0.55, "distance": 1.01},
{"cosine": 0.57, "distance": 0.96},
{"cosine": 0.56, "distance": 0.99}
],
"mean_cosine": 0.56,
"min_cosine": 0.55,
"max_cosine": 0.57
},
{
"model_id": 64,
"template_vs_probe_cosine": 0.51,
"template_vs_probe_distance": 1.12,
"reference_vs_probe": [
{"cosine": 0.50, "distance": 1.15},
{"cosine": 0.52, "distance": 1.10},
{"cosine": 0.51, "distance": 1.13}
],
"mean_cosine": 0.51,
"min_cosine": 0.50,
"max_cosine": 0.52
}
],
"ensemble": {
"template_vs_probe_cosine": 0.54,
"template_vs_probe_distance": 1.02,
"mean_cosine": 0.54,
"min_cosine": 0.50,
"max_cosine": 0.57
},
"reference_mutual_similarity": 0.81
}
}
Exemplo: INVALID_INPUT
Caso em que as referencias nao sao consistentes entre si (possivelmente de animais diferentes):
{
"decision": {
"verdict": "INVALID_INPUT",
"score": 0.0,
"confidence": 0.0,
"confidence_label": "NOT_THE_ANIMAL",
"is_same_animal": false,
"explanation": "Reference photos are not consistent with each other."
},
"summary": {
"criteria": [
{"metric": "cosine_similarity", "value": 0.0, "threshold": 0.62, "passed": false, "description": "Cosine similarity (0.0) is below threshold (0.62)"},
{"metric": "euclidean_distance", "value": 0.0, "threshold": 0.85, "passed": false, "description": "Euclidean distance (0.0) is below threshold (0.85)"},
{"metric": "mutual_similarity", "value": 0.29, "threshold": 0.40, "passed": false, "description": "Reference photos are NOT consistent (0.29 < 0.40) -- possibly different animals"},
{"metric": "domain_check", "value": 1, "threshold": 1, "passed": true, "description": "Domain check passed for all 4 photos"}
]
},
"details": {
"models": [
{
"model_id": 60,
"template_vs_probe_cosine": 0.0,
"template_vs_probe_distance": 0.0,
"reference_vs_probe": [
{"cosine": 0.0, "distance": 0.0},
{"cosine": 0.0, "distance": 0.0},
{"cosine": 0.0, "distance": 0.0}
],
"mean_cosine": 0.0,
"min_cosine": 0.0,
"max_cosine": 0.0
},
{
"model_id": 62,
"template_vs_probe_cosine": 0.0,
"template_vs_probe_distance": 0.0,
"reference_vs_probe": [
{"cosine": 0.0, "distance": 0.0},
{"cosine": 0.0, "distance": 0.0},
{"cosine": 0.0, "distance": 0.0}
],
"mean_cosine": 0.0,
"min_cosine": 0.0,
"max_cosine": 0.0
},
{
"model_id": 64,
"template_vs_probe_cosine": 0.0,
"template_vs_probe_distance": 0.0,
"reference_vs_probe": [
{"cosine": 0.0, "distance": 0.0},
{"cosine": 0.0, "distance": 0.0},
{"cosine": 0.0, "distance": 0.0}
],
"mean_cosine": 0.0,
"min_cosine": 0.0,
"max_cosine": 0.0
}
],
"ensemble": {
"template_vs_probe_cosine": 0.0,
"template_vs_probe_distance": 0.0,
"mean_cosine": 0.0,
"min_cosine": 0.0,
"max_cosine": 0.0
},
"reference_mutual_similarity": 0.29
}
}