fix: trace debug — show Stranger_NNN for unnamed traces instead of unknown
This commit is contained in:
@@ -1 +1 @@
|
||||
55053
|
||||
17505
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -55,7 +55,7 @@
|
||||
"LIBRARY_PATH" : "/usr/local/lib",
|
||||
"LOGNAME" : "accusys",
|
||||
"MANPATH" : "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/share/man:/Library/Developer/CommandLineTools/usr/share/man:/Library/Developer/CommandLineTools/Toolchains/XcodeDefault.xctoolchain/usr/share/man:",
|
||||
"OLDPWD" : "/Users/accusys",
|
||||
"OLDPWD" : "/Users/accusys/momentry_core_0.1/scripts/swift_processors",
|
||||
"OPENCODE" : "1",
|
||||
"OPENCODE_PID" : "1458",
|
||||
"OPENCODE_PROCESS_ROLE" : "worker",
|
||||
@@ -76,7 +76,7 @@
|
||||
"__CFBundleIdentifier" : "com.googlecode.iterm2",
|
||||
"__CF_USER_TEXT_ENCODING" : "0x1F5:0x0:0x0"
|
||||
},
|
||||
"inputHash" : "3faa9a4477d1e318c5f16d2c9fceb9eebe648921c6297d266ad3a15a6c49f202",
|
||||
"inputHash" : "53f3a379d09ddfa90c5740d510d9e67e676b6f02a47252c63b128688222763ec",
|
||||
"output" : "",
|
||||
"result" : {
|
||||
"exit" : {
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -55,7 +55,7 @@
|
||||
"LIBRARY_PATH" : "/usr/local/lib",
|
||||
"LOGNAME" : "accusys",
|
||||
"MANPATH" : "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/share/man:/Library/Developer/CommandLineTools/usr/share/man:/Library/Developer/CommandLineTools/Toolchains/XcodeDefault.xctoolchain/usr/share/man:",
|
||||
"OLDPWD" : "/Users/accusys",
|
||||
"OLDPWD" : "/Users/accusys/momentry_core_0.1/scripts/swift_processors",
|
||||
"OPENCODE" : "1",
|
||||
"OPENCODE_PID" : "1458",
|
||||
"OPENCODE_PROCESS_ROLE" : "worker",
|
||||
@@ -76,7 +76,7 @@
|
||||
"__CFBundleIdentifier" : "com.googlecode.iterm2",
|
||||
"__CF_USER_TEXT_ENCODING" : "0x1F5:0x0:0x0"
|
||||
},
|
||||
"inputHash" : "01434ad628ddb16c9ce2b957fc96867e99fa6e30223390316f069bf26c365418",
|
||||
"inputHash" : "59cb90e0d1c12f3974d89b55cd41ec8eab762189e688dad1e4943d36a197def4",
|
||||
"output" : "",
|
||||
"result" : {
|
||||
"exit" : {
|
||||
|
||||
Binary file not shown.
@@ -111,48 +111,62 @@ struct SwiftFace: ParsableCommand {
|
||||
return
|
||||
}
|
||||
|
||||
guard let faceObservations = detectReq.results, !faceObservations.isEmpty else {
|
||||
let faceObservations = detectReq.results ?? []
|
||||
let landmarkObservations = lmReq.results ?? []
|
||||
guard !faceObservations.isEmpty || !landmarkObservations.isEmpty else {
|
||||
return
|
||||
}
|
||||
let landmarkObservations = lmReq.results ?? []
|
||||
|
||||
let seconds = CMTimeGetSeconds(actualTime)
|
||||
let frameNumber = Int(seconds * Double(fps))
|
||||
var frameFaces: [[String: Any]] = []
|
||||
|
||||
for (idx, observation) in faceObservations.enumerated() {
|
||||
let bb = observation.boundingBox
|
||||
let faceX = Int(bb.origin.x * CGFloat(width))
|
||||
let faceY = Int((1.0 - bb.origin.y - bb.size.height) * CGFloat(height))
|
||||
let faceW = Int(bb.size.width * CGFloat(width))
|
||||
let faceH = Int(bb.size.height * CGFloat(height))
|
||||
// Use actual CGImage size (may differ from naturalSize after transform)
|
||||
let imgW = CGFloat(cgImage.width)
|
||||
let imgH = CGFloat(cgImage.height)
|
||||
|
||||
// Process landmark observations FIRST (each has bbox + landmarks, self-consistent)
|
||||
for lmObs in landmarkObservations {
|
||||
let bb = lmObs.boundingBox
|
||||
let faceX = Int(bb.origin.x * imgW)
|
||||
let faceY = Int((1.0 - bb.origin.y - bb.size.height) * imgH)
|
||||
let faceW = Int(bb.size.width * imgW)
|
||||
let faceH = Int(bb.size.height * imgH)
|
||||
|
||||
var faceData: [String: Any] = [
|
||||
"bbox": ["x": max(0, faceX), "y": max(0, faceY),
|
||||
"width": faceW, "height": faceH],
|
||||
"confidence": Double(observation.faceCaptureQuality ?? observation.confidence),
|
||||
"confidence": Double(lmObs.confidence),
|
||||
]
|
||||
|
||||
if let yaw = observation.yaw?.doubleValue,
|
||||
let roll = observation.roll?.doubleValue {
|
||||
// Pose from landmark observation
|
||||
if let yaw = lmObs.yaw?.doubleValue,
|
||||
let roll = lmObs.roll?.doubleValue {
|
||||
var poseInfo: [String: Any] = ["roll": roll, "yaw": yaw]
|
||||
if let pitch = observation.pitch?.doubleValue {
|
||||
if let pitch = lmObs.pitch?.doubleValue {
|
||||
poseInfo["pitch"] = pitch
|
||||
}
|
||||
faceData["pose"] = poseInfo
|
||||
}
|
||||
|
||||
if idx < landmarkObservations.count,
|
||||
let lms = landmarkObservations[idx].landmarks {
|
||||
let imgSize = CGSize(width: width, height: height)
|
||||
// Landmarks with Y-flip (macOS image coords: bottom-left -> top-left)
|
||||
if let lms = lmObs.landmarks {
|
||||
let imgSize = CGSize(width: imgW, height: imgH)
|
||||
let leftEye = lms.leftEye?.pointsInImage(imageSize: imgSize) ?? []
|
||||
let rightEye = lms.rightEye?.pointsInImage(imageSize: imgSize) ?? []
|
||||
let nose = lms.nose?.pointsInImage(imageSize: imgSize) ?? []
|
||||
|
||||
if !leftEye.isEmpty || !rightEye.isEmpty || !nose.isEmpty {
|
||||
var lm: [String: [[Double]]] = [:]
|
||||
if !leftEye.isEmpty { lm["left_eye"] = leftEye.map { [Double($0.x), Double($0.y)] } }
|
||||
if !rightEye.isEmpty { lm["right_eye"] = rightEye.map { [Double($0.x), Double($0.y)] } }
|
||||
if !nose.isEmpty { lm["nose"] = nose.map { [Double($0.x), Double($0.y)] } }
|
||||
if !leftEye.isEmpty {
|
||||
lm["left_eye"] = leftEye.map { [Double($0.x), Double(imgH - $0.y)] }
|
||||
}
|
||||
if !rightEye.isEmpty {
|
||||
lm["right_eye"] = rightEye.map { [Double($0.x), Double(imgH - $0.y)] }
|
||||
}
|
||||
if !nose.isEmpty {
|
||||
lm["nose"] = nose.map { [Double($0.x), Double(imgH - $0.y)] }
|
||||
}
|
||||
faceData["landmarks"] = lm
|
||||
}
|
||||
|
||||
@@ -160,8 +174,8 @@ struct SwiftFace: ParsableCommand {
|
||||
let inner = lms.innerLips?.pointsInImage(imageSize: imgSize) ?? []
|
||||
if !outer.isEmpty || !inner.isEmpty {
|
||||
faceData["lips"] = [
|
||||
"outer_lips": outer.map { [Double($0.x), Double($0.y)] },
|
||||
"inner_lips": inner.map { [Double($0.x), Double($0.y)] }
|
||||
"outer_lips": outer.map { [Double($0.x), Double(imgH - $0.y)] },
|
||||
"inner_lips": inner.map { [Double($0.x), Double(imgH - $0.y)] }
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -169,6 +183,48 @@ struct SwiftFace: ParsableCommand {
|
||||
frameFaces.append(faceData)
|
||||
}
|
||||
|
||||
// Output face rect observations that the landmark detector missed.
|
||||
// Match against ALL landmark observations via IoU to avoid duplicates.
|
||||
for faceObs in faceObservations {
|
||||
let fBB = faceObs.boundingBox
|
||||
var matched = false
|
||||
for lmObs in landmarkObservations {
|
||||
let lBB = lmObs.boundingBox
|
||||
let ix = max(fBB.origin.x, lBB.origin.x)
|
||||
let iy = max(fBB.origin.y, lBB.origin.y)
|
||||
let iw = min(fBB.maxX, lBB.maxX) - ix
|
||||
let ih = min(fBB.maxY, lBB.maxY) - iy
|
||||
if iw <= 0 || ih <= 0 { continue }
|
||||
let intersection = iw * ih
|
||||
let union = fBB.width * fBB.height + lBB.width * lBB.height - intersection
|
||||
if intersection / union > 0.3 {
|
||||
matched = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if matched { continue }
|
||||
// Unmatched face rect: output without landmarks
|
||||
let faceX = Int(fBB.origin.x * imgW)
|
||||
let faceY = Int((1.0 - fBB.origin.y - fBB.size.height) * imgH)
|
||||
let faceW = Int(fBB.size.width * imgW)
|
||||
let faceH = Int(fBB.size.height * imgH)
|
||||
|
||||
var faceData: [String: Any] = [
|
||||
"bbox": ["x": max(0, faceX), "y": max(0, faceY),
|
||||
"width": faceW, "height": faceH],
|
||||
"confidence": Double(faceObs.faceCaptureQuality ?? faceObs.confidence),
|
||||
]
|
||||
if let yaw = faceObs.yaw?.doubleValue,
|
||||
let roll = faceObs.roll?.doubleValue {
|
||||
var poseInfo: [String: Any] = ["roll": roll, "yaw": yaw]
|
||||
if let pitch = faceObs.pitch?.doubleValue {
|
||||
poseInfo["pitch"] = pitch
|
||||
}
|
||||
faceData["pose"] = poseInfo
|
||||
}
|
||||
frameFaces.append(faceData)
|
||||
}
|
||||
|
||||
if !frameFaces.isEmpty {
|
||||
allFrames.append([
|
||||
"frame": frameNumber,
|
||||
|
||||
@@ -270,19 +270,19 @@ def process_yolo(
|
||||
|
||||
# Load YOLO model (prefer CoreML for ANE acceleration, fallback to PyTorch)
|
||||
model_path_mlpackage = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)), "..", "yolov5nu.mlpackage"
|
||||
os.path.dirname(os.path.abspath(__file__)), "..", "yolov8s.mlpackage"
|
||||
)
|
||||
model_path_pt = os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)), "..", "yolov5nu.pt"
|
||||
os.path.dirname(os.path.abspath(__file__)), "..", "yolov8s.pt"
|
||||
)
|
||||
if os.path.exists(model_path_mlpackage):
|
||||
model = YOLO(model_path_mlpackage)
|
||||
print("YOLO: CoreML model loaded (4.5x ANE acceleration)")
|
||||
print("YOLO: CoreML model loaded (YOLOv8s, ANE accelerated)")
|
||||
elif os.path.exists(model_path_pt):
|
||||
model = YOLO(model_path_pt)
|
||||
print("YOLO: PyTorch model loaded")
|
||||
print("YOLO: PyTorch model loaded (YOLOv8s)")
|
||||
else:
|
||||
model = YOLO("yolov5nu.pt") # will auto-download
|
||||
model = YOLO("yolov8s.pt") # will auto-download
|
||||
|
||||
# Get video info
|
||||
import cv2
|
||||
|
||||
Reference in New Issue
Block a user