315 lines
8.5 KiB
Go
315 lines
8.5 KiB
Go
package vqdcms
|
|
|
|
/*
|
|
#cgo linux CFLAGS: -w -I${SRCDIR}/include -fPIC
|
|
#cgo linux CPPFLAGS: -w -I${SRCDIR}/include -fPIC
|
|
#cgo linux LDFLAGS: -Wl,-rpath,'$ORIGIN/./VqdSDK' -rdynamic -ldl
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <dlfcn.h>
|
|
#include "nxu_common.h"
|
|
#include "nxu_vqd_api.h"
|
|
#include "ez_vqd.h"
|
|
|
|
#define LIB_NAME_VQD "libEasyVQD.so"
|
|
|
|
void *g_hDll = NULL;
|
|
typedef int (*vqdLoad)(char *, int , char*);
|
|
typedef int (*vqdUnLoad)();
|
|
typedef int (*vqdCreate)(VideoInfoCVR*);
|
|
typedef int (*vqdDestroy)(VideoInfoCVR*);
|
|
typedef int (*vqdConfig)(VideoInfoCVR, NXU_VQD_Para_S *, int);
|
|
typedef int (*vqdRun)(VideoInfoCVR, int, int, char*, int, char*, int, NXU_VQD_Result_S*);
|
|
|
|
static vqdLoad _vqdLoad = NULL;
|
|
static vqdUnLoad _vqdUnLoad = NULL;
|
|
static vqdCreate _vqdCreate = NULL;
|
|
static vqdDestroy _vqdDestroy = NULL;
|
|
static vqdConfig _vqdConfig = NULL;
|
|
static vqdRun _vqdRun = NULL;
|
|
|
|
int VQDCreate(VideoInfoCVR* handle)
|
|
{
|
|
if (_vqdCreate)
|
|
{
|
|
return _vqdCreate(handle);
|
|
}
|
|
return -99;
|
|
}
|
|
int VQDDestroy(VideoInfoCVR* handle)
|
|
{
|
|
if (_vqdDestroy)
|
|
{
|
|
return _vqdDestroy(handle);
|
|
}
|
|
return -99;
|
|
}
|
|
int VQDConfig(VideoInfoCVR handle, NXU_VQD_Para_S *stPara, int interval)
|
|
{
|
|
if (_vqdConfig)
|
|
{
|
|
return _vqdConfig(handle, stPara, interval);
|
|
}
|
|
return -99;
|
|
}
|
|
int VQDRun(VideoInfoCVR handle, int width, int height, char* data, int frameNum, char* save_filename, int save_filename_size, NXU_VQD_Result_S* out_stResult)
|
|
{
|
|
if (_vqdRun)
|
|
{
|
|
return _vqdRun(handle, width, height, data, frameNum, save_filename, save_filename_size, out_stResult);
|
|
}
|
|
return -99;
|
|
}
|
|
|
|
|
|
void lib_error(char *msg)
|
|
{
|
|
const char* err = dlerror();
|
|
sprintf(msg, "load error[%s]:%s\n", LIB_NAME_VQD, err);
|
|
}
|
|
|
|
int VQDLoad(char *path, int path_size, char *errmsg)
|
|
{
|
|
if (g_hDll)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
char sopath[512] = {0};
|
|
memset(sopath, 0x00, 512);
|
|
sprintf(sopath, "%s/%s", path, LIB_NAME_VQD);
|
|
g_hDll = dlopen(sopath, RTLD_NOW | RTLD_GLOBAL);
|
|
if (g_hDll)
|
|
{
|
|
int ret = 0;
|
|
do
|
|
{
|
|
_vqdLoad = dlsym(g_hDll, "ez_cvr_vqd_load");
|
|
if (_vqdLoad == NULL)
|
|
{
|
|
ret = -3;
|
|
break;
|
|
}
|
|
_vqdUnLoad = dlsym(g_hDll, "ez_cvr_vqd_unload");
|
|
_vqdCreate = dlsym(g_hDll, "ez_cvr_vqd_create");
|
|
_vqdDestroy = dlsym(g_hDll, "ez_cvr_vqd_destroy");
|
|
_vqdConfig = dlsym(g_hDll, "ez_cvr_vqd_config");
|
|
_vqdRun = dlsym(g_hDll, "ez_cvr_vqd_run");
|
|
ret = _vqdLoad(path, path_size, errmsg);
|
|
if (ret != 0)
|
|
{
|
|
return -5;
|
|
}
|
|
}while(0);
|
|
if (ret != 0)
|
|
{
|
|
lib_error(errmsg);
|
|
}
|
|
return ret;
|
|
}
|
|
lib_error(errmsg);
|
|
return -2;
|
|
}
|
|
|
|
int VQDUnLoad()
|
|
{
|
|
if (_vqdUnLoad)
|
|
{
|
|
_vqdUnLoad();
|
|
}
|
|
_vqdUnLoad = NULL;
|
|
if (g_hDll)
|
|
{
|
|
dlclose(g_hDll);
|
|
}
|
|
g_hDll = NULL;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
*/
|
|
import "C"
|
|
|
|
import (
|
|
"fmt"
|
|
"log/slog"
|
|
"path/filepath"
|
|
"unsafe"
|
|
)
|
|
|
|
var (
|
|
vqdInitDLL = false
|
|
)
|
|
|
|
func VQDInit() (err error) {
|
|
if vqdInitDLL {
|
|
return
|
|
}
|
|
cwd, _ := os.Getwd()
|
|
vqdSDKDir := filepath.Join(cwd, "VqdSDK")
|
|
var errmsg [128]C.char
|
|
ret := C.VQDLoad(C.CString(vqdSDKDir), C.int(len(vqdSDKDir)), &errmsg[0])
|
|
if ret != 0 {
|
|
VQDUnInit()
|
|
resBuf1 := (*[128]byte)(unsafe.Pointer(&errmsg[0]))[:128:128]
|
|
slog.Info("vqd cms open", "ret", int(ret), "err", string(resBuf1))
|
|
return fmt.Errorf("[%d]:%s", int(ret), resBuf1)
|
|
}
|
|
vqdInitDLL = true
|
|
slog.Info("vqd cms open ok")
|
|
return
|
|
}
|
|
|
|
func VQDUnInit() {
|
|
C.VQDUnLoad()
|
|
vqdInitDLL = false
|
|
slog.Info("vqd cms stop ok")
|
|
}
|
|
|
|
func (v *VideoInfoVQD) Create(params VQDPara, enable int, interval int) error {
|
|
v.mu.Lock()
|
|
defer v.mu.Unlock()
|
|
v.Params = params
|
|
var stPara C.NXU_VQD_Para_S
|
|
setParams(&stPara, params, enable)
|
|
var handle C.VideoInfoCVR
|
|
ret := int(C.VQDCreate(&handle))
|
|
if ret != 0 {
|
|
return fmt.Errorf("ez_cvr_vqd_create fail:%d", ret)
|
|
}
|
|
v.VQDHandle = uintptr(handle)
|
|
C.VQDConfig((C.VideoInfoCVR)(unsafe.Pointer(v.VQDHandle)), &stPara, C.int(interval))
|
|
v.IsCreateSuccess = true
|
|
return nil
|
|
}
|
|
func (v *VideoInfoVQD) Config(params VQDPara, enable int, interval int) error {
|
|
v.mu.Lock()
|
|
defer v.mu.Unlock()
|
|
if !v.IsCreateSuccess {
|
|
return fmt.Errorf("vqd cms is not create")
|
|
}
|
|
v.Params = params
|
|
var stPara C.NXU_VQD_Para_S
|
|
setParams(&stPara, params, enable)
|
|
ret := int(C.VQDConfig((C.VideoInfoCVR)(unsafe.Pointer(v.VQDHandle)), &stPara, C.int(interval)))
|
|
if ret != 0 {
|
|
return fmt.Errorf("ez_cvr_vqd_config fail:%d", ret)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func setParams(stPara *C.NXU_VQD_Para_S, params VQDPara, enable int) {
|
|
if params.UseDeepLearning {
|
|
stPara.bUseDeepLearning = C.NXU_TRUE
|
|
} else {
|
|
stPara.bUseDeepLearning = C.NXU_FALSE
|
|
}
|
|
|
|
//enable := NXU_VQD_ENABLE_LGTDARK
|
|
// 设置参数
|
|
// 设置亮度检测
|
|
stPara.s32EnableFunc = C.NXU_S32(enable)
|
|
stPara.stLgtDarkPara.f32DarkThr = C.NXU_FLOAT(params.LgtDarkPara.DarkThr)
|
|
stPara.stLgtDarkPara.f32LightThr = C.NXU_FLOAT(params.LgtDarkPara.LightThr)
|
|
stPara.stLgtDarkPara.f32LgtDarkAbnNumRatio = C.NXU_FLOAT(params.LgtDarkPara.LgtDarkAbnNumRatio)
|
|
stPara.s32VecFrmNum = C.int(params.VecFrmNum)
|
|
|
|
//enable |= NXU_VQD_ENABLE_BLUE
|
|
// 设置蓝屏检测
|
|
stPara.stBluePara.f32BlueThr = C.NXU_FLOAT(params.BluePara.BlueThr)
|
|
stPara.stBluePara.f32BlueAbnNumRatio = C.NXU_FLOAT(params.BluePara.BlueAbnNumRatio)
|
|
|
|
//enable |= NXU_VQD_ENABLE_CLARITY
|
|
// 设置清晰度检测
|
|
stPara.stClarityPara.f32ClarityThr = C.NXU_FLOAT(params.ClarityPara.ClarityThr)
|
|
stPara.stClarityPara.f32ClarityAbnNumRatio = C.NXU_FLOAT(params.ClarityPara.ClarityAbnNumRatio)
|
|
|
|
//enable |= NXU_VQD_ENABLE_SHARK
|
|
// 设置抖动检测
|
|
stPara.stSharkPara.f32SharkThr = C.NXU_FLOAT(params.SharkPara.SharkThr)
|
|
stPara.stSharkPara.f32SharkAbnNumRatio = C.NXU_FLOAT(params.SharkPara.SharkAbnNumRatio)
|
|
|
|
//enable |= NXU_VQD_ENABLE_FREEZE
|
|
// 设置冻结检测
|
|
stPara.stFreezePara.f32FreezeThr = C.NXU_FLOAT(params.FreezePara.FreezeThr)
|
|
stPara.stFreezePara.f32FreezeAbnNumRatio = C.NXU_FLOAT(params.FreezePara.FreezeAbnNumRatio)
|
|
|
|
//enable |= NXU_VQD_ENABLE_COLOR
|
|
// 设置偏色检测
|
|
stPara.stColorPara.f32ColorThr = C.NXU_FLOAT(params.ColorPara.ColorThr)
|
|
stPara.stColorPara.f32ColorAbnNumRatio = C.NXU_FLOAT(params.ColorPara.ColorAbnNumRatio)
|
|
|
|
//enable |= NXU_VQD_ENABLE_OCCLUSION
|
|
// 设置遮挡检测
|
|
stPara.stOcclusionPara.f32OcclusionThr = C.NXU_FLOAT(params.OcclusionPara.OcclusionThr)
|
|
stPara.stOcclusionPara.f32OcclusionAbnNumRatio = C.NXU_FLOAT(params.OcclusionPara.OcclusionAbnNumRatio)
|
|
|
|
//enable |= NXU_VQD_ENABLE_NOISE
|
|
// 设置噪声检测参数
|
|
stPara.stNoisePara.f32NoiseThr = C.NXU_FLOAT(params.NoisePara.NoiseThr)
|
|
stPara.stNoisePara.f32NoiseAbnNumRatio = C.NXU_FLOAT(params.NoisePara.NoiseAbnNumRatio)
|
|
|
|
//enable |= NXU_VQD_ENABLE_CONTRAST
|
|
// 设置对比度检测
|
|
stPara.stContrastPara.f32CtraLowThr = C.NXU_FLOAT(params.ContrastPara.CtraLowThr)
|
|
stPara.stContrastPara.f32CtraHighThr = C.NXU_FLOAT(params.ContrastPara.CtraHighThr)
|
|
stPara.stContrastPara.f32CtraAbnNumRatio = C.NXU_FLOAT(params.ContrastPara.CtraAbnNumRatio)
|
|
|
|
//enable |= NXU_VQD_ENABLE_MOSAIC
|
|
// 设置马赛克检测
|
|
stPara.stMosaicPara.f32MosaicThr = C.NXU_FLOAT(params.MosaicPara.MosaicThr)
|
|
stPara.stMosaicPara.f32MosaicAbnNumRatio = C.NXU_FLOAT(params.MosaicPara.MosaicAbnNumRatio)
|
|
|
|
//enable |= NXU_VQD_ENABLE_FLOWER
|
|
// 设置花屏检测
|
|
stPara.stFlowerPara.f32FlowerThr = C.NXU_FLOAT(params.FlowerPara.FlowerThr)
|
|
stPara.stFlowerPara.f32FlowerAbnNumRatio = C.NXU_FLOAT(params.FlowerPara.FlowerAbnNumRatio)
|
|
}
|
|
|
|
func (v *VideoInfoVQD) Frame(data []byte, w, h, frameNum int, save_filename string, outResult *VQDResult) int {
|
|
v.mu.Lock()
|
|
defer v.mu.Unlock()
|
|
if !v.IsCreateSuccess {
|
|
slog.Info("vqd cms is not create")
|
|
return -10
|
|
}
|
|
|
|
result := &C.NXU_VQD_Result_S{}
|
|
yuv := C.CBytes(data)
|
|
defer C.free(yuv)
|
|
filename := C.CString(save_filename)
|
|
defer C.free(unsafe.Pointer(filename))
|
|
ret := int(C.VQDRun((C.VideoInfoCVR)(unsafe.Pointer(v.VQDHandle)), C.int(w), C.int(h), (*C.char)(yuv),
|
|
C.int(frameNum), filename, C.int(len(save_filename)), result))
|
|
if ret == 0 {
|
|
// 分析成功
|
|
outResult.AbnormalType = int(result.s32AbnormalType)
|
|
outResult.ColorDev = float32(result.f32ColorDev)
|
|
outResult.LgtDark = float32(result.f32LgtDark)
|
|
outResult.Clarity = float32(result.f32Clarity)
|
|
outResult.Noise = float32(result.f32Noise)
|
|
outResult.Contrast = float32(result.f32Contrast)
|
|
outResult.Occlusion = float32(result.f32Occlusion)
|
|
outResult.Blue = float32(result.f32Blue)
|
|
outResult.Shark = float32(result.f32Shark)
|
|
outResult.Freeze = float32(result.f32Freeze)
|
|
outResult.Mosaic = float32(result.f32Mosaic)
|
|
outResult.Flower = float32(result.f32Flower)
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func (v *VideoInfoVQD) Destroy() {
|
|
v.mu.Lock()
|
|
defer v.mu.Unlock()
|
|
if !v.IsCreateSuccess {
|
|
slog.Info("vqd cms Destroy fail")
|
|
return
|
|
}
|
|
h := (C.VideoInfoCVR)(unsafe.Pointer(v.VQDHandle))
|
|
v.IsCreateSuccess = false
|
|
C.VQDDestroy(&h)
|
|
}
|