All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.gdface.cassdk.BaseJniBridge Maven / Gradle / Ivy

There is a newer version: 2.1.1
Show newest version
package net.gdface.cassdk;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.logging.Logger;

import net.gdface.utils.ResourcePool.IntResourcePool;

public abstract class BaseJniBridge {
	protected static final Logger logger = Logger.getLogger(BaseJniBridge.class.getSimpleName());
	protected static final String CASSDK_HOME = getCassdkHome();
	protected static final int DEFAULT_SAMPLE_SIZE;
	/**
	 * {@link FacePos#facialData} 面部数据长度
	 */
	public static final int FACEPOS_FACIALDATA_LEN = 512;
	protected static final String INVALID_LICENSE = "invalid license";
	protected static final String INVALID_CHANNEL = "nChannelID is invalid or SDK is not initialized";
	protected static final String INVALID_IMAGE = "image data is invalid,please check function parameter:pImage,bpp,nWidth,nHeight";
	protected static final String INVALID_FPS = "pfps or nMaxFaceNums is invalid";
	protected static final String INVALID_PBUF = "pBuf,ptfp,pFeature is NULL";
	/**
	 * 模型数据复制标记,用于保证只在初始化时被执行一次
	 */
	static boolean modelCopyed = false;
	protected static IntResourcePool detectChannelPool;
	protected static IntResourcePool featureChannelPool;
	protected static int maxDetectFaceNum;
	protected static int sampleSize;
	/**
	 * 特征码长度常量
	 */
	public static int FEATURE_SIZE;
	static {
		DEFAULT_SAMPLE_SIZE = CasConfig.getSampleSize();
		maxDetectFaceNum = CasConfig.getMaxDetectFaceNum();
		sampleSize = DEFAULT_SAMPLE_SIZE;
	}
	/**
	 * 复制 CASSDK运行所需的模型数据到Java当前目录user.dir
* 必须定义 cassdk_home变量,用于指定CASSDK的目录位置
* 定义cassdk_home变量的方法 * 1. 定义环境变量CASSDK_HOME * 2. java运行时必须用-D选项定义cassdk_home * 优先在环境变量中查找CASSDK_HOME,如果找不到,再在系统变量定义中查找cassdk_home
* 如果都找不到则抛出异常
* 假定模型数据在${cassdk_home}/bin下 */ protected static final synchronized void copyModelToUserDir() { if(modelCopyed){ return; } File cassdkPath=new File(new File(CASSDK_HOME),"bin"); // 检查 "cassdk_home"的合法性 if(!cassdkPath.exists()||!cassdkPath.isDirectory()){ throw new ExceptionInInitializerError("NOT FOUND FOLDER:".concat(CASSDK_HOME)); } // 根据操作系统类型确定文件复制的目标路径 File destDir; if(System.getProperty("os.name").toLowerCase().startsWith("win")){ // Windows版本SDK的加载数据文件是可执行程序所在路径(java下即JVM程序) final String javaLibraryPath = System.getProperty("java.library.path"); // 以java.library.path中的第一个路径为jvm所在位置 destDir = new File( javaLibraryPath.substring(0, javaLibraryPath.indexOf(';'))); if(!new File(destDir,"java.exe").exists()){ throw new ExceptionInInitializerError("CANT NOT locate JVM folder(无法定位JVM路径)"); } logger.info(String.format("JVM 路径 %s",destDir.toString())); }else{ // linux版本SDK的加载数据文件是用户当前路径 destDir=new File(System.getProperty("user.dir")); } logger.info(String.format("copy model files from %s to %s", cassdkPath.getAbsolutePath(),destDir.getAbsolutePath())); try { // 如果destDir与"cassdk_dir"相等则放弃复制 if(!destDir.getCanonicalPath().equals(cassdkPath.getCanonicalPath())){ for(String file:CasConfig.getVersion().getModelFiles()){ File facedb = new File(cassdkPath,file); if(needCopy(facedb,destDir)){ try{ logger.info(String.format("copy file %s", file)); copyAndDeleteOnExit(facedb,destDir); }catch (RuntimeException e) { if(e.getCause() instanceof IOException){ throw new ExceptionInInitializerError( String.format("无法从\n%s\n复制模型文件(%s)到\n%s\n请手工复制\n因为:%s", cassdkPath.toString(), file, destDir.toString(), e.getMessage())); } throw e; } } } } modelCopyed=true; } catch (Exception e) { throw new ExceptionInInitializerError(e); } } /** * 查找 cassdk_home变量,优先在环境变量中查找CASSDK_HOME,如果找不到,再在系统变量定义中查找cassdk_home
* 如果都找不到则抛出异常 * @return */ static final String getCassdkHome() { String cassdkHome=System.getenv("CASSDK_HOME"); if(null!=cassdkHome){ logger.info(String.format("environment variable CASSDK_HOME=%s", cassdkHome)); }else{ if(null==(cassdkHome=System.getProperty("cassdk_home"))){ throw new ExceptionInInitializerError("UNDEFINED cassdk_home,you can defined the variable by java -Dcassdk_home= OR set environment variable 'CASSDK_HOME'"); } logger.info(String.format("cassdk_home=%s,defined by java -D=", cassdkHome)); } return cassdkHome; } /** * 递归判断文件/文件夹是否需要复制到目标文件夹
* 判断条件:目标不存在或大小不相等,源不存在则返回false * @param src 原文件/文件夹 * @param dstFolder 目标文件夹 */ static final boolean needCopy(final File src, final File dstFolder) { if(null==src||null==dstFolder){ throw new NullPointerException("src or dstFolder is null"); } if(!src.exists()){ return false; } if(!dstFolder.exists()){ return true; } if(src.isDirectory()){ File[] noeq = src.listFiles(new FileFilter(){ @Override public boolean accept(File pathname) { File folder = new File(dstFolder,src.getName()); return needCopy(pathname,folder); }}); return noeq.length>0; }else{ File dst=new File(dstFolder,src.getName()); return (!dst.isFile())||(dst.length()!=src.length()); } } /** * 递归复制文件/文件夹到指定的目录,并且在JVM结束时删除 * @param src 原文件/文件夹 * @param dstFolder 目标文件夹 * @throws RuntimeException {@link IOException}被封装成 {@link RuntimeException}抛出 */ static final void copyAndDeleteOnExit(final File src, final File dstFolder) throws RuntimeException { if(null==src||null==dstFolder){ throw new NullPointerException("src or dstFolder is null"); } if(!src.exists()){ return; } if(src.isDirectory()){ src.listFiles(new FileFilter(){ @Override public boolean accept(File pathname) { File folder = new File(dstFolder,src.getName()); folder.deleteOnExit(); // JVM结束时删除指定文件夹 copyAndDeleteOnExit(pathname,folder); return false; }}); }else{ try { File dst=new File(dstFolder,src.getName()); nioCopyFile(src,dst); // JVM结束时删除文件 dst.deleteOnExit(); } catch (IOException e) { throw new RuntimeException(e); } } } /** * NIO方式复制文件
* 目标文件所在的文件夹如果不存在自动创建文件夹 * @param src 源文件 * @param dst 目标文件 * @throws IOException */ static final void nioCopyFile(File src, File dst) throws IOException { if(null==src||null==dst){ throw new NullPointerException("src or dst is null"); } if(!src.exists()||!src.isFile()){ throw new IllegalArgumentException(String.format("INVALID FIILE NAME(无效文件名) src=%s",src.getCanonicalPath())); } if (dst.exists() &&!dst.isFile()) { throw new IllegalArgumentException(String.format("INVALID FIILE NAME(无效文件名) dst=%s",dst.getCanonicalPath())); } File folder = dst.getParentFile(); if (!folder.exists()){ folder.mkdirs(); } if(((src.length()+(1<<10)-1)>>10)>(folder.getFreeSpace()>>10)){ throw new IOException(String.format("DISK ALMOST FULL(磁盘空间不足) %s",folder.getCanonicalPath())); } FileInputStream fin=null; FileOutputStream fout = null; FileChannel fic = null; FileChannel foc = null; try { fin=new FileInputStream(src); fout = new FileOutputStream(dst); fic = fin.getChannel(); foc = fout.getChannel(); // 1MB缓冲区 ByteBuffer bb = ByteBuffer.allocate(1024<<10); while(fic.read(bb)>0){ bb.flip(); foc.write(bb); bb.clear(); } } finally { // 安全释放资源 if(null!=fic){ fic.close(); } if(null!=foc){ foc.close(); } if(null!=fin){ fin.close(); } if(null!=fout){ fout.close(); } } } /** * * 设置最大可检测人脸的数目,默认为256
* 用于新线程初始化人脸检测结果数据缓冲区大小
* 此值为全局变量,对在此方法调用之后新建的线程有效 * @param maxNum 必须>0,否则抛出异常 * @throws IllegalArgumentException 当maxNum<=0 */ public static synchronized void setMaxDetectFaceNum(int maxNum) { if(maxNum <= 0){ throw new IllegalArgumentException(String.format("Invalid maxNum:%d",maxNum)); } maxDetectFaceNum = maxNum; } public static int getMaxDetectFaceNum() { return maxDetectFaceNum; } public static int getSampleSize() { return sampleSize; } /** * 设置人脸检测时的图像归一化尺寸 * @param sampleSize 为0使用SDK提供的默认尺寸(参见SDK中THFI_DetectFace函数定义),<0则抛出异常 * @throws IllegalArgumentException sampleSize<0 */ public static void setSampleSize(int sampleSize) { if(sampleSize < 0){ throw new IllegalArgumentException(String.format("Invalid sampleSize:%d",sampleSize)); } BaseJniBridge.sampleSize = sampleSize; } protected BaseJniBridge() { } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy