001package net.gdface.sdk.fse; 002 003import java.nio.LongBuffer; 004import java.util.Arrays; 005import java.util.Comparator; 006 007import net.gdface.sdk.FseResult; 008import net.gdface.utils.BufferUtils; 009import net.gdface.utils.BinaryUtils; 010 011/** 012 * 特征码内存对象<br> 013 * 特征码内存JNI内存对象的Java层映射, 014 * 该类实现了{@link Comparable}接口,可以根据相似度结果字段({@link CodeBean#similarity})排序 015 * @author guyadong 016 * 017 */ 018public class CodeBean implements Comparable<CodeBean>{ 019 /** 020 * 特征码ID, 021 * 特征码的MD5校验值(使用MD5保证特征码ID的唯一性) 022 */ 023 public byte[] id=null; 024 /** 025 * 人脸特征码(人脸模板)数据,数据长度与实际应用的算法相关 026 */ 027 public byte[] code=null; 028 /** 029 * 当前特征码所属的图像的MD5校验值(图像ID),可为{@code null}, 030 * 应用层也可将此字段根据业务需要解释为其他含义 031 */ 032 public String imgMD5=null; 033 /** 034 * 相似度比较结果,该字段只在特征码搜索方法返回值中有效。用于当前存储人脸特征方法调用搜索返回结果. 035 * 代表当前特征码与输入搜索人脸特征的相似度比较值。 036 */ 037 public double similarity=0; 038 039 public CodeBean() { 040 } 041 public CodeBean(byte[] id, byte[] code, String imgMD5, Double similarity) { 042 this.id = id; 043 this.code = code; 044 this.imgMD5 = imgMD5; 045 if(similarity != null){ 046 this.similarity = similarity; 047 } 048 } 049 050 @Override 051 public int hashCode() { 052 final int prime = 31; 053 int result = 1; 054 result = prime * result + Arrays.hashCode(code); 055 result = prime * result + Arrays.hashCode(id); 056 result = prime * result + ((imgMD5 == null) ? 0 : imgMD5.hashCode()); 057 return result; 058 } 059 @Override 060 public boolean equals(Object obj) { 061 if (this == obj) 062 return true; 063 if (obj == null) 064 return false; 065 if (!(obj instanceof CodeBean)) 066 return false; 067 CodeBean other = (CodeBean) obj; 068 if (!Arrays.equals(code, other.code)) 069 return false; 070 if (!Arrays.equals(id, other.id)) 071 return false; 072 if (imgMD5 == null) { 073 if (other.imgMD5 != null) 074 return false; 075 } else if (!imgMD5.equals(other.imgMD5)) 076 return false; 077 return true; 078 } 079 @Override 080 public String toString() { 081 return toString(false); 082 } 083 public String toString(boolean full) { 084 String out=String.format("id=[%s],imgMD5=[%s],similarity=%f", BinaryUtils.toHex(id),imgMD5,similarity); 085 if(full){ 086 out+=String.format("\ncode:\n%s\n", null==code?"null":BinaryUtils.toHex(code)); 087 } 088 return out; 089 } 090 @Override 091 public int compareTo(CodeBean o) { 092 double sub = similarity - o.similarity; 093 return sub > 0 ? 1 : (sub < 0 ? -1 : 0); 094 } 095 096 /** 097 * 将{@link #imgMD5}转为应用id(Long),如果{@link #imgMD5}为{@code null}则返回{@code null} 098 * @return 099 */ 100 public Long appLongId(){ 101 return asAppID(imgMD5); 102 } 103 /** 104 * 将{@link #imgMD5}转为应用id(Integer),如果{@link #imgMD5}为{@code null}则返回{@code null} 105 * @return 106 */ 107 public Integer appIntId(){ 108 Long l = asAppID(imgMD5); 109 return l == null ? null : l.intValue(); 110 } 111 /** 112 * 用于相似度排序的{@link Comparator}实例 113 */ 114 public static final Comparator<CodeBean> COMPARATOR = new Comparator<CodeBean>() { 115 @Override 116 public int compare(CodeBean o1, CodeBean o2) { 117 return o1.compareTo(o2); 118 } 119 }; 120 /** 121 * 将Long类型整数转为32位的字符串,用于 {@link #imgMD5}字段 122 * @param appid 123 * @return appid为{@code null}则返回{@code null} 124 */ 125 public static String asImgMD5(long appid){ 126 LongBuffer buffer = LongBuffer.allocate(2).put(0).put(appid); 127 return BinaryUtils.toHex(BufferUtils.asByteArray(buffer.array())); 128 } 129 /** 130 * 从{@link #imgMD5}字段返回Long类型整数, 131 * @param imgMD5 HEX格式(32字节长)的MD5 132 * @return imgMD5为{@code null}则返回{@code null} 133 */ 134 public static Long asAppID(String imgMD5){ 135 if(imgMD5 != null && imgMD5.getBytes().length == 32){ 136 return BufferUtils.asLongArray(BinaryUtils.hex2Bytes(imgMD5))[1]; 137 } 138 return null; 139 } 140 public byte[] getId() { 141 return id; 142 } 143 public void setId(byte[] id) { 144 this.id = id; 145 } 146 public byte[] getCode() { 147 return code; 148 } 149 public void setCode(byte[] code) { 150 this.code = code; 151 } 152 public String getImgMD5() { 153 return imgMD5; 154 } 155 public void setImgMD5(String imgMD5) { 156 this.imgMD5 = imgMD5; 157 } 158 public double getSimilarity() { 159 return similarity; 160 } 161 public void setSimilarity(double similarity) { 162 this.similarity = similarity; 163 } 164 public static final FseResult[] toFseResult(CodeBean[] codeBeans){ 165 if(codeBeans != null){ 166 FseResult[] result = new FseResult[codeBeans.length]; 167 for(int i =0;i<result.length;++i){ 168 result[i] = new FseResult(codeBeans[i].id, codeBeans[i].imgMD5, codeBeans[i].similarity); 169 } 170 return result; 171 } 172 return null; 173 } 174}