Analítica e IA
Reconocimiento facial y conteo de personas
Registra y administra personas conocidas, consulta eventos de coincidencia facial, ajusta el umbral de coincidencia y obtén analíticas de conteo de personas de las cámaras a través de la API de Rhombus.
En esta página
- Descripción general
- Requisitos previos
- Registrar y administrar personas conocidas
- Crear una persona
- Subir una imagen de rostro
- Consultar la transacción de subida
- Etiquetar a una persona
- Listar personas y matchmakers
- Actualizar o eliminar personas y rostros
- Consultar eventos de coincidencia facial
- Filtro de búsqueda
- Solicitud de página
- Interpretar un evento facial
- Ajustar la coincidencia y corregir eventos
- Leer y actualizar el umbral de coincidencia
- Corregir un evento mal identificado
- Analíticas de conteo de personas
- Serie temporal de conteo
- Conteos de ocupación a lo largo del tiempo
- Referencia: enums de reportes
- Casos de uso
- Solución de problemas
- Próximos pasos
Esta página se tradujo automáticamente. Si encuentras errores o tienes sugerencias, escríbenos.
Descripción general
Esta guía cubre dos capacidades de analítica de cámara distintas que es fácil confundir:
- Reconocimiento facial (identidad) — registra personas conocidas a partir de imágenes de rostros y luego recibe eventos de coincidencia facial cuando una cámara detecta un rostro que coincide. Cada evento incluye una puntuación de confianza y la persona que mejor coincide. Úsalo para reconocer quién aparece en la cámara.
- Conteo de personas (aforo) — analítica de cámara agregada y no identificante que cuenta cuántas personas cruzan el campo de visión de una cámara a lo largo del tiempo. Proviene del servicio de reportes como series temporales de conteo y conteos de ocupación. No implica identidad alguna.
A través de la API puedes:
- Registrar y administrar personas creando registros de persona y subiendo imágenes de rostros
- Consultar eventos de coincidencia facial con filtros enriquecidos y paginación
- Ajustar el umbral de coincidencia y corregir eventos mal identificados
- Obtener analíticas de conteo de personas como series temporales o los conteos más recientes por cámara
No es lo mismo que los sensores de ocupación. Rhombus también ofrece sensores de ocupación físicos (hardware Bluetooth/de movimiento) que reportan la presencia en una sala. Esos son un producto aparte servido por una API diferente — consulta la guía de Sensores IoT. El "conteo de personas" de esta página es analítica de cámara.
Privacidad biométrica. El reconocimiento facial procesa datos biométricos. Muchas jurisdicciones regulan la recopilación, el almacenamiento y el uso de identificadores biométricos, y algunas exigen aviso o consentimiento. Revisa las leyes de privacidad biométrica que apliquen a tus ubicaciones antes de registrar rostros y confirma las políticas de tu organización. Esta guía describe únicamente la superficie de la API — no constituye asesoría legal.
Requisitos previos
Antes de comenzar, asegúrate de tener:
- Una clave de API de Rhombus. Registrar o administrar rostros requiere permisos de administración de rostros; leer los reportes de conteo de personas requiere acceso de lectura de reportes. Genera y limita el alcance de las claves en la Consola de Rhombus, en Configuración → Integraciones y recursos para desarrolladores → Tokens de API.
- Al menos una cámara con la analítica correspondiente habilitada (reconocimiento facial para los flujos de identidad, conteo de personas para las analíticas de aforo).
- El reconocimiento facial es una función licenciada y restringida. Si los endpoints de rostros no están disponibles para tu organización, contacta a tu equipo de cuenta de Rhombus para confirmar la habilitación.
Todas las solicitudes son POST a https://api2.rhombussystems.com y se autentican con los encabezados x-auth-scheme y x-auth-apikey. Las marcas de tiempo están en milisegundos epoch salvo que se indique lo contrario, y la confianza de coincidencia es un decimal entre 0 y 1.
Registrar y administrar personas conocidas
Una persona es un registro de identidad con nombre para el que registras rostros. Un matchmaker es una plantilla de rostro registrada asociada a una persona; el motor de reconocimiento compara los rostros detectados con tus matchmakers.
Crear una persona
Crea un registro de persona con nombre para registrar rostros contra él.
import requests
headers = {
"x-auth-scheme": "api-token",
"x-auth-apikey": "YOUR_API_KEY",
"Content-Type": "application/json"
}
response = requests.post(
"https://api2.rhombussystems.com/api/faceRecognition/person/createPerson",
headers=headers,
json={"name": "Jordan Rivera"}
)
person = response.json().get("person", {})
print(f"Created person {person.get('name')} -> {person.get('uuid')}")const response = await fetch('https://api2.rhombussystems.com/api/faceRecognition/person/createPerson', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-auth-scheme': 'api-token',
'x-auth-apikey': 'YOUR_API_KEY'
},
body: JSON.stringify({ name: 'Jordan Rivera' })
});
const { person } = await response.json();
console.log(`Created person ${person.name} -> ${person.uuid}`);curl -X POST https://api2.rhombussystems.com/api/faceRecognition/person/createPerson \
-H "Content-Type: application/json" \
-H "x-auth-scheme: api-token" \
-H "x-auth-apikey: YOUR_API_KEY" \
-d '{"name": "Jordan Rivera"}'Nombre visible de la persona.
La respuesta devuelve un objeto person:
Subir una imagen de rostro
Registra un rostro subiendo una imagen .jpg o .png (máximo 5 MB) como multipart/form-data. El archivo debe enviarse bajo el nombre de campo de formulario file. Dos parámetros de consulta opcionales controlan la transacción:
transaction— un ID de transacción que proporcionas para rastrear y luego consultar la subida. Si se omite, el servidor genera uno y lo devuelve.createPersonIfNotFound— establécelo entruepara que el sistema cree una persona nueva automáticamente cuando el rostro subido no coincide con uno existente.
import requests
headers = {
"x-auth-scheme": "api-token",
"x-auth-apikey": "YOUR_API_KEY"
# NO establezcas Content-Type manualmente; requests define el límite multipart
}
with open("jordan_rivera.jpg", "rb") as f:
files = {"file": ("jordan_rivera.jpg", f, "image/jpeg")}
response = requests.post(
"https://api2.rhombussystems.com/api/faceRecognition/matchmaker/uploadFaceMatchmakers",
headers=headers,
params={"transaction": "enroll-jordan-001", "createPersonIfNotFound": "true"},
files=files
)
data = response.json()
print(f"Transaction: {data.get('transactionId')}")
for result in data.get("fileUploadResults", []):
print(f" {result.get('fileName')}: success={result.get('success')} {result.get('message', '')}")import fs from 'fs';
const form = new FormData();
const buffer = fs.readFileSync('jordan_rivera.jpg');
form.append('file', new Blob([buffer], { type: 'image/jpeg' }), 'jordan_rivera.jpg');
const url = new URL('https://api2.rhombussystems.com/api/faceRecognition/matchmaker/uploadFaceMatchmakers');
url.searchParams.set('transaction', 'enroll-jordan-001');
url.searchParams.set('createPersonIfNotFound', 'true');
const response = await fetch(url, {
method: 'POST',
headers: {
'x-auth-scheme': 'api-token',
'x-auth-apikey': 'YOUR_API_KEY'
},
body: form
});
const data = await response.json();
console.log(`Transaction: ${data.transactionId}`);
for (const result of data.fileUploadResults || []) {
console.log(` ${result.fileName}: success=${result.success} ${result.message || ''}`);
}curl -X POST "https://api2.rhombussystems.com/api/faceRecognition/matchmaker/uploadFaceMatchmakers?transaction=enroll-jordan-001&createPersonIfNotFound=true" \
-H "x-auth-scheme: api-token" \
-H "x-auth-apikey: YOUR_API_KEY" \
-F "file=@jordan_rivera.jpg;type=image/jpeg"Sube una imagen por solicitud. Envía exactamente una parte file, mantenla por debajo de 5 MB y usa .jpg o .png. Deja que tu cliente HTTP defina el límite de Content-Type: multipart/form-data — no lo establezcas manualmente.
La respuesta devuelve:
fileName, success (booleano) y message.Consultar la transacción de subida
Las imágenes de rostros se procesan de forma asíncrona. Consulta la transacción para conocer el faceId resultante y el personUuid al que se registró o vinculó el rostro.
import requests
import time
headers = {
"x-auth-scheme": "api-token",
"x-auth-apikey": "YOUR_API_KEY",
"Content-Type": "application/json"
}
for _ in range(10):
response = requests.post(
"https://api2.rhombussystems.com/api/faceRecognition/matchmaker/findFaceUploadMetadataByTransaction",
headers=headers,
json={"transactionId": "enroll-jordan-001"}
)
metadata = response.json().get("faceUploadMetadata", [])
if metadata and all(m.get("success") is not None for m in metadata):
for m in metadata:
print(f"faceId={m.get('faceId')} personUuid={m.get('personUuid')} "
f"success={m.get('success')} {m.get('errorMsg', '')}")
break
time.sleep(2)const headers = {
'Content-Type': 'application/json',
'x-auth-scheme': 'api-token',
'x-auth-apikey': 'YOUR_API_KEY'
};
for (let i = 0; i < 10; i++) {
const response = await fetch('https://api2.rhombussystems.com/api/faceRecognition/matchmaker/findFaceUploadMetadataByTransaction', {
method: 'POST',
headers,
body: JSON.stringify({ transactionId: 'enroll-jordan-001' })
});
const { faceUploadMetadata = [] } = await response.json();
if (faceUploadMetadata.length && faceUploadMetadata.every(m => m.success != null)) {
for (const m of faceUploadMetadata) {
console.log(`faceId=${m.faceId} personUuid=${m.personUuid} success=${m.success} ${m.errorMsg || ''}`);
}
break;
}
await new Promise(r => setTimeout(r, 2000));
}curl -X POST https://api2.rhombussystems.com/api/faceRecognition/matchmaker/findFaceUploadMetadataByTransaction \
-H "Content-Type: application/json" \
-H "x-auth-scheme: api-token" \
-H "x-auth-apikey: YOUR_API_KEY" \
-d '{"transactionId": "enroll-jordan-001"}'Cada entrada de faceUploadMetadata incluye:
| Campo | Tipo | Descripción |
|---|---|---|
transactionId | string | La transacción a la que pertenece esta subida |
faceId | string | Identificador del matchmaker de rostro registrado (una vez procesado) |
personUuid | string | Persona a la que se registró o vinculó el rostro |
success | boolean | Si el procesamiento tuvo éxito |
errorMsg | string | Detalle del error cuando success es false |
createdAtMillis | integer | Marca de tiempo de la subida en milisegundos epoch |
origS3Key | string | Clave de almacenamiento de la imagen original subida |
¿Prefieres registrar a una persona a partir de un rostro que la cámara ya capturó? Usa createFaceMatchmakerFromSighting con el faceEventUuid de un evento facial existente y el personUuid de destino para convertir ese avistamiento en una plantilla registrada — sin necesidad de subir nada.
Etiquetar a una persona
Adjunta etiquetas (por ejemplo, employee o visitor) para organizar a las personas y filtrar los eventos faciales más adelante.
import requests
headers = {
"x-auth-scheme": "api-token",
"x-auth-apikey": "YOUR_API_KEY",
"Content-Type": "application/json"
}
response = requests.post(
"https://api2.rhombussystems.com/api/faceRecognition/person/addPersonLabel",
headers=headers,
json={"personUuid": "YOUR_PERSON_UUID", "label": "employee"}
)
print(response.json())const response = await fetch('https://api2.rhombussystems.com/api/faceRecognition/person/addPersonLabel', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-auth-scheme': 'api-token',
'x-auth-apikey': 'YOUR_API_KEY'
},
body: JSON.stringify({ personUuid: 'YOUR_PERSON_UUID', label: 'employee' })
});
console.log(await response.json());curl -X POST https://api2.rhombussystems.com/api/faceRecognition/person/addPersonLabel \
-H "Content-Type: application/json" \
-H "x-auth-scheme: api-token" \
-H "x-auth-apikey: YOUR_API_KEY" \
-d '{"personUuid": "YOUR_PERSON_UUID", "label": "employee"}'Usa removePersonLabel con el mismo cuerpo para quitar una etiqueta, y findPersonLabelsByOrg (cuerpo vacío {}) para obtener un mapa labelsByPerson con las etiquetas de cada persona.
Listar personas y matchmakers
Lista todas las personas registradas con findPeopleByOrg, y lista las plantillas de rostro registradas con findFaceMatchmakersByOrg (o findFaceMatchmakersByPerson para una sola persona).
import requests
headers = {
"x-auth-scheme": "api-token",
"x-auth-apikey": "YOUR_API_KEY",
"Content-Type": "application/json"
}
people = requests.post(
"https://api2.rhombussystems.com/api/faceRecognition/person/findPeopleByOrg",
headers=headers, json={}
).json().get("people", [])
for person in people:
print(f"{person.get('name')} ({person.get('uuid')})")
matchmakers = requests.post(
"https://api2.rhombussystems.com/api/faceRecognition/matchmaker/findFaceMatchmakersByOrg",
headers=headers, json={}
).json().get("faceMatchmakers", [])
for mm in matchmakers:
print(f"faceId={mm.get('id')} personUuid={mm.get('personUuid')} uploaded={mm.get('uploaded')}")const headers = {
'Content-Type': 'application/json',
'x-auth-scheme': 'api-token',
'x-auth-apikey': 'YOUR_API_KEY'
};
const people = await (await fetch('https://api2.rhombussystems.com/api/faceRecognition/person/findPeopleByOrg', {
method: 'POST', headers, body: '{}'
})).json();
for (const person of people.people || []) {
console.log(`${person.name} (${person.uuid})`);
}
const matchmakers = await (await fetch('https://api2.rhombussystems.com/api/faceRecognition/matchmaker/findFaceMatchmakersByOrg', {
method: 'POST', headers, body: '{}'
})).json();
for (const mm of matchmakers.faceMatchmakers || []) {
console.log(`faceId=${mm.id} personUuid=${mm.personUuid} uploaded=${mm.uploaded}`);
}curl -X POST https://api2.rhombussystems.com/api/faceRecognition/person/findPeopleByOrg \
-H "Content-Type: application/json" \
-H "x-auth-scheme: api-token" \
-H "x-auth-apikey: YOUR_API_KEY" \
-d '{}'
curl -X POST https://api2.rhombussystems.com/api/faceRecognition/matchmaker/findFaceMatchmakersByOrg \
-H "Content-Type: application/json" \
-H "x-auth-scheme: api-token" \
-H "x-auth-apikey: YOUR_API_KEY" \
-d '{}'Cada matchmaker de rostro incluye id (el ID del rostro), personUuid, orgUuid, uploaded (booleano) y createdOn.
Actualizar o eliminar personas y rostros
| Endpoint | Cuerpo | Propósito |
|---|---|---|
/api/ | { | Obtener una persona |
/api/ | { | Actualizar nombre/correo (selectivo) |
/api/ | { | Eliminar una persona |
/api/ | { | Obtener un rostro registrado |
/api/ | { | Eliminar una plantilla de rostro registrada |
Para administrar la retención y eliminación de datos biométricos, usa deletePerson (elimina la persona y su registro) y deleteFaceMatchmaker (elimina un solo rostro registrado). Los eventos faciales se pueden eliminar individualmente con deleteFaceEvent (más abajo).
Consultar eventos de coincidencia facial
Cuando una cámara detecta un rostro, genera un evento facial. Recupera eventos con findFaceEventsByOrg, que toma un searchFilter y un pageRequest.
import requests
import time
headers = {
"x-auth-scheme": "api-token",
"x-auth-apikey": "YOUR_API_KEY",
"Content-Type": "application/json"
}
now_ms = int(time.time() * 1000)
one_day_ago_ms = now_ms - (24 * 60 * 60 * 1000)
response = requests.post(
"https://api2.rhombussystems.com/api/faceRecognition/faceEvent/findFaceEventsByOrg",
headers=headers,
json={
"searchFilter": {
"hasName": True,
"timestampFilter": {
"rangeStart": str(one_day_ago_ms),
"rangeEnd": str(now_ms)
}
},
"pageRequest": {"maxPageSize": 50}
}
)
data = response.json()
for event in data.get("faceEvents", []):
match = event.get("selectedPersonMatch") or {}
print(f"{event.get('faceName')} on {event.get('deviceUuid')} "
f"confidence={match.get('confidence')} at {event.get('eventTimestamp')}")
# Obtén la página siguiente si hay lastEvaluatedKey presente
next_key = data.get("lastEvaluatedKey")const headers = {
'Content-Type': 'application/json',
'x-auth-scheme': 'api-token',
'x-auth-apikey': 'YOUR_API_KEY'
};
const now = Date.now();
const oneDayAgo = now - (24 * 60 * 60 * 1000);
const response = await fetch('https://api2.rhombussystems.com/api/faceRecognition/faceEvent/findFaceEventsByOrg', {
method: 'POST',
headers,
body: JSON.stringify({
searchFilter: {
hasName: true,
timestampFilter: {
rangeStart: String(oneDayAgo),
rangeEnd: String(now)
}
},
pageRequest: { maxPageSize: 50 }
})
});
const data = await response.json();
for (const event of data.faceEvents || []) {
const match = event.selectedPersonMatch || {};
console.log(`${event.faceName} on ${event.deviceUuid} confidence=${match.confidence} at ${event.eventTimestamp}`);
}
const nextKey = data.lastEvaluatedKey;curl -X POST https://api2.rhombussystems.com/api/faceRecognition/faceEvent/findFaceEventsByOrg \
-H "Content-Type: application/json" \
-H "x-auth-scheme: api-token" \
-H "x-auth-apikey: YOUR_API_KEY" \
-d '{
"searchFilter": {
"hasName": true,
"timestampFilter": {
"rangeStart": "1712620800000",
"rangeEnd": "1712707200000"
}
},
"pageRequest": { "maxPageSize": 50 }
}'Filtro de búsqueda
Todos los campos de searchFilter son opcionales. Cuando se omite timestampFilter, la búsqueda usa por defecto los últimos 7 días.
faceNames si ambos están definidos.true) o ausencia (false) de un nombre de persona coincidente.rangeStart y rangeEnd, cada uno una cadena que contiene un valor en milisegundos epoch (inclusive). Por defecto usa los últimos 7 días.Solicitud de página
lastEvaluatedKey de la respuesta anterior para obtener la página siguiente. Ausente cuando no hay más resultados.Interpretar un evento facial
Cada evento en faceEvents es un objeto con estos campos:
name de selectedPersonMatch cuando se seleccionó una coincidencia.uuid, name, faceId y confidence (0–1). Nula cuando no se seleccionó ninguna coincidencia.uuid, name, faceId y confidence (0–1). Útil para revisar coincidencias cercanas.Obtén un solo evento por su UUID con getFaceEvent (cuerpo { "eventUuid": "..." }).
Ajustar la coincidencia y corregir eventos
Leer y actualizar el umbral de coincidencia
El umbral de coincidencia controla qué tan estricta es la coincidencia facial. Es un valor de confianza entre 0 y 1 — un valor más alto exige una coincidencia más cercana (menos falsos positivos, más omisiones); un valor más bajo es más permisivo.
import requests
headers = {
"x-auth-scheme": "api-token",
"x-auth-apikey": "YOUR_API_KEY",
"Content-Type": "application/json"
}
# Leer el umbral actual
current = requests.post(
"https://api2.rhombussystems.com/api/faceRecognition/matchmaker/getFaceMatchingConfig",
headers=headers, json={}
).json()
print(f"Current threshold: {current.get('faceMatchConfidenceThreshold')}")
# Subir el umbral para reducir falsos positivos
updated = requests.post(
"https://api2.rhombussystems.com/api/faceRecognition/matchmaker/updateFaceMatchingConfig",
headers=headers,
json={"faceMatchConfidenceThreshold": 0.8}
).json()
print(f"New threshold: {updated.get('faceMatchConfidenceThreshold')}")const headers = {
'Content-Type': 'application/json',
'x-auth-scheme': 'api-token',
'x-auth-apikey': 'YOUR_API_KEY'
};
const current = await (await fetch('https://api2.rhombussystems.com/api/faceRecognition/matchmaker/getFaceMatchingConfig', {
method: 'POST', headers, body: '{}'
})).json();
console.log(`Current threshold: ${current.faceMatchConfidenceThreshold}`);
const updated = await (await fetch('https://api2.rhombussystems.com/api/faceRecognition/matchmaker/updateFaceMatchingConfig', {
method: 'POST', headers, body: JSON.stringify({ faceMatchConfidenceThreshold: 0.8 })
})).json();
console.log(`New threshold: ${updated.faceMatchConfidenceThreshold}`);curl -X POST https://api2.rhombussystems.com/api/faceRecognition/matchmaker/getFaceMatchingConfig \
-H "Content-Type: application/json" \
-H "x-auth-scheme: api-token" \
-H "x-auth-apikey: YOUR_API_KEY" \
-d '{}'
curl -X POST https://api2.rhombussystems.com/api/faceRecognition/matchmaker/updateFaceMatchingConfig \
-H "Content-Type: application/json" \
-H "x-auth-scheme: api-token" \
-H "x-auth-apikey: YOUR_API_KEY" \
-d '{"faceMatchConfidenceThreshold": 0.8}'Corregir un evento mal identificado
Reasigna un evento facial a la persona correcta (o establece un nombre directamente) con updateFaceEvent. Así corriges coincidencias erróneas.
import requests
headers = {
"x-auth-scheme": "api-token",
"x-auth-apikey": "YOUR_API_KEY",
"Content-Type": "application/json"
}
response = requests.post(
"https://api2.rhombussystems.com/api/faceRecognition/faceEvent/updateFaceEvent",
headers=headers,
json={
"eventUuid": "YOUR_FACE_EVENT_UUID",
"personUuid": "CORRECT_PERSON_UUID"
}
)
print(response.json())const response = await fetch('https://api2.rhombussystems.com/api/faceRecognition/faceEvent/updateFaceEvent', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-auth-scheme': 'api-token',
'x-auth-apikey': 'YOUR_API_KEY'
},
body: JSON.stringify({
eventUuid: 'YOUR_FACE_EVENT_UUID',
personUuid: 'CORRECT_PERSON_UUID'
})
});
console.log(await response.json());curl -X POST https://api2.rhombussystems.com/api/faceRecognition/faceEvent/updateFaceEvent \
-H "Content-Type: application/json" \
-H "x-auth-scheme: api-token" \
-H "x-auth-apikey: YOUR_API_KEY" \
-d '{
"eventUuid": "YOUR_FACE_EVENT_UUID",
"personUuid": "CORRECT_PERSON_UUID"
}'personUuid coincide con una de las mejores coincidencias de persona del evento.Para eliminar un evento por completo, llama a deleteFaceEvent con { "eventUuid": "..." }.
Analíticas de conteo de personas
El conteo de personas es analítica de cámara agregada — cuenta personas sin identificarlas, servida por el servicio de reportes. Úsalo para tráfico de personas, aforo y paneles de tendencias.
Serie temporal de conteo
getCountReportV2 devuelve una serie temporal de conteos agrupados por intervalo. Para el conteo de personas, establece types en ["PEOPLE"].
import requests
import time
headers = {
"x-auth-scheme": "api-token",
"x-auth-apikey": "YOUR_API_KEY",
"Content-Type": "application/json"
}
now_ms = int(time.time() * 1000)
week_ago_ms = now_ms - (7 * 24 * 60 * 60 * 1000)
response = requests.post(
"https://api2.rhombussystems.com/api/report/getCountReportV2",
headers=headers,
json={
"startTimeMs": week_ago_ms,
"endTimeMs": now_ms,
"interval": "DAILY",
"scope": "DEVICE",
"types": ["PEOPLE"],
"uuid": "YOUR_CAMERA_UUID",
"timeZone": "America/Los_Angeles"
}
)
data = response.json()
for point in data.get("timeSeriesDataPoints", []):
counts = point.get("eventCountMap", {})
print(f"{point.get('dateLocal')}: {counts.get('PEOPLE', 0)} people")const now = Date.now();
const weekAgo = now - (7 * 24 * 60 * 60 * 1000);
const response = await fetch('https://api2.rhombussystems.com/api/report/getCountReportV2', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-auth-scheme': 'api-token',
'x-auth-apikey': 'YOUR_API_KEY'
},
body: JSON.stringify({
startTimeMs: weekAgo,
endTimeMs: now,
interval: 'DAILY',
scope: 'DEVICE',
types: ['PEOPLE'],
uuid: 'YOUR_CAMERA_UUID',
timeZone: 'America/Los_Angeles'
})
});
const data = await response.json();
for (const point of data.timeSeriesDataPoints || []) {
const counts = point.eventCountMap || {};
console.log(`${point.dateLocal}: ${counts.PEOPLE || 0} people`);
}curl -X POST https://api2.rhombussystems.com/api/report/getCountReportV2 \
-H "Content-Type: application/json" \
-H "x-auth-scheme: api-token" \
-H "x-auth-apikey: YOUR_API_KEY" \
-d '{
"startTimeMs": 1712016000000,
"endTimeMs": 1712620800000,
"interval": "DAILY",
"scope": "DEVICE",
"types": ["PEOPLE"],
"uuid": "YOUR_CAMERA_UUID",
"timeZone": "America/Los_Angeles"
}'MINUTELY, QUARTERHOURLY, HOURLY, DAILY, WEEKLY, MONTHLY.REGION, DEVICE, LOCATION, ORG.["PEOPLE"] para el conteo de personas.scope es DEVICE). Omítelo para el alcance ORG.America/Los_Angeles).Cada entrada en timeSeriesDataPoints incluye:
{ "PEOPLE": 42 }).getCountReportV2 admite muchos types además de PEOPLE — consulta la guía de Reportes y analíticas para conocer el modelo completo de reportes, endpoints de analítica adicionales y la exportación CSV.
Conteos de ocupación a lo largo del tiempo
getOccupancyCountsV2 devuelve una serie temporal de conteos de ocupación derivados de la cámara para una sola cámara.
import requests
import time
headers = {
"x-auth-scheme": "api-token",
"x-auth-apikey": "YOUR_API_KEY",
"Content-Type": "application/json"
}
now_ms = int(time.time() * 1000)
day_ago_ms = now_ms - (24 * 60 * 60 * 1000)
response = requests.post(
"https://api2.rhombussystems.com/api/report/getOccupancyCountsV2",
headers=headers,
json={
"deviceUuid": "YOUR_CAMERA_UUID",
"startTimeMs": day_ago_ms,
"endTimeMs": now_ms,
"interval": "HOURLY"
}
)
for point in response.json().get("timeSeriesDataPoints", []):
print(f"{point.get('dateLocal')}: {point.get('eventCountMap')}")const now = Date.now();
const dayAgo = now - (24 * 60 * 60 * 1000);
const response = await fetch('https://api2.rhombussystems.com/api/report/getOccupancyCountsV2', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-auth-scheme': 'api-token',
'x-auth-apikey': 'YOUR_API_KEY'
},
body: JSON.stringify({
deviceUuid: 'YOUR_CAMERA_UUID',
startTimeMs: dayAgo,
endTimeMs: now,
interval: 'HOURLY'
})
});
const data = await response.json();
for (const point of data.timeSeriesDataPoints || []) {
console.log(`${point.dateLocal}:`, point.eventCountMap);
}curl -X POST https://api2.rhombussystems.com/api/report/getOccupancyCountsV2 \
-H "Content-Type: application/json" \
-H "x-auth-scheme: api-token" \
-H "x-auth-apikey: YOUR_API_KEY" \
-d '{
"deviceUuid": "YOUR_CAMERA_UUID",
"startTimeMs": 1712534400000,
"endTimeMs": 1712620800000,
"interval": "HOURLY"
}'MINUTELY, QUARTERHOURLY, HOURLY, DAILY, WEEKLY, MONTHLY).Cada punto de datos añade timestampMs y approximateTimestampMsMap a los campos estándar dateUtc, dateLocal, eventCountMap y reportingDevicesMap.
Este reporte de ocupación es derivado de la cámara. Para la presencia en salas medida por sensores de ocupación físicos (Bluetooth/de movimiento), consulta la guía de Sensores IoT — ese es un producto de hardware aparte con su propia API.
Referencia: enums de reportes
| Enum | Valores |
|---|---|
| Tipo de reporte | CROWD, PEOPLE, FACES, MOTION, BANDWIDTH, VEHICLES, LICENSEPLATES, ALERTS, AM_VERIFICATION, DWELL |
| Intervalo | MINUTELY, QUARTERHOURLY, HOURLY, DAILY, WEEKLY, MONTHLY |
| Alcance | REGION, DEVICE, LOCATION, ORG |
Casos de uso
- Alertas de lista de vigilancia — registra personas de interés y luego consulta
findFaceEventsByOrgfiltrando porpersonUuidsolabelspara marcar avistamientos. - Reconciliación de acceso — cruza los eventos faciales con la actividad de control de acceso para confirmar que la persona que usó su credencial coincide con la que vio la cámara.
- Ciclo de calidad del modelo — revisa
topPersonMatchesen eventos de baja confianza, corrígelos conupdateFaceEventy ajustafaceMatchConfidenceThresholdpara equilibrar falsos positivos y omisiones. - Paneles de tráfico de personas — grafica
getCountReportV2contypes: ["PEOPLE"]para tendencias de tráfico diarias u horarias por cámara o ubicación. - Mosaicos de aforo — grafica
getOccupancyCountsV2para una cámara y muestra la ocupación a lo largo del día.
Solución de problemas
Los endpoints de rostros devuelven un error o no están disponibles
El reconocimiento facial es una función licenciada y restringida. Confirma que tu organización esté habilitada y que tu clave de API tenga permisos de administración de rostros. Contacta a tu equipo de cuenta de Rhombus si los endpoints no están disponibles.
uploadFaceMatchmakers rechaza mi archivo
Envía exactamente un archivo por solicitud bajo el nombre de campo de formulario file, mantenlo por debajo de 5 MB y usa .jpg o .png. Deja que tu cliente HTTP defina el límite multipart de Content-Type — no establezcas Content-Type manualmente.
findFaceUploadMetadataByTransaction aún no devuelve nada
Las subidas se procesan de forma asíncrona. Consulta la transacción hasta que cada entrada reporte un valor de success. Cuando success es false, lee errorMsg para conocer el motivo.
No regresan eventos faciales
Si omites timestampFilter, la búsqueda solo cubre los últimos 7 días. Amplía la ventana con rangeStart/rangeEnd (cadenas en milisegundos epoch) y relaja filtros como hasName o personUuids. Recuerda paginar con lastEvaluatedKey.
Demasiadas coincidencias falsas (o muy pocas)
Ajusta faceMatchConfidenceThreshold con updateFaceMatchingConfig. Súbelo (más cerca de 1) para reducir falsos positivos; bájalo para capturar más coincidencias potenciales. Corrige los errores individuales con updateFaceEvent.
Próximos pasos
Modelo completo de reportes de conteo, conteos de cruce de umbral y exportación CSV
Detecta y busca placas de matrícula y vehículos en tus cámaras
Sensores físicos de ocupación, clima y ambientales
Explora y prueba cada endpoint de la API de Rhombus