001package net.gdface.sdk;
002
003import java.io.File;
004import java.io.InputStream;
005import java.net.URL;
006import java.nio.ByteBuffer;
007import java.util.List;
008import java.util.Map;
009
010import net.gdface.annotation.DeriveMethod;
011import net.gdface.annotation.GenericParam;
012import net.gdface.image.ImageErrorException;
013import net.gdface.image.MatType;
014
015/**
016 * 
017 * 人脸识别SDK核心接口<br>
018 * 此接口中mat前缀的方法图像数据参数为图像矩阵(要求图像宽高必须为偶数),
019 * 其他方法中所有byte[]类型的图像参数都指未解码的图像格式(如jpg,bmp,png...),<br>
020 * 目前支持的图像格式类型依赖于JDK的支持能力
021 * @author guyadong
022 */
023public interface FaceApi {
024
025        /**
026         * 对人脸图像提取特征码,返回比较相似度结果<br>
027         * imgData1和imgData2相等或imgData2为{@code null}时,即比较同一张图像中的两张人脸的相似度
028         * 调用该方法时假设图像({@code imgData1}和{@code imgData2})能正常解码,<br>
029         * 所以当对图像解码出现异常时,将{@link ImageErrorException}异常对象封装到{@link RuntimeException}抛出<br>
030         * 任何参数为{@code null}则抛出{@link IllegalArgumentException}
031         * @param imgData1
032         *             图像1数据(jpg,png...)字节数组
033         * @param facePos1
034         *            检测到的人脸/眼睛位置
035         * @param imgData2
036         *             图像1数据(jpg,png...)字节数组
037         * @param facePos2
038         *            检测到的人脸/眼睛位置
039         * @return 两张人脸之间的相似度(0.0~1)
040         * @throws NotFaceDetectedException
041         * @throws ImageErrorException
042         * @see #getCodeInfo(byte[], int, CodeInfo[])
043         * @see #compareCode(byte[], byte[])
044         */
045        @DeriveMethod(localResolvedTypes={InputStream.class,URL.class,File.class,ByteBuffer.class})
046        public abstract double compare2Face(
047                        @GenericParam(name="T1")byte[] imgData1, 
048                        CodeInfo facePos1, 
049                        @GenericParam(name="T2")byte[] imgData2, 
050                        CodeInfo facePos2)
051                        throws NotFaceDetectedException, ImageErrorException;
052
053        /**
054         * 对两个图像指定范围({@link FRect})进行人脸检测,找到并提取唯一的人脸特征码,然后比较相似度,返回相似度结果<br>
055         * imgData1和imgData2相等或imgData2为{@code null}时,
056         * 即比较同一张图像中的两张人脸的相似度,这种情况下detectRect1和detectRect2都不能为{@code null}<br>
057         * imgData1和imgData2不相等且都不为{@code null}时,detectRect1和detectRect2被忽略
058         * 
059         * @param imgData1
060         *            图像1数据(jpg,png...)字节数组,为{@code null}则抛出{@link IllegalArgumentException}
061         * @param detectRect1
062         *            图片检测范围,为null时全图检测
063         * @param imgData2
064         *            图像2数据(jpg,png...)字节数组
065         * @param detectRect2
066         *            图片检测范围,为null时全图检测
067         * @return 两张人脸之间的相似度(0.0~1)
068         * @throws ImageErrorException
069         * @throws NotFaceDetectedException
070         * @see #detectAndGetCodeInfo(byte[], int)
071         * @see #compareCode(byte[], byte[])
072         */
073        @DeriveMethod(localResolvedTypes={InputStream.class,URL.class,File.class,ByteBuffer.class})
074        public abstract double detectAndCompare2Face(
075                        @GenericParam(name="T1")byte[] imgData1, 
076                        FRect detectRect1, 
077                        @GenericParam(name="T2")byte[] imgData2, 
078                        FRect detectRect2)
079                        throws ImageErrorException, NotFaceDetectedException;
080
081        /**
082         * 特征码比对<br>
083         * 参数为{@code null}或长度不一致则抛出{@link IllegalArgumentException}异常,返回两个特征码之间的相似度(0.0~1)
084         * @param code1 待比对的特征码
085         * @param code2 待比对的特征码
086         * @return 相似度(0.0~1)
087         */
088        public abstract double compareCode(@GenericParam(name="T1")byte[] code1, @GenericParam(name="T2")byte[] code2);
089
090        /**
091         * 特征码比对1:N<br>
092         * 返回对应的特征码相似度数组
093         * @param code1 待比对的特征码
094         * @param codes 包含人脸特征的{@link CodeInfo }数组
095         * @return 特征码相似度数组
096         */
097        public abstract double[] compareCodes(byte[] code1, CodeInfo[] codes);
098        /**
099         * 特征码比对1:N<br>
100         * 对{@code imgData}图像数据检测人脸并提取特征,然后与{@code code}特征进行比对,
101         * 返回包含比对相似度结果的{@link CompareResult}实例
102         * @param code 人脸特征数据
103         * @param imgData 待比对的图像(jpg,png...)(可能有多张人脸)
104         * @param faceNum  参见 {@link #getCodeInfo(byte[], int, CodeInfo[])}
105         * @return {@link CompareResult}实例
106         * @throws NotFaceDetectedException 没有检测到人脸
107         * @throws ImageErrorException
108         * @see #compareCodes(byte[], CodeInfo[])
109         * @see #detectAndGetCodeInfo(byte[], int)
110         */
111        @DeriveMethod(localResolvedTypes={InputStream.class,URL.class,File.class,ByteBuffer.class})
112        CompareResult compareFaces(
113                        @GenericParam(name="T1")byte[] code, 
114                        @GenericParam(name="T2")byte[] imgData, 
115                        int faceNum)
116        throws NotFaceDetectedException, ImageErrorException;
117
118        /**
119         * 特征码比对1:N<br>
120         * @param code1 人脸特征数据
121         * @param codes 一组人脸特征
122         * @return 返回对应的特征码相似度列表
123         */
124        public abstract List<Double> compareFeatures(byte[] code1, List<byte[]> codes);
125
126        /**
127         * 先对图像数据{@code imgData}进行人脸检测,然后提取人脸特征码<br>
128         * 返回所有成功提取特征码的{@link CodeInfo}数组,
129         * 与{@link #getCodeInfo(byte[], int, CodeInfo[])}的返回结果有差别,返回结果中不包含检测到人脸但提取特征码失败的对象
130         * @param imgData
131         *            图像数据(jpg,png...)字节数组,为{@code null}则抛出{@link IllegalArgumentException}
132         * @param faceNum
133         *            参见 {@link #getCodeInfo(byte[], int, CodeInfo[])}
134         * @return {@link CodeInfo}数组<br>
135         * @throws ImageErrorException
136         * @throws NotFaceDetectedException 没有检测人脸或提取到特征码的人脸数目不是要求的人脸数目(faceNum>0)
137         */
138        @DeriveMethod(localResolvedTypes={InputStream.class,URL.class,File.class,ByteBuffer.class})
139        public abstract CodeInfo[] detectAndGetCodeInfo(byte[] imgData, int faceNum)
140                        throws ImageErrorException, NotFaceDetectedException;
141        /**
142         * 检测指定的人脸是否戴口罩<br>
143         * 返回值有三种状态:
144         * <ul>
145         * <li>{@code true} 戴口罩返回</li>
146         * <li>{@code false} 未戴口罩返回</li>
147         * <li>{@code null} 不知道</li>
148         * </ul>
149         * @param imgData  图像数据(jpg,png...)字节数组,为{@code null}则抛出 {@link IllegalArgumentException} 
150         * @param faceInfo  可见光图像人脸信息
151         * @return 返回口罩检测结果
152         * @throws ImageErrorException 
153         * @since 2.1.9
154         */
155        public Boolean wearMask(byte[] imgData, CodeInfo faceInfo) throws ImageErrorException;
156
157        /**
158         * 对图像({@code imgData})进行人脸检测,返回人脸位置数据对象{@link CodeInfo}数组<br>
159         * 没有检测到人脸则返回空数组
160         * @param imgData
161         *            图像数据(jpg,png...)字节数组,为{@code null}则抛出{@link IllegalArgumentException}
162         * @return {@link CodeInfo}数组
163         * @throws ImageErrorException 图像读取错误
164         */
165        @DeriveMethod(localResolvedTypes={InputStream.class,URL.class,File.class,ByteBuffer.class})
166        public abstract CodeInfo[] detectFace(byte[] imgData) throws ImageErrorException;
167
168        /**
169         * 检测最中心的人脸<br>
170         * 返回人脸位置数据对象{@link CodeInfo}
171         * @param imgData 图像数据(jpg,png...)字节数组,为{@code null}则抛出{@link IllegalArgumentException}
172         * @return {@link CodeInfo}
173         * @throws NotFaceDetected 没有检测到人脸
174         * @throws ImageError 图像读取错误
175         */
176        public CodeInfo detectCenterFace(byte[] imgData) throws NotFaceDetectedException, ImageErrorException;
177        /**
178         * 检测最大的人脸<br>
179         * 返回人脸位置数据对象{@link CodeInfo}
180         * @param imgData 图像数据(jpg,png...)字节数组,为{@code null}则抛出{@link IllegalArgumentException}
181         * @return {@link CodeInfo}
182         * @throws NotFaceDetected 没有检测到人脸
183         * @throws ImageError 图像读取错误
184         */
185        public CodeInfo detectMaxFace(byte[] imgData) throws NotFaceDetectedException, ImageErrorException;
186
187        /**
188         * 根据{@code facePos}提供的人脸信息位置, 在{@code imgData}图像中提取特征码<br>
189         * 与 {@link #detectAndGetCodeInfo(byte[], int)}不同, 本方法不对图像数据{@code imgData}进行人脸检测,<br>
190         * 假设{@code facePos}是 {@link #detectFace(byte[])}或 {@link #detectFaceAgain(byte[], FRect[])} 的返回结果<br>
191         * 返回facePos,如果没有提取到特征码,则对应元素{@link CodeInfo#getCode()}返回{@code null}
192         * @param imgData
193         *           图像数据(jpg,png...)字节数组,为{@code null}则抛出 {@link IllegalArgumentException} 
194         * @param faceNum
195         *            要求返回的人脸特征码数目<br>
196         *            大于0时,如果实际提取到的人脸特征码数目不等于{@code faceNum},则抛出{@link NotFaceDetectedException}<br>
197         *            小于等于0时,返回所有提取到到人脸特征码 
198         * @param facePos
199         *            检测到的人脸位置对象列表<br>
200         *            为{@code null}或数组长度为0时抛出{@link IllegalArgumentException}<br>
201         *            如果元素为{@code null},则跳过<br>
202         * @return 返回facePos
203         * @throws NotFaceDetectedException 提取特征码的人脸数目为0或没有提取到指定数目(faceNum大于0时)的特征码
204         */
205        @DeriveMethod(localResolvedTypes={InputStream.class,URL.class,File.class,ByteBuffer.class})
206        public abstract CodeInfo[] getCodeInfo(byte[] imgData, int faceNum, CodeInfo[] facePos) throws NotFaceDetectedException;
207
208        /**
209         * 根据{@code facePos}提供的人脸信息位置, 在{@code imgData}图像中提取特征码<br>
210         * 返回包含人脸特征的{@link CodeInfo}对象,提取特征失败则返回{@code null}
211         * @param imgData  图像数据(jpg,png...)字节数组,为{@code null}则抛出 {@link IllegalArgumentException} 
212         * @param facePos 人脸位置信息对象,为{@code null}则抛出异常
213         * @return {@link CodeInfo} or {@code null}
214         */
215        @DeriveMethod(methodSuffix="Single",localResolvedTypes={InputStream.class,URL.class,File.class,ByteBuffer.class})
216        public CodeInfo getCodeInfo(byte[] imgData, CodeInfo facePos);
217
218        /**
219         * 多张人脸提取特征(用于多张人脸合成一个特征的算法)<br>
220         * 返回人脸特征数据
221         * {@link #multiFaceFeature()}返回{@code false}时代表此方法未被实现,执行会抛出异常
222         * @param faces 人脸图像数据(jpg,png...)与人脸位置信息对象的映射
223         * @return 人脸特征数据
224         * @throws NotFaceDetectedException 
225         */
226        public abstract byte[] getFeature(Map<ByteBuffer,CodeInfo>faces) throws NotFaceDetectedException;
227        /**
228         * 判断图像是否能提取到人脸特征码<br>
229         * 为{@code true}则能检测到人脸并能提取特征码
230         * @param imgData
231         *            图像数据(jpg,png...)字节数组,为{@code null}则抛出{@link IllegalArgumentException}
232         * @return 为{@code true}则能检测到人脸并能提取特征码
233         * @throws ImageErrorException
234         * @see #detectAndGetCodeInfo(byte[], int)
235         */
236        @DeriveMethod(localResolvedTypes={InputStream.class,URL.class,File.class,ByteBuffer.class})
237        public abstract boolean hasFace(byte[] imgData) throws ImageErrorException;
238
239        /**
240         * 1:N 人脸特征搜索<br>
241         * 搜索与{@code code}相似度大于{@code similarty}的记录(最多返回前{@code rows}个结果)<br>
242         *  返回包含相似度计算结果的{@link FseResult}数组,返回结果以相似度降序排列<br>
243         *  相似度值通过 {@link FseResult#getSimilartys()} 获取<br>
244         *  对应的人脸特征ID由 {@link FseResult#getFeatureIds()}获取
245         * @param feature
246         *            要搜索的特征码
247         * @param similarty
248         *            相似度阀值
249         * @param rows
250         *            最多返回的记录数目
251         * @return 包含相似度计算结果的{@link FseResult}数组<br>
252         * @since 3.0.0
253         * @throws UnsupportedOperationException 没有人脸识别算法(FaceApi实例)支持
254         */
255        public FseResult[] searchFeatures(byte[] feature, double similarty, int rows);
256
257        /**
258         * 1:N 人脸图像搜索<br>
259         * 对{@code facePos}指定的人脸位置提取特征码,然后在数据库中搜索相似的人脸返回搜索结果。<br>
260         * 返回包含相似度计算结果的FseResult数组<br>
261         * 相似度值通过 FseResult.getSimilartys() 获取<br>
262         * 对应的人脸特征ID由 FseResult.getFeatureIds()获取<br>
263         * 
264         * @param imgData
265         *            图片字节数组
266         * @param facePos
267         *            人脸位置对象<br>
268         *            为{@code null}时,先做人脸检测再提取特征码<br>
269         *            不为{@code null}时,直接在指定的位置提取特征码<br>
270         * @param similarty 相似度阀值
271         * @param rows 最多返回的记录数目
272         * @return 包含相似度计算结果的{@link FseResult}数组<br>
273         * @since 3.0.0
274         * @throws NotFaceDetectedException -
275         * @throws ImageErrorException -
276         * @throws UnsupportedOperationException 没有人脸识别算法(FaceApi实例)支持
277         * @see #getCodeInfo(byte[], int, CodeInfo[])
278         * @see #searchFeatures(byte[], double, int)
279         */
280        @DeriveMethod(localResolvedTypes={InputStream.class,URL.class,File.class,ByteBuffer.class})
281        public FseResult[] searchFaces(byte[] imgData, CodeInfo facePos, double similarty, int rows) throws NotFaceDetectedException, ImageErrorException;
282
283        /**
284         * 对图像矩阵进行人脸检测<br>
285         * 返回人脸信息对象列表,没有检测到人脸返回空表
286         * @param matType 图像矩阵类型
287         * @param matData 图像矩阵
288         * @param width 图像宽度
289         * @param height 图像高度
290         * @return 人脸信息对象列表
291         * @since 2.1.9
292         */
293        @DeriveMethod(localResolvedTypes={ByteBuffer.class})
294        public CodeInfo[] matDetectFace(MatType matType, byte[] matData, int width, int height);
295        /**
296         * 检测最大的人脸<br>
297         * 返回人脸位置数据对象{@link CodeInfo}
298         * @param imgData 图像数据(jpg,png...)字节数组,为{@code null}则抛出{@link IllegalArgumentException}
299         * @return {@link CodeInfo}
300         * @throws NotFaceDetected 没有检测到人脸
301         * @since 2.1.9
302         */
303        @DeriveMethod(localResolvedTypes={ByteBuffer.class})
304        public CodeInfo matDetectMaxFace(MatType matType, byte[] matData, int width, int height) throws NotFaceDetectedException;
305        /**
306         * 根据{@code facePos}提供的人脸信息位置, 在图像矩阵中提取特征码<br>
307         * 返回包含人脸特征的{@link CodeInfo}对象,提取特征失败则返回{@code null}
308         * @param matType 图像矩阵类型
309         * @param matData 图像矩阵
310         * @param width 图像宽度
311         * @param height 图像高度
312         * @param facePos 人脸位置信息对象,为{@code null}则抛出异常
313         * @return {@link CodeInfo} or {@code null}
314         */
315        @DeriveMethod(methodSuffix="Single",localResolvedTypes={ByteBuffer.class})
316        public CodeInfo matGetCodeInfo(MatType matType, byte[] matData, int width, int height, CodeInfo facePos);
317
318        /**
319         * 根据facePos提供的人脸信息位置, 在图像矩阵中提取特征码<br>
320         * 包含人脸特征数据的facePos
321         * @param matType 图像矩阵类型
322         * @param matData 图像矩阵
323         * @param width 图像宽度
324         * @param height 图像高度
325         * @param facenum 
326         *            要求返回的人脸特征码数目<br>
327         *            大于0时,如果实际提取到的人脸特征码数目不等于{@code faceNum},则抛出{@link NotFaceDetectedException}<br>
328         *            小于等于0时,返回所有提取到到人脸特征码       
329         * @param facePos 人脸位置信息对象,不可为{@code null}
330         * @return always facePos
331         * @throws NotFaceDetectedException 提取特征码的人脸数目为0或没有提取到指定数目(faceNum大于0时)的特征码
332         * @since 2.1.9
333         */
334        @DeriveMethod(localResolvedTypes={ByteBuffer.class})
335        public CodeInfo[] matGetCodeInfo(MatType matType, byte[] matData, int width, int height, int facenum, CodeInfo[] facePos) throws NotFaceDetectedException;
336        /**
337         * 先对图像矩阵数据{@code imgData}进行人脸检测,然后提取人脸特征码<br>
338         * 返回包含人脸特征数据的{@code CodeInfo}数组
339         * @param matType 图像矩阵类型
340         * @param matData 图像矩阵
341         * @param width 图像宽度
342         * @param height 图像高度
343         * @param faceNum 参见 {@link #getCodeInfo(byte[], int, CodeInfo[])}
344         * @return {@code CodeInfo}数组
345         * @throws NotFaceDetectedException
346         * @since 2.1.9
347         */
348        @DeriveMethod(localResolvedTypes={ByteBuffer.class})
349        public CodeInfo[] matDetectAndGetCodeInfo(MatType matType, byte[] matData, int width, int height, int faceNum)  throws NotFaceDetectedException;
350        /**
351     * 检测指定的人脸是否戴口罩<br>
352         * 返回值有三种状态:
353         * <ul>
354         * <li>{@code true} 戴口罩返回</li>
355         * <li>{@code false} 未戴口罩返回</li>
356         * <li>{@code null} 不知道</li>
357         * </ul>
358         * @param matType 图像矩阵类型
359         * @param matData  图像矩阵
360         * @param width  图像宽度
361         * @param height 图像高度
362         * @param faceInfo  人脸位置信息
363     * @return 返回口罩检测结果
364     * @since 2.1.9
365     */
366        @DeriveMethod(localResolvedTypes={ByteBuffer.class})
367        public Boolean matWearMask(MatType matType, byte[] matData, int width, int height, CodeInfo faceInfo);
368        /**
369         * 判断图像矩阵是否能提取到人脸特征码<br>
370         * 返回为{@code true}则能检测到人脸并能提取特征码
371         * @param matType 图像矩阵类型
372         * @param matData 图像矩阵,为{@code null}则抛出{@link IllegalArgumentException}
373         * @param width  图像宽度
374         * @param height 图像高度
375         * @return 为{@code true}则能检测到人脸并能提取特征码
376         * @since 2.1.9
377         */
378        @DeriveMethod(localResolvedTypes={ByteBuffer.class})
379        boolean matHasFace(MatType matType, byte[] matData, int width, int height);
380
381        /**
382         * 1:N 人脸图像搜索<br>
383         * 对{@code facePos}指定的人脸位置提取特征码,然后在数据库中搜索相似的人脸返回搜索结果。<br>
384         * 返回包含相似度计算结果的FseResult数组<br>
385         * 相似度值通过 FseResult.getSimilartys() 获取<br>
386         * 对应的人脸特征ID由 FseResult.getFeatureIds()获取<br>
387         * @param matType 图像矩阵类型
388         * @param matData 图像矩阵
389         * @param width 图像宽度
390         * @param facePos
391         *            人脸位置对象<br>
392         *            为{@code null}时,先做人脸检测再提取特征码<br>
393         *            不为{@code null}时,直接在指定的位置提取特征码<br>
394         * @param similarty 相似度阀值
395         * @param rows 最多返回的记录数目
396         * @return 包含相似度计算结果的{@link FseResult}数组<br>
397         * @since 3.0.0
398         * @throws NotFaceDetectedException -
399         * @throws ImageErrorException -
400         * @throws UnsupportedOperationException 没有人脸识别算法(FaceApi实例)支持
401         * @see #getCodeInfo(byte[], int, CodeInfo[])
402         * @see #searchFeatures(byte[], double, int)
403         */
404        @DeriveMethod(localResolvedTypes={ByteBuffer.class})
405        public FseResult[] matSearchFaces(MatType matType, byte[] matData, int width, int height, CodeInfo facePos, double similarty, int rows)
406        throws NotFaceDetectedException, ImageErrorException;
407
408        /**
409         * 返回当前SDK特性(能力)描述,已定义字段:<br>
410         * <ul>
411         * <li>SDK_VERSION [string]SDK版本号</li>
412         * <li>MULTI_FACE_FEATURE [boolean]算法是否支持多人脸合成特征</li>
413         * <li>FACE_LIVE [boolean]是否支持活体检测</li>
414         * <li>WEAR_MASK [boolean]是否支持口罩检测</li>
415         * <li>FDDATA_SIZE [int]人脸检测数据的(byte)长度</li>
416         * <li>FEATURE_SIZE [int]人脸特征数据(byte)长度</li>
417         * <li>MAX_FACE_COUNT [int]最大检测人脸数目</li>
418         * <li>FSE_ENABLE [boolean]是否支持特征内存搜索引擎</li>
419         * <li>CODEINFO_RELOCATE [boolean]是否支持CodeInfo对象重定位</li>
420         * <li>LOCAL_DETECT [boolean] 人脸检测是否为本地实现,未定义则为false</li>
421         * </ul>
422         * 以上字段名常量定义参见{@link CapacityFieldConstant}
423         * @return key-value 对描述算法能力的映射
424         * @since 2.2.7
425         */
426        public Map<String, String> sdkCapacity();
427
428        /**
429         * 返回当前接口实现方式<br> 
430         * false WebService类型<br>
431         * true 本地实现
432         * @return boolean
433         */
434        public abstract boolean isLocal();
435}