package main /* #cgo CFLAGS: -I${SRCDIR}/sdk/include -w -g #cgo CXXFLAGS: -I${SRCDIR}/sdk/include -w -g -std=c++11 #cgo LDFLAGS: -L/usr/local/cuda-8.0/lib64 -L${SRCDIR}/sdk/lib #cgo LDFLAGS: -Wl,-rpath,${SRCDIR}/sdk/lib #cgo LDFLAGS: -lTHFaceImage -lTHFeature -lTHFaceProperty -lTHFaceTracking #cgo LDFLAGS: -lcudart -lcublas -lcurand -lrt -ldl -lpthread #include #include "cface.h" */ import "C" import ( "errors" "unsafe" "basic.com/libgowrapper/sdkstruct.git" "basic.com/pubsub/protomsg.git" "github.com/gogo/protobuf/proto" ) // SDKFace sdk type SDKFace struct { detector bool extractor bool propertizer bool tracker bool fnLogger func(...interface{}) } // NewSDK sdk func NewSDK(fn func(...interface{})) *SDKFace { return &SDKFace{ detector: false, extractor: false, propertizer: false, tracker: false, fnLogger: fn, } } // Free free func (s *SDKFace) Free() { C.c_api_release() } func (s *SDKFace) printLog(l ...interface{}) { if s.fnLogger != nil { s.fnLogger(l) } } // Detector detector func (s *SDKFace) Detector(minFaces, rollAngle, threadMax, gpu int) bool { if s.detector { return true } ret := C.c_api_face_detector_init(C.int(threadMax), C.int(gpu), C.int(minFaces), C.int(rollAngle)) if ret <= 0 { s.printLog("->face--> CREATE Detector ERROR: ", ret) return false } s.printLog("->face--> CREATE Detector Threads: ", threadMax, " GPU:", gpu) s.detector = true return true } // Extractor ext func (s *SDKFace) Extractor(threadMax, gpu int) bool { if s.extractor { return true } ret := C.c_api_face_extractor_init(C.int(threadMax), C.int(gpu)) if ret <= 0 { s.printLog("->face--> CREATE Extractor ERROR: ", ret) return false } s.printLog("->face--> CREATE Extractor Threads: ", threadMax, " GPU:", gpu) s.extractor = true return true } // Propertizer prop func (s *SDKFace) Propertizer(threadMax int) bool { if s.propertizer { return true } ret := C.c_api_face_property_init(C.int(threadMax)) if ret <= 0 { s.printLog("->face--> CREATE Propertizer ERROR: ", ret) return false } s.printLog("->face--> CREATE Propertizer Threads: ", threadMax) s.propertizer = true return true } // Tracker track func (s *SDKFace) Tracker(w, h, maxFaces, interval, sampleSize, threadMax, gpu int) bool { if s.tracker { return true } ret := C.c_api_face_tracker_init(C.int(threadMax), C.int(gpu), C.int(w), C.int(h), C.int(maxFaces), C.int(interval), C.int(sampleSize)) if ret <= 0 { s.printLog("->face--> CREATE Tracker ERROR: ", ret) return false } s.tracker = true return true } // CFacePosArrayToGoArray convert cFacePos array to go func CFacePosArrayToGoArray(cArray unsafe.Pointer, count int) (goArray []sdkstruct.CFacePos) { p := uintptr(cArray) for i := 0; i < count; i++ { j := *(*sdkstruct.CFacePos)(unsafe.Pointer(p)) goArray = append(goArray, j) p += unsafe.Sizeof(j) } return } // Detect det func (s *SDKFace) Detect(data []byte, w, h, c int, ch int) []sdkstruct.CFacePos { if !s.detector { return nil } var count C.int cfpos := C.c_api_face_detect(&count, (*C.uchar)(unsafe.Pointer(&data[0])), C.int(w), C.int(h), C.int(ch)) if cfpos != nil { defer C.free(unsafe.Pointer(cfpos)) return CFacePosArrayToGoArray(unsafe.Pointer(cfpos), int(count)) } s.printLog("->face--> Detect No One") return nil } // Extract extract func (s *SDKFace) Extract(fpos sdkstruct.CFacePos, data []byte, w, h, c int, ch int) []byte { if !s.extractor { return nil } s.printLog("->face--> facepos: ", fpos) var featLen C.int pos := (*C.cFacePos)(unsafe.Pointer(&fpos)) if pos == nil { return nil } p := C.c_api_face_extract(&featLen, pos, (*C.uchar)(unsafe.Pointer(&data[0])), C.int(w), C.int(h), C.int(ch)) if p != nil { defer C.free(unsafe.Pointer(p)) return C.GoBytes(unsafe.Pointer(p), featLen) } s.printLog("->face--> Extract Nothing") return nil } // Compare face compare func (s *SDKFace) Compare(feat1 []byte, feat2 []byte) float32 { if s.extractor { return 0 } res := C.c_api_face_compare((*C.uchar)(unsafe.Pointer(&feat1[0])), (*C.uchar)(unsafe.Pointer(&feat2[0]))) return float32(res) } // Propertize prop func (s *SDKFace) Propertize(fpos sdkstruct.CFacePos, data []byte, w, h, c int, ch int) sdkstruct.CThftResult { if !s.propertizer { return sdkstruct.CThftResult{Age: 0} } pos := (*C.cFacePos)(unsafe.Pointer(&fpos)) result := C.c_api_face_property(pos, (*C.uchar)(unsafe.Pointer(&data[0])), C.int(w), C.int(h), C.int(ch)) s.printLog("->face--> Propertize") return *(*sdkstruct.CThftResult)(unsafe.Pointer(&result)) } // CFaceInfoArrayToGoArray convert cFaceInfo array to go func CFaceInfoArrayToGoArray(cArray unsafe.Pointer, count int) (goArray []sdkstruct.CFaceInfo) { p := uintptr(cArray) for i := 0; i < count; i++ { j := *(*sdkstruct.CFaceInfo)(unsafe.Pointer(p)) goArray = append(goArray, j) p += unsafe.Sizeof(j) } return } // Track track func (s *SDKFace) Track(data []byte, w, h, c int, ch int) []sdkstruct.CFaceInfo { if !s.tracker { return nil } //img, const int chan, void **fInfo, int *fcnt); var fCount C.int cFinfo := C.c_api_face_track(&fCount, (*C.uchar)(unsafe.Pointer(&data[0])), C.int(w), C.int(h), C.int(ch)) // fmt.Println("cFinfo detected:", cFinfo) if cFinfo == nil { return nil } defer C.free(unsafe.Pointer(cFinfo)) faces := CFaceInfoArrayToGoArray(unsafe.Pointer(cFinfo), int(fCount)) return faces } // FaceInfo2FacePos info -> pos func FaceInfo2FacePos(face sdkstruct.CFaceInfo) (fPos sdkstruct.CFacePos) { fPos.RcFace = face.RcFace fPos.PtLeftEye = face.PtLeftEye fPos.PtRightEye = face.PtRightEye fPos.PtNose = face.PtNose fPos.PtMouth = face.PtMouth fPos.FAngle.Yaw = face.FAngle.Yaw fPos.FAngle.Pitch = face.FAngle.Pitch fPos.FAngle.Roll = face.FAngle.Roll fPos.FAngle.Confidence = face.FAngle.Confidence copy(fPos.PFacialData[:], face.PFacialData[:512]) return fPos } // TrackerResize init face tracker func (s *SDKFace) TrackerResize(w, h, ch int) int { if !s.tracker { s.printLog("->face--> TrackerResize Failed, No Tracker Init") return -1 } return int(C.c_api_face_track_resize(C.int(ch), C.int(w), C.int(h))) } // Run run func (s *SDKFace) Run(data []byte, w, h, c, dchan int) (int, []byte, error) { if data == nil || w <= 0 || h <= 0 { return 0, nil, errors.New("->face--> Face Input Image Error") } if !s.tracker || !s.extractor || !s.propertizer { return 0, nil, errors.New("->face--> Face SDK No Init Correctly") } channel := c if channel == 0 { channel = 3 } var fInfo []sdkstruct.CFaceInfo fInfo = s.Track(data, w, h, c, dchan) if len(fInfo) == 0 { return 0, nil, errors.New("->face--> Face Track No One") } var faces []*protomsg.ResultFaceDetect for _, d := range fInfo { //运行sd dec := FaceInfo2FacePos(d) p := s.Propertize(dec, data, w, h, c, dchan) feat := s.Extract(dec, data, w, h, c, dchan) /// filter rules // sdkid := rMsg.Msg.Tasklab.Sdkinfos[rMsg.Msg.Tasklab.Index].Ipcid // size := (d.RcFace.Right - d.RcFace.Left) * (d.RcFace.Bottom - d.RcFace.Top) // angle := d.FAngle // if !filter(rMsg.Msg.Tasklab.Taskid, sdkid, angle.Confidence, float32(angle.Yaw), int(size)) { // continue // } /// filter rules prop := (*protomsg.ThftResult)(unsafe.Pointer(&p)) fpos := tconvert2ProtoFacePos(d) //组成结果并序列化 res := &protomsg.ResultFaceDetect{Pos: fpos, Result: prop, Feats: feat} faces = append(faces, res) } facePos := protomsg.ParamFacePos{Faces: faces} d, e := proto.Marshal(&facePos) return len(faces), d, e } func tconvert2ProtoFacePos(dec sdkstruct.CFaceInfo) *protomsg.FacePos { crect := dec.RcFace rect := protomsg.Rect{Left: crect.Left, Top: crect.Top, Right: crect.Right, Bottom: crect.Bottom} leftEye := (*protomsg.Point)(unsafe.Pointer(&dec.PtLeftEye)) rightEye := (*protomsg.Point)(unsafe.Pointer(&dec.PtRightEye)) mouth := (*protomsg.Point)(unsafe.Pointer(&dec.PtMouth)) nose := (*protomsg.Point)(unsafe.Pointer(&dec.PtNose)) angle := (*protomsg.FaceAngle)(unsafe.Pointer(&dec.FAngle)) faceID := uint64(dec.NFaceID) facialData := dec.PFacialData[:512] // facialData := make([]byte, 512) // copy(facialData[:], dec.PFacialData[:512]) return &protomsg.FacePos{ RcFace: &rect, PtLeftEye: leftEye, PtRightEye: rightEye, PtMouth: mouth, PtNose: nose, FAngle: angle, Quality: dec.NQuality, FacialData: facialData, FaceID: faceID, } }