基于虹軟服務(wù)器版本(Linux Pro)的人臉識別服務(wù)搭建

項(xiàng)目背景

在人類社會的快速發(fā)展中,科技正深刻地影響著各行各業(yè),其中人工智能技術(shù)尤為突出。特別是人臉識別技術(shù),因其高效、直觀和便捷的特性,在金融、安防、醫(yī)療、零售等多個領(lǐng)域得到了廣泛應(yīng)用。隨著技術(shù)的逐步成熟,人臉識別正在從基礎(chǔ)的身份驗(yàn)證功能,拓展到更深層次的場景需求中,例如行為分析、個性化服務(wù)以及高效管理等。
本項(xiàng)目的背景基于當(dāng)下對智能化、高效化需求的日益增長。傳統(tǒng)身份認(rèn)證方式(如卡片、密碼)存在安全性低、易被遺忘或偽造的問題,已無法滿足某些場景對高安全性與無感化體驗(yàn)的雙重要求。為此,本項(xiàng)目旨在開發(fā)一個服務(wù)端人臉識別系統(tǒng),專注于實(shí)時、高效的人臉檢測與識別能力,為目標(biāo)行業(yè)(如智能安防、醫(yī)療管理或企業(yè)考勤)提供技術(shù)支持和服務(wù)優(yōu)化。

環(huán)境

服務(wù)器:wsl Ubuntu 22.04.3
開發(fā)語言(框架):java SpringBoot
SDK版本:Linux Pro

集成

1、下載sdk
2、將arcsoft-sdk-face-server-1.0.0.0.jar 放入工程lib文件夾
3、引入jar包

    <dependency>
            <groupId>arcsoft-sdk-face-server</groupId>
            <artifactId>arcsoft-sdk-face-server</artifactId>
            <version>1.0.0.0</version>
            <scope>system</scope>
            <systemPath>${pom.basedir}/lib/arcsoft-sdk-face-server-1.0.0.0.jar</systemPath>
        </dependency>

4、將libarcsoft_face.so、libarcsoft_face_engine.so、libarcsoft_face_engine_jni.so放入服務(wù)器/usr/local/arcsoft_lib目錄

引擎池

引擎池的優(yōu)勢:
(1)為了避免頻繁創(chuàng)建和銷毀引擎實(shí)例帶來的開銷
(2)支持高并發(fā)任務(wù)處理,減少系統(tǒng)瓶頸
(3)減少初始化時間,提高系統(tǒng)響應(yīng)速度。
引擎池注意事項(xiàng):
(1)根據(jù)系統(tǒng)的并發(fā)需求、可用資源(如內(nèi)存和CPU)以及引擎實(shí)例的開銷,合理設(shè)置池的最小值和最大值,避免浪費(fèi)系統(tǒng)資源。
(2)每次使用完畢,需及時正確歸還引擎,避免資源被長期占用。

1、創(chuàng)建AFaceEngine繼承FaceEngine,用isCore來標(biāo)識核心引擎,因?yàn)槿四樧缘侥膫€引擎,識別就必須用哪個引擎,核心引擎即用于注冊與識別。
(1)核心引擎:本文使用核心引擎來做人臉注冊和比對,人臉注冊時,使用哪個引擎注冊的,人臉的特征數(shù)據(jù)就保存在哪個引擎中,注冊人臉不適于隨機(jī)使用引擎實(shí)例注冊,否則識別時拿到的引擎若沒有注冊人臉,就會導(dǎo)致人臉識別不到的情況,本文示例核心引擎僅一個,如果需要多個核心引擎可根據(jù)本文邏輯自信擴(kuò)展,注意多個核心引擎注冊人臉時,每個核心引擎都需要注冊。
(2)非核心引擎:非核心引擎可用于做一些與識別和注冊無關(guān)的操作,例如人臉檢測、人臉屬性檢測、特征值提取、圖像質(zhì)量檢測、活體檢測等操作。

public class AFaceEngine extends FaceEngine {
    private boolean isCore;

    public AFaceEngine(Boolean isCore,String libPath){
        super(libPath);
        this.isCore = isCore;
    }
    public AFaceEngine(Boolean isCore,String libPath,String appId, String sdkKey, String activeKey){
        super(libPath);
        this.isCore = isCore;
    }

    public boolean isCore() {
        return isCore;
    }
}

2、引擎工廠FaceEngineFactory,用于創(chuàng)建引擎。
創(chuàng)建引擎時,創(chuàng)建一個核心引擎(可根據(jù)業(yè)務(wù)量控制核心引擎數(shù)量)與多個普通引擎,并激活與初始化所有引擎,核心引擎用于注冊、識別,普通引擎用于人臉檢測、圖像質(zhì)量檢測、活體檢測、屬性識別、特征提取等操作

  @Override
    public PooledObject<AFaceEngine> makeObject() {
        AFaceEngine faceEngine = new AFaceEngine(true,"/usr/local/arcsoft_lib");  // 創(chuàng)建核心對象
        faceEngine.activeOnline(appId,sdkKey,activeKey);
        faceEngine.setLivenessParam(0.5f, 0.7f);
        if (!coreObjectCreated) {
            //因?yàn)楹诵囊鎯H做注冊與識別,為了節(jié)省資源,故此只初始化最近本識別檢測功能
            faceEngine.init(coreEngineConfiguration);
            coreObjectCreated = true;
            System.out.println("Created core FaceEngine.");
        } else {
            //非核心引擎要做人臉各項(xiàng)功能,故單獨(dú)初始化所有功能
            faceEngine.init(engineConfiguration);
            System.out.println("Created regular FaceEngine.");
        }
        return new DefaultPooledObject<>(faceEngine);
    }

完整的FaceEngineFactory引擎工廠

class FaceEngineFactory implements PooledObjectFactory<AFaceEngine> {
    private boolean coreObjectCreated = false;
    private EngineConfiguration engineConfiguration;
    private EngineConfiguration coreEngineConfiguration;
    private String appId;
    private String sdkKey;
    private String activeKey;

    public FaceEngineFactory(EngineConfiguration engineConfiguration, EngineConfiguration coreEngineConfiguration, String appId, String sdkKey, String activeKey){
        super();
        this.engineConfiguration = engineConfiguration;
        this.coreEngineConfiguration = coreEngineConfiguration;
        this.appId = appId;
        this.sdkKey = sdkKey;
        this.activeKey = activeKey;
    }

    @Override
    public PooledObject<AFaceEngine> makeObject() {
        AFaceEngine faceEngine = new AFaceEngine(true,"/usr/local/arcsoft_lib");  // 創(chuàng)建核心對象
        faceEngine.activeOnline(appId,sdkKey,activeKey);
        faceEngine.setLivenessParam(0.5f, 0.7f);
        if (!coreObjectCreated) {
            //因?yàn)楹诵囊鎯H做注冊與識別,為了節(jié)省資源,故此只初始化最近本識別檢測功能
            faceEngine.init(coreEngineConfiguration);
            coreObjectCreated = true;
            System.out.println("Created core FaceEngine.");
        } else {
            //非核心引擎要做人臉各項(xiàng)功能,故單獨(dú)初始化所有功能
            faceEngine.init(engineConfiguration);
            System.out.println("Created regular FaceEngine.");
        }
        return new DefaultPooledObject<>(faceEngine);
    }

    @Override
    public void destroyObject(PooledObject<AFaceEngine> p) {
        p.getObject().unInit();
    }

    @Override
    public boolean validateObject(PooledObject<AFaceEngine> p) {
        return true;
    }

    @Override
    public void activateObject(PooledObject<AFaceEngine> p) {
        System.out.println("Activating FaceEngine.");
    }

    @Override
    public void passivateObject(PooledObject<AFaceEngine> p) {
        System.out.println("Passivating FaceEngine.");
    }

3、創(chuàng)建引擎池CustomFaceEnginePool,用于管理引擎,自定義borrowCoreObject方法,用于借用核心引擎,并設(shè)置maxWaitMillis超時時間。

 // 阻塞等待核心對象歸還
    public AFaceEngine borrowCoreObject(long maxWaitMillis) throws Exception {
        AFaceEngine coreObject = null;
        long startTime = System.currentTimeMillis();
        // 不斷嘗試從池中借用對象
        while (System.currentTimeMillis() - startTime < maxWaitMillis) {
            coreObject = this.borrowObject();
            if (coreObject.isCore()) {
                return coreObject;  // 找到核心對象,返回
            } else {
                // 不是核心對象,立即歸還并繼續(xù)等待
                this.returnObject(coreObject);
            }
            Thread.sleep(100);
        }
        throw new Exception("Timed out waiting for core object.");
    }

為了避免引擎被借出未被正確歸還,需設(shè)計(jì)一個最大借出時間,超時后系統(tǒng)強(qiáng)制歸還引擎
記錄借出時間:

 private final Map<AFaceEngine, Long> borrowedObjects = new ConcurrentHashMap<>();
    private static final long MAX_BORROW_TIME = 10000; // 最大借出時間 10s

  public AFaceEngine borrowObject() throws Exception {
        AFaceEngine engine = super.borrowObject();
        // 記錄借出時間
        borrowedObjects.put(engine, System.currentTimeMillis());
        return engine;
    }

檢查借出引擎是否超時,如果超時強(qiáng)制歸還:

 /**
     * 監(jiān)控借出的對象,檢測超時
     */
    private void monitorBorrowedObjects() {
        while (true) {
            try {
                Thread.sleep(1000); // 每秒掃描一次
                long currentTime = System.currentTimeMillis();
                for (Map.Entry<AFaceEngine, Long> entry : borrowedObjects.entrySet()) {
                    long borrowedTime = currentTime - entry.getValue();
                    if (borrowedTime > MAX_BORROW_TIME) {
                        // 超時強(qiáng)制歸還
                        AFaceEngine engine = entry.getKey();
                        System.err.println("Engine timed out, forcing return: " + engine);
                        borrowedObjects.remove(engine); // 從記錄中移除
                        super.returnObject(engine); // 強(qiáng)制歸還到池中
                    }
                }
            } catch (Exception e) {
                System.err.println("Error in monitor thread: " + e.getMessage());
            }
        }
    }

完整的引擎池CustomFaceEnginePool代碼:

public class CustomFaceEnginePool extends GenericObjectPool<AFaceEngine> {
    // 記錄借出對象及其借出時間
    private final Map<AFaceEngine, Long> borrowedObjects = new ConcurrentHashMap<>();
    private static final long MAX_BORROW_TIME = 10000; // 最大借出時間 10s

    public CustomFaceEnginePool(PooledObjectFactory<AFaceEngine> factory, GenericObjectPoolConfig<AFaceEngine> config) {
        super(factory, config);
        // 啟動監(jiān)控線程
        new Thread(this::monitorBorrowedObjects).start();
    }

    @Override
    public AFaceEngine borrowObject() throws Exception {
        AFaceEngine engine = super.borrowObject();
        // 記錄借出時間
        borrowedObjects.put(engine, System.currentTimeMillis());
        return engine;
    }

    @Override
    public void returnObject(AFaceEngine obj) {
        // 移除借出記錄
        borrowedObjects.remove(obj);
        super.returnObject(obj);
    }

    /**
     * 阻塞等待核心對象歸還
     */
    public AFaceEngine borrowCoreObject(long maxWaitMillis) throws Exception {
        AFaceEngine coreObject = null;
        long startTime = System.currentTimeMillis();
        while (System.currentTimeMillis() - startTime < maxWaitMillis) {
            coreObject = this.borrowObject();
            if (coreObject.isCore()) {
                borrowedObjects.put(coreObject, System.currentTimeMillis());
                return coreObject;
            } else {
                this.returnObject(coreObject);
            }
            Thread.sleep(100);
        }
        throw new Exception("Timed out waiting for core object.");
    }

    /**
     * 監(jiān)控借出的對象,檢測超時
     */
    private void monitorBorrowedObjects() {
        while (true) {
            try {
                Thread.sleep(1000); // 每秒掃描一次
                long currentTime = System.currentTimeMillis();
                for (Map.Entry<AFaceEngine, Long> entry : borrowedObjects.entrySet()) {
                    long borrowedTime = currentTime - entry.getValue();
                    if (borrowedTime > MAX_BORROW_TIME) {
                        // 超時強(qiáng)制歸還
                        AFaceEngine engine = entry.getKey();
                        System.err.println("Engine timed out, forcing return: " + engine);
                        borrowedObjects.remove(engine); // 從記錄中移除
                        super.returnObject(engine); // 強(qiáng)制歸還到池中
                    }
                }
            } catch (Exception e) {
                System.err.println("Error in monitor thread: " + e.getMessage());
            }
        }
    }
}

引擎準(zhǔn)備完成,接下來就是使用引擎進(jìn)行各項(xiàng)人臉操作,本示例實(shí)現(xiàn)了人臉注冊、人臉識別、人臉屬性檢測三個功能,其余擴(kuò)展功能都可根據(jù)本文提供的代碼進(jìn)行擴(kuò)展,本文提供的各項(xiàng)人臉操作均為原子性接口,可根據(jù)實(shí)際需求自由組合。

引擎操作類

1、引擎初始化,根據(jù)文檔配置引擎的各項(xiàng)功能與參數(shù),調(diào)用引擎池進(jìn)行初始化操作

public void init() {
        try {
            //引擎配置
            EngineConfiguration engineConfiguration = new EngineConfiguration();
            EngineConfiguration coreEngineConfiguration = new EngineConfiguration();

            //設(shè)置檢測模式為image
            engineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
            coreEngineConfiguration.setDetectMode(DetectMode.ASF_DETECT_MODE_IMAGE);
            //設(shè)置人臉角度為全角度
            engineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
            coreEngineConfiguration.setDetectFaceOrientPriority(DetectOrient.ASF_OP_ALL_OUT);
            //設(shè)置可檢測最大人臉數(shù)
            engineConfiguration.setDetectFaceMaxNum(1);
            coreEngineConfiguration.setDetectFaceMaxNum(1);
            //設(shè)置人臉識別的模型,ASF_REC_MIDDLE:中等模型,ASF_REC_LARGE:大模型
            engineConfiguration.setFaceModel(FaceModel.ASF_REC_MIDDLE);
            coreEngineConfiguration.setFaceModel(FaceModel.ASF_REC_MIDDLE);
            //功能配置
            FunctionConfiguration functionConfiguration = new FunctionConfiguration();
            //年齡檢測
            functionConfiguration.setSupportAge(true);
            //人臉檢測
            functionConfiguration.setSupportFaceDetect(true);
            //人臉識別
            functionConfiguration.setSupportFaceRecognition(true);
            //性別檢測
            functionConfiguration.setSupportGender(true);
            //活體檢測
            functionConfiguration.setSupportLiveness(true);
            //ir活體檢測
            functionConfiguration.setSupportIRLiveness(true);
            //圖像質(zhì)量檢測
            functionConfiguration.setSupportImageQuality(true);
            //口罩檢測
            functionConfiguration.setSupportMaskDetect(true);
            engineConfiguration.setFunctionConfiguration(functionConfiguration);

            GenericObjectPoolConfig<AFaceEngine> config = new GenericObjectPoolConfig<>();
            config.setMaxTotal(5);
            facePool = new CustomFaceEnginePool(new FaceEngineFactory(engineConfiguration,coreEngineConfiguration,appId,sdkKey,activeKey), config);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

2、加載數(shù)據(jù)庫中所有人臉到引擎

    public void loadAllFace(List<FaceFeatureInfo> faceFeatureInfoList) throws Exception {
        AFaceEngine faceEngine = facePool.borrowCoreObject(5000);
        int i = faceEngine.registerFaceFeature(faceFeatureInfoList);
        log.info("load all face  count:{}", +faceFeatureInfoList.size());
        log.info("load all face  res:{}", +i);
        facePool.returnObject(faceEngine);
    }

注意:此處使用的是facePool.borrowCoreObject(5000),借用核心引擎進(jìn)行l(wèi)oad face,將數(shù)據(jù)控中所有人臉注冊到核心引擎中,使用完畢后立即調(diào)用facePool.returnObject(faceEngine);歸還核心引擎。

3、人臉檢測(普通引擎)

  //人臉檢測
    public ArrayList<FaceInfo> detectFaces(ImageInfo imageInfo) throws Exception {
        ArrayList<FaceInfo> faceInfos = new ArrayList<>();
        AFaceEngine faceEngine = facePool.borrowObject();
        int detectFacesCode = faceEngine.detectFaces(imageInfo, faceInfos);
        log.info("人臉屬性檢測 res:{}", detectFacesCode);
        facePool.returnObject(faceEngine);
        return faceInfos;
    }

4、人臉圖像質(zhì)量檢測,有些圖像雖然可檢測到人臉,但因?yàn)閳D像質(zhì)量較差,無法提取到有效的人臉特征值,所以,提取特征值之前,建議檢測圖像質(zhì)量,僅對達(dá)標(biāo)的圖像進(jìn)行特征值提取,提高效率。

 //圖像質(zhì)量檢測
    public float imageQuality(ImageInfo imageInfo, FaceInfo faceInfo) throws Exception {
        ImageQuality imageQuality = new ImageQuality();
        AFaceEngine faceEngine = facePool.borrowObject();
        int imageQualityCode =faceEngine.imageQualityDetect(imageInfo, faceInfo, 0, imageQuality);
        facePool.returnObject(faceEngine);
        log.info("圖像質(zhì)量檢測 res:{}", imageQualityCode);
        log.info("圖像質(zhì)量檢測分?jǐn)?shù):{}", imageQuality.getFaceQuality());
        return imageQuality.getFaceQuality();
    }

5、人臉屬性檢測

public FaceAttributesResponse faceAttributes(ImageInfo imageInfo, FaceInfo faceInfo) throws Exception {
        FaceAttributesResponse faceAttributesResponse = new FaceAttributesResponse();
        FunctionConfiguration configuration = new FunctionConfiguration();
        configuration.setSupportAge(true);
        configuration.setSupportGender(true);
        configuration.setSupportLiveness(true);
        configuration.setSupportMaskDetect(true);
        ArrayList<FaceInfo> faceInfos = new ArrayList<>();
        faceInfos.add(faceInfo);
        AFaceEngine faceEngine = facePool.borrowObject();
        int faceAttributesCode = faceEngine.process(imageInfo, faceInfos, configuration);
        log.info("圖像屬性處理errorCode:{}", faceAttributesCode);
        //性別檢測
        List<GenderInfo> genderInfoList = new ArrayList<GenderInfo>();
        int genderCode = faceEngine.getGender(genderInfoList);
        log.info("性別 res:{}", +genderCode);
        log.info("性別:{}", +genderInfoList.get(0).getGender());
        faceAttributesResponse.setSex(genderInfoList.get(0).getGender() == 0?"男":"女");
        //年齡檢測
        List<AgeInfo> ageInfoList = new ArrayList<AgeInfo>();
        int ageCode = faceEngine.getAge(ageInfoList);
        log.info("年齡 res:{}", +ageCode);
        log.info("年齡:{}", ageInfoList.get(0).getAge());
        faceAttributesResponse.setAge(String.valueOf(ageInfoList.get(0).getAge()));
        //rgb活體檢測
        List<LivenessInfo> livenessInfoList = new ArrayList<LivenessInfo>();
        int livenCode = faceEngine.getLiveness(livenessInfoList);
        log.info("RGB活體 res:{}", +livenCode);
        log.info("活體:{}", livenessInfoList.get(0).getLiveness());
        faceAttributesResponse.setLive(livenessInfoList.get(0).getLiveness()==0?"非真人":"真人");
        //口罩檢測
        List<MaskInfo> maskInfoList = new ArrayList<MaskInfo>();
        int maskCode = faceEngine.getMask(maskInfoList);
        log.info("口罩 res:{}", +maskCode);
        log.info("口罩:{}", +maskInfoList.get(0).getMask());
        faceAttributesResponse.setMask(maskInfoList.get(0).getMask()==0?"無口罩":"有口罩");
        facePool.returnObject(faceEngine);
        return faceAttributesResponse;
    }

6、IR活體檢測,需要前端傳入雙目攝像頭數(shù)據(jù),包括RGB圖像與IR圖像,對IR圖像進(jìn)行人臉檢測、活體檢測,得到活體結(jié)果后需要判斷與RGB圖像人臉位置的重合度用于初步確認(rèn)兩張圖像為同一張人臉(未實(shí)現(xiàn))。

 public int irLivingDetect(ImageInfo irImg) throws Exception {
        AFaceEngine faceEngine = facePool.borrowObject();
        //IR屬性處理
        List<FaceInfo> faceInfoListGray = new ArrayList<FaceInfo>();
        int irFaceDetectCode = faceEngine.detectFaces(irImg, faceInfoListGray);
        log.info("ir圖像人臉檢測 res:{}", +irFaceDetectCode);
        FunctionConfiguration configuration2 = new FunctionConfiguration();
        configuration2.setSupportIRLiveness(true);
        int irLivingCode = faceEngine.processIr(irImg, faceInfoListGray, configuration2);
        log.info("ir活體檢測 res:{}", +irLivingCode);
        //IR活體檢測
        List<IrLivenessInfo> irLivenessInfo = new ArrayList<>();
        int errorCode = faceEngine.getLivenessIr(irLivenessInfo);
        log.info("獲取ir活體檢測 res:{}", +errorCode);
        facePool.returnObject(faceEngine);
        return irLivenessInfo.get(0).getLiveness();
    }

7、注冊人臉,此操作需使用核心引擎

  public int registerFace(FaceFeatureInfo faceFeatureInfo) throws Exception {
        AFaceEngine faceEngine = facePool.borrowCoreObject(5000);
        int i = faceEngine.registerFaceFeature(faceFeatureInfo);
        facePool.returnObject(faceEngine);
        return i;
    }

8、移除人臉,此處應(yīng)增加數(shù)據(jù)庫的移除操作

  public int removeFace(int searchId) throws Exception {
        AFaceEngine faceEngine = facePool.borrowCoreObject(5000);
        int i = faceEngine.removeFaceFeature(searchId);
        facePool.returnObject(faceEngine);
        return i;
    }

9、更新人臉,此處應(yīng)新增數(shù)據(jù)的更新操作

public int updateFace(FaceFeatureInfo faceFeatureInfo) throws Exception {
        AFaceEngine faceEngine = facePool.borrowCoreObject(5000);
        int i = faceEngine.updateFaceFeature(faceFeatureInfo);
        facePool.returnObject(faceEngine);
        return i;
    }

10、人臉識別(搜索),此操作需使用核心引擎

 public SearchResult searchFace(FaceFeature faceFeature) throws Exception {
        AFaceEngine faceEngine = facePool.borrowCoreObject(5000);
        FaceSearchCount faceSearchCount = new FaceSearchCount();
        faceEngine.getFaceCount(faceSearchCount);
        log.info("引擎庫face count:{}", +faceSearchCount.getCount());
        SearchResult searchResult = new SearchResult();
        int searchCode = faceEngine.searchFaceFeature(faceFeature, CompareModel.LIFE_PHOTO, searchResult);
        log.info("人臉?biāo)阉?res:{}", +searchCode);
        log.info("人臉?biāo)阉?sim:{}", +searchResult.getMaxSimilar());
        facePool.returnObject(faceEngine);
        return searchResult;
    }

注意:人臉識別需傳入CompareModel識別模式,CompareModel.LIFE_PHOTO為生活照識別,即通用的人臉識別;CompareModel.ID_PHOTO為身份證照片識別,針對身份證照片進(jìn)行了特殊優(yōu)化,用于人證比對。
11、提取特征值

  public FaceFeature extractFaceFeature(ImageInfo imageInfo, FaceInfo faceInfo, ExtractType type) throws Exception {
        AFaceEngine faceEngine = facePool.borrowObject();
        FaceFeature faceFeature = new FaceFeature();
        int extractCode = faceEngine.extractFaceFeature(imageInfo, faceInfo, type, 0, faceFeature);
        log.info("特征提取 res:{}", extractCode);
        facePool.returnObject(faceEngine);
        return faceFeature;
    }

注意:特征值提取需要傳入ExtractType,ExtractType.REGISTER表示此特征值將用于注冊操作,ExtractType.RECOGNIZE表示此特征值將用于識別操作。

核心的引擎操作已經(jīng)完成了,接下來就可以自由組合進(jìn)行業(yè)務(wù)上的處理了

人臉注冊(效果圖)

image.png

人臉識別(效果圖)

image.png

人臉屬性檢測(效果圖)

image.png

項(xiàng)目地址:https://gitee.com/wanmaomao/arc-face-for-linux

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容