1 概述
完成 Android 相機(jī)預(yù)覽功能以后,在此基礎(chǔ)上我使用 dlib 與 opencv 庫(kù)做了一個(gè)關(guān)于人臉檢測(cè)的 demo。該 demo 在相機(jī)預(yù)覽過程中對(duì)人臉進(jìn)行實(shí)時(shí)檢測(cè),并將檢測(cè)到的人臉用矩形框描繪出來。具體實(shí)現(xiàn)原理如下:
采用雙層 View,底層的 TextureView 用于預(yù)覽,程序從 TextureView 中獲取預(yù)覽幀數(shù)據(jù),然后調(diào)用 dlib 庫(kù)對(duì)幀數(shù)據(jù)進(jìn)行處理,最后將檢測(cè)結(jié)果繪制在頂層的 SurfaceView 中。
2 項(xiàng)目配置
由于項(xiàng)目中用到了 dlib 與 opencv 庫(kù),因此需要對(duì)其進(jìn)行配置。主要涉及到以下幾個(gè)方面:
2.1 C++支持
在項(xiàng)目創(chuàng)建過程中依次選擇 Include C++ Support、C++11、Exceptions Support ( -fexceptions )以及 Runtime Type Information Support ( -frtti ) 。最后生成的 build.gradle 文件如下:
defaultConfig?{ ?applicationId?"com.example.lightweh.facedetection" ?minSdkVersion?23 ?targetSdkVersion?28 ?versionCode?1 ?versionName?"1.0" ?testInstrumentationRunner?"android.support.test.runner.AndroidJUnitRunner" ?externalNativeBuild?{ ?cmake?{?arguments?"-DCMAKE_BUILD_TYPE=Release" ?cppFlags?"-std=c++11?-frtti?-fexceptions" ?} ?} }
其中,arguments 參數(shù)是后添加上去的,主要用于指定 CMake 的編譯模式為 Release,因?yàn)樵?Debug 模式下 dlib 庫(kù)中相關(guān)算法的運(yùn)行速度非常慢。前期如果需要調(diào)試 C++ 代碼,可先將 arguments 參數(shù)注釋。
2.2 dlib 與 opencv 下載
到dlib官網(wǎng)下載最新版本的源碼,解壓后將文件夾中的dlib目錄復(fù)制到 Android Studio 工程的 cpp 目錄下。
到 sourceforge 下載最新的 opencv-android 庫(kù),解壓后將文件夾中的 native 目錄同樣復(fù)制到 Android Studio 工程的 cpp 目錄下,并改名為 opencv。
2.3 CMakeLists 配置
在 CMakeLists 文件中,我們首先包含 dlib 的 cmake 文件,接下來添加 opencv 的 include 文件夾并引入 opencv 的 so 庫(kù),同時(shí)將 jni_common 目錄中的文件及人臉檢測(cè)相關(guān)文件添加至 native-lib 庫(kù)中,最后進(jìn)行鏈接。
#?設(shè)置native目錄set(NATIVE_DIR?${CMAKE_SOURCE_DIR}/src/main/cpp)#?設(shè)置dlibinclude(${NATIVE_DIR}/dlib/cmake)#?設(shè)置opencv?include文件夾include_directories(${NATIVE_DIR}/opencv/jni/include)#?設(shè)置opencv的so庫(kù)add_library( ?libopencv_java3 ?SHARED ?IMPORTED) set_target_properties( ?libopencv_java3 ?PROPERTIES ?IMPORTED_LOCATION?${NATIVE_DIR}/opencv/libs/${ANDROID_ABI}/libopencv_java3.so)#?將jni_common目錄中所有文件名,存至SRC_LIST中AUX_SOURCE_DIRECTORY(${NATIVE_DIR}/jni_common?SRC_LIST) add_library(?#?Sets?the?name?of?the?library. ?native-lib?#?Sets?the?library?as?a?shared?library. ?SHARED?#?Provides?a?relative?path?to?your?source?file(s). ?${SRC_LIST} ?src/main/cpp/face_detector.h ?src/main/cpp/face_detector.cpp ?src/main/cpp/native-lib.cpp) find_library(?#?Sets?the?name?of?the?path?variable. ?log-lib?#?Specifies?the?name?of?the?NDK?library?that ?#?you?want?CMake?to?locate. ?log) target_link_libraries(?#?Specifies?the?target?library. ?native-lib ?dlib ?libopencv_java3 ?jnigraphics?#?Links?the?target?library?to?the?log?library ?#?included?in?the?NDK. ?${log-lib})#?指定release編譯選項(xiàng)set(CMAKE_C_FLAGS_RELEASE?"${CMAKE_C_FLAGS_RELEASE}?-s?-O3?-Wall")set(CMAKE_CXX_FLAGS_RELEASE?"${CMAKE_CXX_FLAGS_RELEASE}?-s?-O3?-Wall")
由于 C++ 代碼中用到了頭文件 "android/bitmap.h",所以鏈接時(shí)需要添加 jnigraphics 庫(kù)。
3 JNI相關(guān) Java 類定義
3.1 VisionDetRet 類
VisionDetRet 類的相關(guān)對(duì)象主要負(fù)責(zé) C++ 與 Java 之間的數(shù)據(jù)傳遞。
public?final?class?VisionDetRet?{?private?int?mLeft;?private?int?mTop;?private?int?mRight;?private?int?mBottom; ?VisionDetRet()?{}?public?VisionDetRet(int?l,?int?t,?int?r,?int?b)?{ ?mLeft?=?l; ?mTop?=?t; ?mRight?=?r; ?mBottom?=?b; ?}?public?int?getLeft()?{?return?mLeft; ?}?public?int?getTop()?{?return?mTop; ?}?public?int?getRight()?{?return?mRight; ?}?public?int?getBottom()?{?return?mBottom; ?} }
3.2 FaceDet 類
FaceDet 類為 JNI 函數(shù)調(diào)用類,主要定義了一些需要 C++ 實(shí)現(xiàn)的 native 方法。
public?class?FaceDet?{?private?static?final?String?TAG?=?"FaceDet";?//?accessed?by?native?methods ?@SuppressWarnings("unused")?private?long?mNativeFaceDetContext;?static?{?try?{?//?預(yù)加載native方法庫(kù) ?System.loadLibrary("native-lib"); ?jniNativeClassInit(); ?Log.d(TAG,?"jniNativeClassInit?success"); ?}?catch?(UnsatisfiedLinkError?e)?{ ?Log.e(TAG,?"library?not?found"); ?} ?}?public?FaceDet()?{ ?jniInit(); ?}?@Nullable ?@WorkerThread ?public?List<VisionDetRet>?detect(@NonNull?Bitmap?bitmap)?{ ?VisionDetRet[]?detRets?=?jniBitmapDet(bitmap);?return?Arrays.asList(detRets); ?}?@Override ?protected?void?finalize()?throws?Throwable?{?super.finalize(); ?release(); ?}?public?void?release()?{ ?jniDeInit(); ?}?@Keep ?private?native?static?void?jniNativeClassInit();?@Keep ?private?synchronized?native?int?jniInit();?@Keep ?private?synchronized?native?int?jniDeInit();?@Keep ?private?synchronized?native?VisionDetRet[]?jniBitmapDet(Bitmap?bitmap); }
4 Native 方法實(shí)現(xiàn)
4.1 定義 VisionDetRet 類對(duì)應(yīng)的 C++ 類
#include?<jni.h>#define?CLASSNAME_VISION_DET_RET?"com/lightweh/dlib/VisionDetRet"#define?CONSTSIG_VISION_DET_RET?"()V"#define?CLASSNAME_FACE_DET?"com/lightweh/dlib/FaceDet"class?JNI_VisionDetRet?{public: ?JNI_VisionDetRet(JNIEnv?*env)?{?//?查找VisionDetRet類信息 ?jclass?detRetClass?=?env->FindClass(CLASSNAME_VISION_DET_RET);?//?獲取VisionDetRet類成員變量 ?jID_left?=?env->GetFieldID(detRetClass,?"mLeft",?"I"); ?jID_top?=?env->GetFieldID(detRetClass,?"mTop",?"I"); ?jID_right?=?env->GetFieldID(detRetClass,?"mRight",?"I"); ?jID_bottom?=?env->GetFieldID(detRetClass,?"mBottom",?"I"); ?}?void?setRect(JNIEnv?*env,?jobject?&jDetRet,?const?int?&left,?const?int?&top,?const?int?&right,?const?int?&bottom)?{?//?設(shè)置VisionDetRet類對(duì)象jDetRet的成員變量值 ?env->SetIntField(jDetRet,?jID_left,?left); ?env->SetIntField(jDetRet,?jID_top,?top); ?env->SetIntField(jDetRet,?jID_right,?right); ?env->SetIntField(jDetRet,?jID_bottom,?bottom); ?}?//?創(chuàng)建VisionDetRet類實(shí)例 ?static?jobject?createJObject(JNIEnv?*env)?{ ?jclass?detRetClass?=?env->FindClass(CLASSNAME_VISION_DET_RET); ?jmethodID?mid?= ?env->GetMethodID(detRetClass,?"<init>",?CONSTSIG_VISION_DET_RET);?return?env->NewObject(detRetClass,?mid); ?}?//?創(chuàng)建VisionDetRet類對(duì)象數(shù)組 ?static?jobjectArray?createJObjectArray(JNIEnv?*env,?const?int?&size)?{ ?jclass?detRetClass?=?env->FindClass(CLASSNAME_VISION_DET_RET);?return?(jobjectArray)?env->NewObjectArray(size,?detRetClass,?NULL); ?}private: ?jfieldID?jID_left; ?jfieldID?jID_top; ?jfieldID?jID_right; ?jfieldID?jID_bottom; };
4.2 定義人臉檢測(cè)類
人臉檢測(cè)算法需要用大小位置不同的窗口在圖像中進(jìn)行滑動(dòng),然后判斷窗口中是否存在人臉。本文采用的是 dlib 中的是HOG(histogram of oriented gradient)方法對(duì)人臉進(jìn)行檢測(cè),其檢測(cè)效果要好于 opencv。dlib 中同樣提供了 CNN 方法來進(jìn)行人臉檢測(cè),效果好于 HOG,不過需要使用 GPU 加速,不然程序運(yùn)行會(huì)非常慢。
class?FaceDetector?{private: ?dlib::frontal_face_detector?face_detector;?std::vector<dlib::rectangle>?det_rects;public: ?FaceDetector();?//?實(shí)現(xiàn)人臉檢測(cè)算法 ?int?Detect(const?cv::Mat?&image);?//?返回檢測(cè)結(jié)果 ?std::vector<dlib::rectangle>?getDetResultRects(); }; FaceDetector::FaceDetector()?{?//?定義人臉檢測(cè)器 ?face_detector?=?dlib::get_frontal_face_detector(); }int?FaceDetector::Detect(const?cv::Mat?&image)?{?if?(image.empty())?return?0;?if?(image.channels()?==?1)?{ ?cv::cvtColor(image,?image,?CV_GRAY2BGR); ?} ?dlib::cv_image<dlib::bgr_pixel>?dlib_image(image); ?det_rects.clear();?//?返回檢測(cè)到的人臉矩形特征框 ?det_rects?=?face_detector(dlib_image);?return?det_rects.size(); }std::vector<dlib::rectangle>?FaceDetector::getDetResultRects()?{?return?det_rects; }
4.3 native 方法實(shí)現(xiàn)
JNI_VisionDetRet?*g_pJNI_VisionDetRet; JavaVM?*g_javaVM?=?NULL;//?該函數(shù)在加載本地庫(kù)時(shí)被調(diào)用JNIEXPORT?jint?JNI_OnLoad(JavaVM?*vm,?void?*reserved)?{ ?g_javaVM?=?vm; ?JNIEnv?*env; ?vm->GetEnv((void?**)?&env,?JNI_VERSION_1_6);?//?初始化?g_pJNI_VisionDetRet ?g_pJNI_VisionDetRet?=?new?JNI_VisionDetRet(env);?return?JNI_VERSION_1_6; }//?該函數(shù)用于執(zhí)行清理操作void?JNI_OnUnload(JavaVM?*vm,?void?*reserved)?{ ?g_javaVM?=?NULL;?delete?g_pJNI_VisionDetRet; }namespace?{#define?JAVA_NULL?0 ?using?DetPtr?=?FaceDetector?*;?//?用于存放人臉檢測(cè)類對(duì)象的指針,關(guān)聯(lián)Jave層對(duì)象與C++底層對(duì)象(相互對(duì)應(yīng)) ?class?JNI_FaceDet?{ ?public: ?JNI_FaceDet(JNIEnv?*env)?{ ?jclass?clazz?=?env->FindClass(CLASSNAME_FACE_DET); ?mNativeContext?=?env->GetFieldID(clazz,?"mNativeFaceDetContext",?"J"); ?env->DeleteLocalRef(clazz); ?}?DetPtr?getDetectorPtrFromJava(JNIEnv?*env,?jobject?thiz)?{ ?DetPtr?const?p?=?(DetPtr)?env->GetLongField(thiz,?mNativeContext);?return?p; ?}?void?setDetectorPtrToJava(JNIEnv?*env,?jobject?thiz,?jlong?ptr)?{ ?env->SetLongField(thiz,?mNativeContext,?ptr); ?} ?jfieldID?mNativeContext; ?};?//?Protect?getting/setting?and?creating/deleting?pointer?between?java/native ?std::mutex?gLock;?std::shared_ptr<JNI_FaceDet>?getJNI_FaceDet(JNIEnv?*env)?{?static?std::once_flag?sOnceInitflag;?static?std::shared_ptr<JNI_FaceDet>?sJNI_FaceDet;?std::call_once(sOnceInitflag,?[env]()?{ ?sJNI_FaceDet?=?std::make_shared<JNI_FaceDet>(env); ?});?return?sJNI_FaceDet; ?}?//?從java對(duì)象獲取它持有的c++對(duì)象指針 ?DetPtr?const?getDetPtr(JNIEnv?*env,?jobject?thiz)?{?std::lock_guard<std::mutex>?lock(gLock);?return?getJNI_FaceDet(env)->getDetectorPtrFromJava(env,?thiz); ?}?//?The?function?to?set?a?pointer?to?java?and?delete?it?if?newPtr?is?empty ?//?C++對(duì)象new以后,將指針轉(zhuǎn)成long型返回給java對(duì)象持有 ?void?setDetPtr(JNIEnv?*env,?jobject?thiz,?DetPtr?newPtr)?{?std::lock_guard<std::mutex>?lock(gLock); ?DetPtr?oldPtr?=?getJNI_FaceDet(env)->getDetectorPtrFromJava(env,?thiz);?if?(oldPtr?!=?JAVA_NULL)?{?delete?oldPtr; ?} ?getJNI_FaceDet(env)->setDetectorPtrToJava(env,?thiz,?(jlong)?newPtr); ?} }?//?end?unnamespace#ifdef?__cplusplusextern?"C"?{#endif#define?DLIB_FACE_JNI_METHOD(METHOD_NAME)?Java_com_lightweh_dlib_FaceDet_##METHOD_NAMEvoid?JNIEXPORTDLIB_FACE_JNI_METHOD(jniNativeClassInit)(JNIEnv?*env,?jclass?_this)?{}//?生成需要返回的結(jié)果數(shù)組jobjectArray?getRecResult(JNIEnv?*env,?DetPtr?faceDetector,?const?int?&size)?{?//?根據(jù)檢測(cè)到的人臉數(shù)創(chuàng)建相應(yīng)大小的jobjectArray ?jobjectArray?jDetRetArray?=?JNI_VisionDetRet::createJObjectArray(env,?size);?for?(int?i?=?0;?i?<?size;?i++)?{?//?對(duì)檢測(cè)到的每一個(gè)人臉創(chuàng)建對(duì)應(yīng)的實(shí)例對(duì)象,然后插入數(shù)組 ?jobject?jDetRet?=?JNI_VisionDetRet::createJObject(env); ?env->SetObjectArrayElement(jDetRetArray,?i,?jDetRet); ?dlib::rectangle?rect?=?faceDetector->getDetResultRects()[i];?//?將人臉矩形框的值賦給對(duì)應(yīng)的jobject實(shí)例對(duì)象 ?g_pJNI_VisionDetRet->setRect(env,?jDetRet,?rect.left(),?rect.top(), ?rect.right(),?rect.bottom()); ?}?return?jDetRetArray; }JNIEXPORT?jobjectArray?JNICALLDLIB_FACE_JNI_METHOD(jniBitmapDet)(JNIEnv?*env,?jobject?thiz,?jobject?bitmap)?{ ?cv::Mat?rgbaMat; ?cv::Mat?bgrMat; ?jniutils::ConvertBitmapToRGBAMat(env,?bitmap,?rgbaMat,?true); ?cv::cvtColor(rgbaMat,?bgrMat,?cv::COLOR_RGBA2BGR);?//?獲取人臉檢測(cè)類指針 ?DetPtr?mDetPtr?=?getDetPtr(env,?thiz);?//?調(diào)用人臉檢測(cè)算法,返回檢測(cè)到的人臉數(shù) ?jint?size?=?mDetPtr->Detect(bgrMat);?//?返回檢測(cè)結(jié)果 ?return?getRecResult(env,?mDetPtr,?size); }jint?JNIEXPORT?JNICALLDLIB_FACE_JNI_METHOD(jniInit)(JNIEnv?*env,?jobject?thiz)?{ ?DetPtr?mDetPtr?=?new?FaceDetector();?//?設(shè)置人臉檢測(cè)類指針 ?setDetPtr(env,?thiz,?mDetPtr);?return?JNI_OK; }jint?JNIEXPORT?JNICALLDLIB_FACE_JNI_METHOD(jniDeInit)(JNIEnv?*env,?jobject?thiz)?{?//?指針置0 ?setDetPtr(env,?thiz,?JAVA_NULL);?return?JNI_OK; }#ifdef?__cplusplus}#endif
5 Java端調(diào)用人臉檢測(cè)算法
在開啟人臉檢測(cè)之前,需要在相機(jī) AutoFitTextureView 上覆蓋一層自定義 BoundingBoxView 用于繪制檢測(cè)到的人臉矩形框,該 View 的具體實(shí)現(xiàn)如下:
public?class?BoundingBoxView?extends?SurfaceView?implements?SurfaceHolder.Callback?{?protected?SurfaceHolder?mSurfaceHolder;?private?Paint?mPaint;?private?boolean?mIsCreated;?public?BoundingBoxView(Context?context,?AttributeSet?attrs)?{?super(context,?attrs); ?mSurfaceHolder?=?getHolder(); ?mSurfaceHolder.addCallback(this); ?mSurfaceHolder.setFormat(PixelFormat.TRANSPARENT); ?setZOrderOnTop(true); ?mPaint?=?new?Paint(); ?mPaint.setAntiAlias(true); ?mPaint.setColor(Color.RED); ?mPaint.setStrokeWidth(5f); ?mPaint.setStyle(Paint.Style.STROKE); ?}?@Override ?public?void?surfaceChanged(SurfaceHolder?surfaceHolder,?int?format,?int?width,?int?height)?{ ?}?@Override ?public?void?surfaceCreated(SurfaceHolder?surfaceHolder)?{ ?mIsCreated?=?true; ?}?@Override ?public?void?surfaceDestroyed(SurfaceHolder?surfaceHolder)?{ ?mIsCreated?=?false; ?}?public?void?setResults(List<VisionDetRet>?detRets) ?{?if?(!mIsCreated)?{?return; ?} ?Canvas?canvas?=?mSurfaceHolder.lockCanvas();?//清除掉上一次的畫框。 ?canvas.drawColor(Color.TRANSPARENT,?PorterDuff.Mode.CLEAR); ?canvas.drawColor(Color.TRANSPARENT);?for?(VisionDetRet?detRet?:?detRets)?{ ?Rect?rect?=?new?Rect(detRet.getLeft(),?detRet.getTop(),?detRet.getRight(),?detRet.getBottom()); ?canvas.drawRect(rect,?mPaint); ?} ?mSurfaceHolder.unlockCanvasAndPost(canvas); ?} }
同時(shí),需要在布局文件中添加對(duì)應(yīng)的 BoundingBoxView 層,保證與 AutoFitTextureView 完全重合:
<?xml?version="1.0"?encoding="utf-8"?><RelativeLayout?xmlns:android="http://schemas.android.com/apk/res/android" ?xmlns:tools="http://schemas.android.com/tools" ?android:layout_width="match_parent" ?android:layout_height="match_parent" ?tools:context=".CameraFragment"> ?<com.lightweh.facedetection.AutoFitTextureView ?android:id="@+id/textureView" ?android:layout_width="wrap_content" ?android:layout_height="wrap_content" ?android:layout_centerVertical="true" ?android:layout_centerHorizontal="true"?/> ?<com.lightweh.facedetection.BoundingBoxView ?android:id="@+id/boundingBoxView" ?android:layout_width="wrap_content" ?android:layout_height="wrap_content" ?android:layout_alignLeft="@+id/textureView" ?android:layout_alignTop="@+id/textureView" ?android:layout_alignRight="@+id/textureView" ?android:layout_alignBottom="@+id/textureView"?/></RelativeLayout>
BoundingBoxView 添加完成以后,即可在 CameraFragment 中添加對(duì)應(yīng)的人臉檢測(cè)代碼:
private?class?detectAsync?extends?AsyncTask<Bitmap,?Void,?List<VisionDetRet>>?{?@Override ?protected?void?onPreExecute()?{ ?mIsDetecting?=?true;?super.onPreExecute(); ?}?protected?List<VisionDetRet>?doInBackground(Bitmap...?bp)?{ ?List<VisionDetRet>?results;?//?返回檢測(cè)結(jié)果 ?results?=?mFaceDet.detect(bp[0]);?return?results; ?}?protected?void?onPostExecute(List<VisionDetRet>?results)?{?//?繪制檢測(cè)到的人臉矩形框 ?mBoundingBoxView.setResults(results); ?mIsDetecting?=?false; ?} }
然后,分別在 onResume 與 onPause 函數(shù)中完成人臉檢測(cè)類對(duì)象的初始化和釋放:
@Overridepublic?void?onResume()?{?super.onResume(); ?startBackgroundThread(); ?mFaceDet?=?new?FaceDet();?if?(mTextureView.isAvailable())?{ ?openCamera(mTextureView.getWidth(),?mTextureView.getHeight()); ?}?else?{ ?mTextureView.setSurfaceTextureListener(mSurfaceTextureListener); ?} }@Overridepublic?void?onPause()?{ ?closeCamera(); ?stopBackgroundThread();?if?(mFaceDet?!=?null)?{ ?mFaceDet.release(); ?}?super.onPause(); }
最后,在 TextureView 的回調(diào)函數(shù) onSurfaceTextureUpdated 完成調(diào)用:
@Overridepublic?void?onSurfaceTextureUpdated(SurfaceTexture?texture)?{?if?(!mIsDetecting)?{ ?Bitmap?bp?=?mTextureView.getBitmap();?//?保證圖片方向與預(yù)覽方向一致 ?bp?=?Bitmap.createBitmap(bp,?0,?0,?bp.getWidth(),?bp.getHeight(),?mTextureView.getTransform(null),?true?);?new?detectAsync().execute(bp); ?} }
6 測(cè)試結(jié)果
經(jīng)測(cè)試,960x720的 bitmap 圖片在華為手機(jī)(Android 6.0,8核1.2GHz,2G內(nèi)存)上執(zhí)行一次檢測(cè)約耗時(shí)800~850ms。Demo 運(yùn)行效果如下:
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。
網(wǎng)頁題目:Android中使用dlib+opencv實(shí)現(xiàn)動(dòng)態(tài)人臉檢測(cè)-創(chuàng)新互聯(lián)
文章轉(zhuǎn)載:http://jinyejixie.com/article32/djcesc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供Google、虛擬主機(jī)、做網(wǎng)站、電子商務(wù)、網(wǎng)站設(shè)計(jì)公司、網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容